Go 1.9实现的sync.Map
使用单个Mutex
来保护包含新键的读写Map。这使得Store
具有不同新键的调用总是相互竞争,也与具有不同新键的Load
调用相互竞争,即使每个键的Load
和Store
仅限于单个线程。
这对于标准库中的sync.Map
用例并不重要,因为它们在稳定状态下不操作新键,但它限制了sync.Map
在涉及高周转率的用例中的实用性。这些用例可能包括:
- 具有高驱逐率的缓存,例如前端键值存储服务的缓存
- RPC或HTTP流ID到处理程序状态的Map
- 将不透明句柄Map到Go指针以编写符合cgo指针传递规则的C导出API
我们应该探索解决新键竞争的方法,例如对读写Map和相关锁进行分片(如#20360建议的那样),记录写入操作(并使用布隆过滤器或HyperLogLog过滤器避免读取日志,类似于#21032的建议),或者将读写Map存储在原子树数据结构中,而不是内置的map
。
8条答案
按热度按时间xtfmy6hx1#
(@orcaman 和/或 @OneOfOne 可能对这个感兴趣?)
hc2pp10m2#
我对这个想法很感兴趣,但我现在不能承诺。我脑海中浮现的一个想法需要破解运行时/哈希Map*,否则我们必须对键进行双重哈希。
w1jd8yoj3#
非常有趣的任务,我很想接手这个。我认为它应该可以在Go1.10里程碑上实现。在我能100%承诺在适当的时候完成这个之前,我会再多考虑一下设计。
oxiaedzo4#
@orcaman What I wanted to do is something like https://github.com/OneOfOne/cmap/tree/master/v2 ,
I use a slightly modified version of this in my code, but I wanted to do that with sync.Map in a way, but that'd require a lot more runtime knowledge to be able to use runtime/map's hasher directly to do the sharding rather than double hash it.
Sadly I don't have the knowledge nor time to learn the internals of runtime/map right now.
By all means if you can do that, it'd be great or we can discuss it.
w41d8nur5#
我认为你可以使用锁片和脏Map,低位哈希值执行选择 - 但这需要访问内部哈希码。
ds97pgxw6#
@bcmills 我愿意尝试一下。有没有描述在实现是标准库一部分时使用内部设施的文档?
z6psavjg7#
我不知道有没有好的入门文档,但也许@randall77或@aclements可以给你指明方向。
kd3sttzy8#
这真是个好主意。