Klasa Map z pakietu immutable jest obecnie popularnie wybierana jako kontener dla globalnego stanu w aplikacjach wykorzystujących redux.
Zauważyłem też że powszechną, ale błędną, praktyką jest modyfikowanie wielu pól przy pomocy łańcucha poleceń set.
const newState = oldState .set('field1', 'value1') .set('field2', 'value2') .set('field3', 'value3');
Podejście to sprawia, że za każdym wywołaniem metody set tworzona jest nowa, na szczęście płytka, kopia mapy ze zmienionym jednym polem.
Poprawę wydajności można uzyskać wykorzystując metodę withMutations.
const newState = oldState.withMutations(map => { map .set('field1', 'value1') .set('field2', 'value2') .set('field3', 'value3'); });
Mierz wyniki
Użycie tej metody nie gwarantuje jednak poprawy wydajności. Poniższy test zawiera 2 skraje przypadki użycia obu podejść:
const Map = require('immutable').Map; const { performance } = require('perf_hooks'); function test(tested) { const before = performance.now(); for (let i = 0; i < 1000; i++) { tested(); } return performance.now() - before; } let map = new Map(); const mapSet1 = test(function() { map.set("field1", "value"); }); map = new Map(); const mapWithMutations1 = test(function() { map.withMutations(map2 => { map2.set("field1", "value"); }) }); map = new Map(); const mapSet2 = test(function() { map .set("field1", "value1") .set("field2", "value2") .set("field3", "value3") .set("field4", "value4") .set("field5", "value5") .set("field6", "value6") .set("field7", "value7") .set("field8", "value8") .set("field9", "value9"); }); map = new Map(); const mapWithMutations2 = test(function() { map.withMutations(map2 => { map2.set("field1", "value1"); map2.set("field2", "value2"); map2.set("field3", "value3"); map2.set("field4", "value4"); map2.set("field5", "value5"); map2.set("field6", "value6"); map2.set("field7", "value7"); map2.set("field8", "value8"); map2.set("field9", "value9"); }) }); console.log({ mapSet1, mapWithMutations1, mapSet2, mapWithMutations2 });
Na mojej maszynie uzyskałem następujący wynik:
{ mapSet1: 0.9362990260124207, mapWithMutations1: 1.4729009866714478, mapSet2: 23.789600014686584, mapWithMutations2: 13.4621000289917 }