什么时候应该在Immutable.js的地图上使用`withMutations`?

dst*_*eit 29 immutable.js

我在Immutable.js地图上有一系列突变.

我应该在什么时候使用withMutations而不是创建中间不可变映射?

来自Immutable.js文档:

如果您需要应用一系列突变来生成新的不可变Map,withMutations()会创建Map的临时可变副本,该副本可以高性能的方式应用突变.事实上,这正是像合并一样复杂的突变.

但是,线路在哪里?如果我需要制作两个突变,我应该使用withMutations吗?

Eri*_*ley 27

如果要对对象进行多个更改分组,则应使用withMutations.

由于每个更改都会创建一个克隆,因此连续的多个更改会导致多个克隆.使用withMutations应用多个更改,然后在结束时克隆一次.每个步骤都有一个克隆表示您正在读取每个更改的整个列表,这使其成为n ^ 2操作.使用mutatable版本只需N即可.

如果你只是像其他答案所暗示的那样开始做事情,这可能会造成巨大的性能损失.踢球者在数据的小测试中可能无关紧要,但是如果您将其推送到现有数据然后在具有300,000个数据的数组上进行大规模操作而不是仅包含100个元素的测试数据会发生什么.在您的测试数据中,您执行了10,000份您可能不会注意到的副本.在生产中你会做900,000,000,00份拷贝,这可能会点燃你的计算机(不是真的,但你会冻结标签).

我写了一个演示,演示了性能差异http://jsperf.com/with-out-mutatable

  • 这个答案有点不正确.每次修改时,ImmutableJS都不会克隆整个数据结构.它确实创建了一个新对象,但它不会复制所有数据,因此对于n次操作,它可以比"O(n ^ 2)"更好.例如`list.push()`需要恒定的时间,因此调用`list = list.push(x)`n次将需要'O(n)'时间.https://facebook.github.io/immutable-js/docs/#/List你仍然可以通过`withMutations`获得一些额外的性能,但你可能不会降低算法的复杂性. (3认同)
  • 您的性能测试是错误的:您在一个列表中进行了10 000次突变.如果你需要这样做,那么一定要使用withMutations.更现实的情况是将5个突变列入包含10 000个项目的列表中. (2认同)

小智 12

我也一直试图决定什么时候最好使用withMutations而不是.到目前为止,当我需要遍历未知大小的项目列表nn在单个地图上执行突变时,我一直在使用withMutations .例:

updateItems(state, items) {
    return state.withMutations(state => {
        items.forEach(item => {
            state.set(item.get('id'), item);
         });
    });
}
Run Code Online (Sandbox Code Playgroud)

我想知道的是,如果我应该在一个较小的已知更新集上使用withMutations,或者我应该链接set.

例:

setItems(state, items, paging) {
    return state.set('items', items).set('paging', paging);
}
Run Code Online (Sandbox Code Playgroud)

要么:

setItems(state, items, paging) {
    return state.withMutations(state => {
        state.set('items', items);
        state.set('paging', paging);
    });
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我更喜欢使用第一个选项(链式set调用),但我不确定性能影响.我创建了这个jsPerf来测试一些类似的情况:http://jsperf.com/immutable-batch-updates-with-mutations .

我运行了2次更新和100次更新,使用空的初始地图和复杂的初始地图,使用withMutations和链接set.

结果似乎表明withMutations,无论初始地图如何,在100更新案例中总是更好.withMutations当以空地图开始时,在2更新情况下执行略微更好.但是,set从复杂的地图开始,仅仅链接2个调用的效果更好.

  • 我可能太晚来参加这个派对,但是在第一种情况下链接`set`方法是在每次方法调用后创建一个新副本,而在第二种情况下,它只被克隆一次. (2认同)

Oll*_*liM 1

我只会创建中间不可变映射,然后使用一些分析工具来检查该方法是否确实存在任何性能问题。在出现性能问题之前无需进行性能优化。

根据经验,我更喜欢使用现有的功能.map,例如.filter等,而不考虑withMutations. 如果需要创建一个新的列表(或映射),其中每个元素都发生变化,我会首先质疑这种需要,并尝试使用现有的工具和函数式编程风格来解决问题。如果这是不可能的,我会使用withMutations.