为什么带填充字段的struct工作得更快

Leo*_*aev 8 parallel-processing concurrency go

我刚刚找到了这个提供无锁环的库,它的工作方式比通道快:https://github.com/textnode/gringo(它的工作速度非常快,尤其是GOMAXPROCS> 1)

但有趣的部分是用于管理队列状态的结构:

type Gringo struct {
    padding1 [8]uint64
    lastCommittedIndex uint64
    padding2 [8]uint64
    nextFreeIndex uint64
    padding3 [8]uint64
    readerIndex uint64
    padding4 [8]uint64
    contents [queueSize]Payload
    padding5 [8]uint64
}
Run Code Online (Sandbox Code Playgroud)

如果我删除"paddingX [8] uint64"字段,它的工作速度大约慢20%.它怎么样?

还要感谢有人解释为什么这种无锁算法比通道快得多,甚至缓冲?

Dav*_*rtz 11

填充通过将每个结构放在其自己的缓存行上来消除错误共享.如果两个变量共享一个缓存行,那么如果对另一个变量进行插入写入,则读取未修改的变量将与读取修改后的变量一样昂贵.

当在多个内核上读取变量而未修改变量时,内核将共享缓存行.这使得读取非常便宜.在任何内核可以写入该缓存行的任何部分之前,它必须使其他内核上的缓存行无效.如果任何核心稍后从该缓存行读取,它将发现缓存行无效并且必须返回共享它.当一个变量经常被修改而另一个变量经常被读取时,这会产生痛苦的额外高速缓存一致性流量.