bvar | bRPC
bvar 是多线程环境下的计数器类库,方便记录和查看用户程序中的各类数值。
特性
- bvar 不能代替所有的计数器,它的本质是把写时的竞争转移到了读:读时需要合并所有写过的线程中的数据, 而不可避免地变慢了,所以读写都很频繁或需要基于最新值做一些逻辑判断时,不应该使用 bvar。
- 当很多线程都在累加一个计数器时,每个线程只累加私有的变量而不参与全局竞争,在读取时累加所有线程的私有变量。虽然读比之前慢多了,但由于这类计数器的读多为低频的记录和展现,慢点无所谓。
相关知识
原子操作
原子操作有时会很慢。一个核心写入自己的 L1 cache 是极快的(4 cycles,约 2ns,但当另一个核心读或写同一处内存时,它得确认看到其他核心中对应的 cacheline。对于软件来说,这个过程是原子的,不能在中间穿插其他代码,只能等待 CPU 完成一致性同步,这个复杂的硬件算法使得原子操作会变得很慢。
cache bouncing
当很多线程在频繁修改某个字段时,这个字段所在的 cache line 被不停地同步到不同的核上,就像在核间弹来弹去,这个现象就叫做 cache bouncing。
memory fence
memory fence 简单来说就是串行化加载与存储操作,主要是为了防止 CPU 乱序执行导致的错误。以下面的代码为例。
1 | // Thread 1 |
有一定的概率 Thread 1 中的指令被乱序执行,这时 Thread 2 中的指令就会在错误的情况下执行。boost 和 C++11 对 memory fence 做了抽象,上面的例子可以这么更正:
1 | // Thread1 |
参考
bvar | bRPC