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
}

