The Go 1.9 implementation of sync.Map is very pointer-heavy. That wastes a bit of CPU (following and caching those pointers and their address translations) and also consumes more steady-state memory than it potentially needs to (by at least one pointer per entry).
Now that sync.Map is in the standard library (instead of just x/sync), we can potentially make use of knowledge about the runtime implementations of map, interface{} and/or atomic.Value to flatten out some of those pointers.
In particular we can probably change the readOnly.m field to contain a runtime.hmap directly instead of a map variable that points to it.
We may also be able to change the elements of that map from *entry to entry, since their addresses will be stable (unless we address #19094). It's not obvious to me whether that would add too much complexity to the process of promoting the read-write map to read-only (which is currently just an atomic store): in particular, we would need some way to ensure that no thread is trying to update the entries of the previous read-only map, which might require that we only promote read-write to read-only during a GC safe-point.
Finally, we may be able to store interface{} values directly in the entry struct rather than unsafe-pointers-to-interfaces, although (as atomic.Value demonstrates) the synchronization for updates may be very subtle.
Further pointer optimizations may be possible; those are just the ones I can think of.
I don't intend to do this optimization work myself any time soon, but I wanted to document this idea in case someone else in the community has a use-case that motivates them to address it.
The text was updated successfully, but these errors were encountered:
The Go 1.9 implementation of
sync.Map
is very pointer-heavy. That wastes a bit of CPU (following and caching those pointers and their address translations) and also consumes more steady-state memory than it potentially needs to (by at least one pointer per entry).Now that
sync.Map
is in the standard library (instead of justx/sync
), we can potentially make use of knowledge about the runtime implementations ofmap
,interface{}
and/oratomic.Value
to flatten out some of those pointers.In particular we can probably change the
readOnly.m
field to contain aruntime.hmap
directly instead of amap
variable that points to it.We may also be able to change the elements of that map from
*entry
toentry
, since their addresses will be stable (unless we address #19094). It's not obvious to me whether that would add too much complexity to the process of promoting the read-write map to read-only (which is currently just an atomic store): in particular, we would need some way to ensure that no thread is trying to update the entries of the previous read-only map, which might require that we only promote read-write to read-only during a GC safe-point.Finally, we may be able to store
interface{}
values directly in theentry
struct rather than unsafe-pointers-to-interfaces, although (asatomic.Value
demonstrates) the synchronization for updates may be very subtle.Further pointer optimizations may be possible; those are just the ones I can think of.
I don't intend to do this optimization work myself any time soon, but I wanted to document this idea in case someone else in the community has a use-case that motivates them to address it.
The text was updated successfully, but these errors were encountered: