您的位置:首页 > 编程语言 > Go语言

Go 语言的分布式读写互斥

2015-05-06 17:51 316 查看
Go语言默认的sync.RWMutex实现在多核环境中表现并不佳,因为所有的读者在进行原子增量操作时,会抢占相同的内存地址。该文探讨了一种n-way
RWMutex,也可以称为“大读者(big reader)”锁,它可以为每个CPU内核分配独立的RWMutex。读者仅需在其核心中处理读锁,而写者则须依次处理所有锁。


查找当前CPU

读者使用CPUID指令来决定使用何种锁,该指令仅需返回当前活动CPU的APICID,而不需要发出系统调用指令抑或改变运行时。这在Intel或AMD处理器上均是可以的;ARM处理器则需要使用CPU
ID寄存器。对于超过256个处理器的系统,必须使用x2APIC,另外除了CPUID还要用到带有EAX=0xb的EDX寄存器。程序启动时,会构建(通过CPU亲和力系统调用) APICID到CPU索引的映射,该映射在处理器的整个生命周期中静态存在。由于CPUID指令的开销可能相当昂贵,goroutine将只在其运行的内核中定期地更新状态结果。频繁更新可以减少内核锁阻塞,但同时也会导致花在加锁过程中的CPUID指令时间增加。

陈旧的CPU信息。如果加上锁运行goroutine的CPU信息可能会是过时的(goroutine会转移到另一个核心)。在 reader记住哪个是上锁的前提下,这只会影响性能,而不会影响准确性,当然,这样的转移也是不太可能的,就像操作系统内核尝试在同一个核心保持线程来改进缓存命中率一样。


性能

这个模式的性能特征会被大量的参数所影响。特别是CPUID 检测频率,readers 的数量,readers 和writers 的比率,还有readers 持有锁的时间,这些因素都非常重要。当在这个时间有且仅有一个writer
活跃的时候,这个writer 持有锁的时期不会影响sync.RWMutex 和DRWMutex 之间的性能差异。

实验证明DRWMutex表现胜过多核系统,特别writer小于1%的时候,CPUID会在最多每10个锁之间被调用(这种变化取决于锁被持有的持续时间)。甚至在少核的情况下,DRWMutex也在普遍选择通过sync.Mutex使用sync.RWMutex的应用程序的情况下表现好过sync.RWMutex.

下图显示核数量使用增加每10个的平均性能:

drwmutex -i 5000 -p 0.0001 -w 1 -r 100 -c 100






错误条表示第25和第75个百分位。注意每第10核的下降;这是因为10个核组成一个运行标准检查系统的机器上的NUMA节点, 所以一旦增加一个NUMA节点,跨线程通信量变得更加宝贵。对于DRWMutex来说,由于对比sync.RWMutex更多的reader能够并行工作,所以性能也随之提升。

查看go-nuts
tread进一步讨论

cpu_amd64.s

main.go

本文转自:开源中国社区[http://www.oschina.net]

本文标题:Go语言的分布式读写互斥

本文地址:http://www.oschina.net/translate/distributed-read-write-
mutex-in-go

参与翻译:BuN_Ny , OSC技术周刊 , eason02

英文原文:Distributed Read-Write Mutex in Go

时间: 2015-05-06 08:40 来源 :开源中国社区 作者 :oschina 原文链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: