一、概述
当很多线程争抢同一把锁时,一些线程无法立刻获得锁,而必须睡眠直到某个线程退出临界区。这个争抢过程我们称之为contention。在多核机器上,当多个线程需要操作同一个资源却被一把锁挡住时,便无法充分发挥多个核心的并发能力。现代OS通过提供比锁更底层的同步原语,使得无竞争锁完全不需要系统调用,只是一两条 wait-free,耗时 10-20ns
的原子操作,非常快。而锁一旦发生竞争,一些线程就要陷入睡眠,再次醒来触发了OS的调度代码,代价至少为 3-5us
。所以让锁尽量无竞争,让所有线程“一起起飞”是高性能服务器的永恒话题。
我们当前的 profiler 工具,可以分析在等待锁上花费的时间。等待过程中线程是休眠状态,不会占用 CPU,所以 contention profiler 中的时间并不是 cpu 时间,也不会出现在 cpu profiler 中。cpu profiler 可以抓到特别频繁的锁,因为他花费了很多 CPU,但耗时真正巨大的临界区往往不是那么频繁,而无法被 cpu profiler 发现。
因此,cpu profiler 和 contention profiler 是一种互补关系,前者分析忙碌时间,后者分析被动的等待时间。还有一类是由用户基于 condition(条件)或 sleep 发起的主动等待时间,无需分析。
注意,无竞争的锁不会被采集,我们采集的是在锁上花费的所有等待时间。
目前我们支持 pthread_mutex_t 锁,开启后每秒默认最多采集 1000 个竞争锁。如果一秒内竞争锁的次数超过了 1000,那么每把锁会有 1000/N
的概率被采集。在各类测试场景中,暂没有发现被采集程序的性能有明显变化。