我的Immutable.js地图上有一系列突变。
我应该在什么时候使用withMutations
而不是创建中间不可变映射?
来自Immutable.js文档:
如果你需要应用一系列突变来产生一个新的不可变的 Map,withMutations()创建Map的临时可变副本 可以以高效的方式应用突变。事实上,这是 确切地说,像合并一样复杂的突变是多么复杂。
但是,这条线在哪里?如果我需要制作两个突变,我应该使用withMutations
?
答案 0 :(得分:25)
如果要对对象进行多项更改,则应使用withMutations。
由于每次更改都会创建一个克隆,因此一行中的多个更改会导致多个克隆。使用withMutations应用多个更改,然后在结束时克隆一次。每个步骤都有一个克隆表示您正在读取每个更改的整个列表,这使其成为n ^ 2操作。使用mutatable版本只需N.
如果您只是像其他答案所暗示的那样开始做事情,这可能会造成巨大的性能损失。踢球者在数据的小测试中可能无关紧要,但是如果您将其推送到现有数据然后在具有300,000个数据的数组上进行大规模操作而不是仅包含100个元素的测试数据会发生什么。在您的测试数据中,您执行了10,000份您可能不会注意到的副本。在生产中你会做900,000,000,00份拷贝,这可能会点燃你的计算机(不是真的,但你会冻结标签)。
我写了一个演示,展示了性能差异http://jsperf.com/with-out-mutatable
答案 1 :(得分:12)
我也一直试图决定什么时候最好使用withMutations而不是。到目前为止,当我需要遍历未知大小string archiveDirectory = ConfigurationManager.AppSettings["ArchiveDirectory"];
if (!string.IsNullOrWhiteSpace(archiveDirectory))
{
archiveDirectory = archiveDirectory.Replace("{foldername}", foldername);
}
的项目列表并在单个地图上执行var regex = new RegExp(/^[\d]{0,9}$/);
突变时,我一直在使用withMutations。
例如:
n
我想知道的是,我是否应该在较小的已知更新集上使用withMutations,或者我应该链接n
。
示例:
updateItems(state, items) {
return state.withMutations(state => {
items.forEach(item => {
state.set(item.get('id'), item);
});
});
}
或者:
set
在这种情况下,我更喜欢使用第一个选项(链式setItems(state, items, paging) {
return state.set('items', items).set('paging', paging);
}
调用),但我不确定性能影响。我创建了这个jsPerf来测试一些类似的案例:http://jsperf.com/immutable-batch-updates-with-mutations。
我使用空的初始地图和复杂的初始地图运行了批量的2次更新和100次更新,两者都使用setItems(state, items, paging) {
return state.withMutations(state => {
state.set('items', items);
state.set('paging', paging);
});
}
并且只链接set
。
结果似乎表明,无论初始地图如何,{100}更新案例总是更好withMutations
。当从空地图开始时,{2}在2更新案例上的表现稍微好一点。但是,在开始使用复杂地图时,只需链接2 set
次调用就可以了。
答案 2 :(得分:2)
我只是创建中间不可变映射,然后使用一些分析工具来检查您是否确实遇到了该方法的任何性能问题。在遇到性能问题之前,无需进行性能优化。
根据经验,我更喜欢使用现有功能,例如.map
,.filter
等,而不考虑withMutations
。如果需要创建一个新的List(或Map),其中每个元素都会发生变异,我首先会质疑这种需求并尝试使用现有工具和函数式编程风格来解决问题。如果那是不可能的,我会用withMutations
创建一个自定义变异。