Go 1.9实现的sync.Map
非常依赖指针。这会浪费一些CPU(跟踪和缓存这些指针及其地址转换),并且消耗比它可能需要的更稳定的内存(每个条目至少一个指针)。
现在,既然sync.Map
已经在标准库中(而不仅仅是x/sync
),我们可以利用关于map
、interface{}
和/或atomic.Value
运行时实现的知识来消除其中的一些指针。
特别是,我们可能可以将readOnly.m
字段更改为直接包含一个runtime.hmap
变量,而不是指向它的map
变量。
我们还可能能够将该Map的元素从*entry
更改为entry
,因为它们的地址将是稳定的(除非我们解决#19094问题)。对我来说,这是否会给将读写Map提升为只读的过程增加太多复杂性并不明显:特别是,我们需要某种方法来确保没有线程试图更新先前只读Map的条目,这可能需要我们在GC安全点期间仅将读写提升为只读。
最后,我们可能能够直接在entry
结构中存储interface{}
值,而不是不安全的接口指针,尽管(如atomic.Value
所示)更新的同步可能是非常微妙的。
进一步的指针优化可能是可能的;这些只是我能想到的。
我不打算自己立即进行这种优化工作,但我想记录这个想法,以防社区中的其他人有一个激励他们解决这个问题的使用场景。
2条答案
按热度按时间7fhtutme1#
我认为解决这个问题需要运行时特定的钩子,或者至少是关于运行时行为的假设代码,这些假设不是语言规范保证的。
yfjy0ee72#
我今天尝试使用atomic.Value来减少一些指针,但最终发现无法保存nil。请参阅https://github.com/golang/go/blob/master/src/sync/map.go#L431C8 -L431C8。意识到支持存储nil的atomic.Value将遇到如何表示已清除的问题。