web-dev-qa-db-ja.com

Immutable.jsのマップで「withMutations」を使用する必要があるのはいつですか?

Immutable.jsマップで一連の突然変異を作成します。

中間の不変マップを作成するよりも、withMutationsを使用することをどの時点で優先すべきですか?

Immutable.jsドキュメントから:

一連の突然変異を適用して新しい不変のマップを作成する必要がある場合、withMutations()は、突然変異の高度なパフォーマンスを適用できる一時的な変更可能なマップのコピーを作成します。実際、これはまさにマージのような複雑な突然変異が行われる方法です。

しかし、行はどこにありますか? 2つの突然変異を行う必要がある場合、withMutationsを使用する必要がありますか?

29
dstreit

オブジェクトの複数の変更をグループ化する場合は、withMutationsを使用する必要があります。

変更ごとにクローンが作成されるため、行内の複数の変更により複数のクローンが作成されます。 withMutationsを使用していくつかの変更を適用し、最後に一度クローンを作成します。すべてのステップでクローンとは、各変更のリスト全体を読んでいることを意味し、n ^ 2操作になります。変更可能なバージョンを使用すると、Nのままになります。

これは、他の答えが示唆するように自由に何かを始めれば、パフォーマンスに大きな打撃を与える可能性があります。キッカーは、小さなデータのテストでは問題ではないかもしれませんが、ライブでプッシュし、100要素のみのテストデータの代わりに300,000個のデータを持つ配列で大規模な操作を行うとどうなりますか?テストデータで、気付かないかもしれない10,000のコピーを作成しました。実稼働環境では、900,000,000,00コピーを実行します。これにより、コンピューターに火がつく可能性があります(実際にはありませんが、タブをフリーズします)。

パフォーマンスの違いを示すデモを作成しました http://jsperf.com/with-out-mutatable

26
Eric Wooley

また、withMutationsとnotのどちらを使用するのが最適かを判断しようとしています。これまで、サイズが不明なnのアイテムのリストをループし、単一のマップでnの変更を実行する必要がある場合、常にwithMutationsを使用していました。例:

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

知りたかったのは、既知の小規模な更新セットでwithMutationsを使用するか、またはsetをチェーンするだけでよいかということです。

例:

setItems(state, items, paging) {
    return state.set('items', items).set('paging', paging);
}

または:

setItems(state, items, paging) {
    return state.withMutations(state => {
        state.set('items', items);
        state.set('paging', paging);
    });
}

この場合、最初のオプション(チェーンset呼び出し)を使用することを好みますが、パフォーマンスへの影響はわかりませんでした。同様のケースをテストするために、このjsPerfを作成しました: http://jsperf.com/immutable-batch-updates-with-mutations

空の初期マップと複雑な初期マップを使用して、2つの更新と100の更新のバッチを実行しました。両方ともwithMutationsを使用し、setをチェーンしているだけです。

結果は、初期マップに関係なく、withMutationsが100更新ケースで常に優れていることを示しているようです。 withMutationsは、空のマップで開始するときの2つの更新ケースでわずかに優れたパフォーマンスを示しました。ただし、複雑なマップで開始する場合、2つのset呼び出しをチェーンするだけでパフォーマンスが向上します。

12
Wade Peterson

中間の不変マップを作成してから、いくつかのプロファイリングツールを使用して、そのアプローチで実際にパフォーマンスの問題があるかどうかを確認します。パフォーマンスの問題が発生する前にパフォーマンスの最適化を行う必要はありません。

経験則として、.map.filterなどwithMutationsをまったく考慮せずに。各要素が変更された新しいリスト(またはマップ)を作成する必要がある場合は、まずその必要性に疑問を持ち、既存のツールと関数型プログラミングスタイルを使用して問題を解決しようとします。それが不可能な場合は、withMutationsを使用してカスタムミューテーションを作成します。

2
OlliM