You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I did a little experiment + benchmarks and wanted to share the results just FYI. Because of the FYI character of this, I created a discussion instead of an issue.
We could improve the performance of all our reducers by 3 to 4 times by just switching libraries.
Intro
Immer.js is the library on which all our reducers rely.
Its produce-method "converts" mutable reducers (the input value is mutated) into immutable ones (the input values are not mutated, and instead, a new copy with the changes is returned).
One alternative to immer.js is mutative. It has fewer features and bit different names, but aims to be more performant than immer.js.
Setup
I replaced produce from immer with create from mutable (d8d3869 and 02e3ac8). This was basically a drop-in replacement, as we didn't use any of the advanced features of immer.
Test Setup:
OS: Windows 11 Pro 10.0.22621
CPUs: 12 × AMD Ryzen 5 5600X 6-Core Processor
RAM: 16309MB
Node.js: v16.19.0
Every action and state was deep frozen before being passed to the produce/create function. Immer.js basically has to be used with autoFreeze as it uses this as an internal flag to determine wether something can be shallow copied or must be deep copied (big perfromance drop when disabling it).
These tested states had <50 patients/vehicles/personnel. It could be that the results for more extreme cases is different.
The accumulated time for each action per type of action is shown in the tables below.
workshop-babz-großes-szenario
Category
immerjs in ms
mutative in ms
mutative no freeze in ms
[Exercise] Tick
4992.40
1182.54
1118.59
[Patient] Move patient
215.10
76.10
72.26
[Personnel] Move personnel
177.14
54.31
50.55
[Transfer] Edit transfer
12.10
1.46
1.23
[Material] Move material
93.12
29.41
27.41
workshop-malteser-großes-szenario
Category
immerjs in ms
mutative in ms
mutative no freeze in ms
[Exercise] Tick
3888.56
905.00
853.14
[Patient] Move patient
110.12
41.11
39.11
[Personnel] Move personnel
74.68
24.49
23.02
[Transfer] Edit transfer
47.81
6.42
5.14
[Material] Move material
29.60
9.82
9.25
The [Exercise] Tick-action changes in every patient at least one property (health). In contrast, all other actions change only one property of one patient/personnel/material and potentially some stuff in the R-Trees.
Total accumulated time to process all actions
For runtime performance (on the server and client) the newImmerDraft-benchmark is relevant.
The noImmerDraft-benchmark is the baseline, without any overhead for mutability. It is impossible for the newImmerDraft-benchmark to be faster than the noImmerDraft-benchmark.
exercise
immerjs in ms
mutative in ms
mutative no freeze in ms
noImmerDraft in ms
small-demo
534
128
134
6
workshop-babz-großes-szenario
5780
1465
1487
80
workshop-malteser-großes-szenario
4271
1050
1063
56
AutoFreeze
Disabling autoFreezereduced the time for each action slightly. Though, the total accumulated time increased slightly. This is very strange.
The time needed to freeze every action and the state after receiving it via the WebSocket was not included in this benchmark. In addition, it could be that V8 has (or will have) optimizations for frozen objects (saving memory, heuristics, ...), which would only be relevant when accessing the properties in the actual application on the frontend.
Conclusion
One can see that mutative is always between 3 to 4 times faster than immer.js.
This is basically free performance.
Still, I would recommend using immer.js for now as it is more mature, and we don't need the performance yet.
In addition, mutative could also probably prevent #531 (if this should ever be desired). immer.js also has some performance improvements in the making immerjs/immer#1015, immerjs/immer#941.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
TLDR:
I did a little experiment + benchmarks and wanted to share the results just FYI. Because of the FYI character of this, I created a discussion instead of an issue.
We could improve the performance of all our reducers by 3 to 4 times by just switching libraries.
Intro
Immer.js is the library on which all our reducers rely.
Its
produce
-method "converts" mutable reducers (the input value is mutated) into immutable ones (the input values are not mutated, and instead, a new copy with the changes is returned).One alternative to
immer.js
is mutative. It has fewer features and bit different names, but aims to be more performant than immer.js.Setup
I replaced
produce
from immer withcreate
from mutable (d8d3869 and 02e3ac8). This was basically a drop-in replacement, as we didn't use any of the advanced features of immer.Test Setup:
Results:
Detailed outputs
immerjs
Mutative
Mutative without `autoFreeze`
Summary
AddLogEntryAction
is not deterministic #580. The migrations are allowed to not be deterministic.autoFreeze
as it uses this as an internal flag to determine wether something can be shallow copied or must be deep copied (big perfromance drop when disabling it).The accumulated time for each action per type of action is shown in the tables below.
workshop-babz-großes-szenario
immerjs
in msmutative
in msmutative
nofreeze
in msworkshop-malteser-großes-szenario
immerjs
in msmutative
in msmutative
nofreeze
in msThe
[Exercise] Tick
-action changes in every patient at least one property (health
). In contrast, all other actions change only one property of one patient/personnel/material and potentially some stuff in the R-Trees.Total accumulated time to process all actions
For runtime performance (on the server and client) the
newImmerDraft
-benchmark is relevant.The
noImmerDraft
-benchmark is the baseline, without any overhead for mutability. It is impossible for thenewImmerDraft
-benchmark to be faster than thenoImmerDraft
-benchmark.immerjs
in msmutative
in msmutative
nofreeze
in msAutoFreeze
Disabling
autoFreeze
reduced the time for each action slightly. Though, the total accumulated time increased slightly. This is very strange.The time needed to freeze every action and the state after receiving it via the WebSocket was not included in this benchmark. In addition, it could be that V8 has (or will have) optimizations for frozen objects (saving memory, heuristics, ...), which would only be relevant when accessing the properties in the actual application on the frontend.
Conclusion
One can see that
mutative
is always between 3 to 4 times faster thanimmer.js
.This is basically free performance.
Still, I would recommend using
immer.js
for now as it is more mature, and we don't need the performance yet.In addition,
mutative
could also probably prevent #531 (if this should ever be desired).immer.js
also has some performance improvements in the making immerjs/immer#1015, immerjs/immer#941.Beta Was this translation helpful? Give feedback.
All reactions