记录了自己在执行 CPU Profiling 的时候遇到的一些经验。
相关文章:
Profiling 基础
首先,Performance analysis and tuning on modern CPUs 这本书是值得阅读的基础。但是里面讲述的很多内容,我目前还没有机会完全实践。
关于线程池
一些程序会同时记录所有线程的 CPU 用量,以及当前进程的 CPU 总用量。这两个是一致的么?至少在一个使用线程池的程序中,未必一致。
这里的原因是线程池中往往会将线程按照 ${task_name}_${task_id}
这样重新命名,从而区分用途。而处于避免线程启动和销毁的开销,又倾向于维护一个全局常驻线程池,新开辟的线程池会先尝试从这个全局线程池中取,然后用完之后再归还。这就导致如果在这个过程中线程名字发生了从 A 到 B 的变换,则可能会看到 B 对应的指标有一个很高的 delta(比如在 grafana 中能看到一个尖峰)。原因是 /proc/$pid/stat
或者 /proc/tasks/$tid/stat
里面的信息都是从启动开始经历的时钟周期,无论是 stime 还是 utime。所以,如果一开始线程名是 A,后来被某个线程池借走了,名字变成 B,但此时 A 的数据还在。如果此时,线程被归还了,名字改为 A,那么 A 的变化率就是这段时间的 jiffies 增量除以这段时间的长度。
On CPU 和 Off CPU time
off-CPU 例如在等待阻塞 IO、锁、page swap 等的时间。这些时间不会通过普通的火焰图被反映出来,但却是影响读取性能的一个因素。我们常常要回答问题,为什么 CPU 没有被用满,但是查询依然比较慢。