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
HashTrieMap was added for the unique package, but it turns out that it's faster than Map in many cases, including its own microbenchmarks.
This work was already done during the Go 1.24 cycle, culminating in https://go.dev/cl/608335. This issue just captures the work that was done so that it can be referenced.
Higher GOMAXPROCS values are omitted because they're not very useful. It's very unlikely that the data structure will be heavily contended on all cores in the same way in real programs; even 4 is pushing it.
Analysis
The load-hit case is slightly slower due to Swiss Tables improving the performance of the old sync.Map (the new implementation was slightly faster before those changes, when I initially benchmarked). Some benchmarks show a seemingly large slowdown, but that's mainly due to the fact that the new implementation can actually shrink, whereas the old one never shrank. This creates additional allocations.
The new implementation also avoids issues the old one had, like the ramp-up time of promoting a key to read-only (which isn't captured by the benchmarks) and likely lower contention when mutating disjoint sets of keys.
Feedback
If any of the slowdowns affect you, you can set GOEXPERIMENT=nosynchashtriemap at build time to revert to the old implementation, and please file a bug. We'd like the implementations to not cause slowdowns in real-world programs.
(We can possibly avoid some of these additional allocations by adding a sync.Pool for entry nodes to the map's structure, though this would mainly only help heavy uses of sync.Map and may not actually matter in practice.)
The text was updated successfully, but these errors were encountered:
HashTrieMap
was added for theunique
package, but it turns out that it's faster thanMap
in many cases, including its own microbenchmarks.This work was already done during the Go 1.24 cycle, culminating in https://go.dev/cl/608335. This issue just captures the work that was done so that it can be referenced.
Microbenchmarks
Higher
GOMAXPROCS
values are omitted because they're not very useful. It's very unlikely that the data structure will be heavily contended on all cores in the same way in real programs; even 4 is pushing it.Analysis
The load-hit case is slightly slower due to Swiss Tables improving the performance of the old
sync.Map
(the new implementation was slightly faster before those changes, when I initially benchmarked). Some benchmarks show a seemingly large slowdown, but that's mainly due to the fact that the new implementation can actually shrink, whereas the old one never shrank. This creates additional allocations.The new implementation also avoids issues the old one had, like the ramp-up time of promoting a key to read-only (which isn't captured by the benchmarks) and likely lower contention when mutating disjoint sets of keys.
Feedback
If any of the slowdowns affect you, you can set
GOEXPERIMENT=nosynchashtriemap
at build time to revert to the old implementation, and please file a bug. We'd like the implementations to not cause slowdowns in real-world programs.(We can possibly avoid some of these additional allocations by adding a
sync.Pool
for entry nodes to the map's structure, though this would mainly only help heavy uses ofsync.Map
and may not actually matter in practice.)The text was updated successfully, but these errors were encountered: