前言
性能问题可以分为两种类型:
On-CPU:线程花时间在CPU上运行的地方;
Off-CPU:在I/O,锁,计数器,分页/交换上阻塞等待的时间
Off-CPU的分析是一种性能分析的方法,用于测量和研究Off-CPU的时间以及堆栈跟踪等上下文。它不同于CPU Profiling,后者仅当线程在On-CPU上执行时检查线程。在这里,我们的目标是阻塞和Off-CPU的时间段。如下图蓝色部分:
Off-CPU的分析是与CPU分析相辅相成的,可以理解为这个就是100%的线程时间。此方法不同于应用程序功能阻塞的跟踪技术,因此这个方法是针对内核调度的阻塞概念。这是一种方便捕获的概念。
线程离开CPU的原因包括:I/O,锁,也有一些跟当前线程执行无关的原因包括:由于对CPU资源的高需求而导致的非自愿上下文切换和中断。不管是什么原因,如果在工作负载请求(同步代码路径)期间发生的这种情况,就会引入延迟。
在本节中,主要介绍Off-CPU时间作为指标,并总结Off-CPU的分析的技术,作为Off-CPU的示例实例。
进行Off-CPU分析的先决条件要求
Off-CPU分析要求堆栈跟踪可供跟踪器使用的,因此首先必须解决这个问题。许多应用程序都是使用 -fomit-frame-pointer gcc选项编译的,从而打破了基于帧指针的堆栈遍历。VM运行时(如动态的Java编译方法)和跟踪器在没有其他帮助的情况下可能无法找到其符号信息,从而导致堆栈跟踪仅为十六进制。当然还有其他陷阱。后续再展开。
几个相关概念的说明
1)CPU采样
许多传统的分析工具使用跨所有CPU的活动定时采样,以特定的时间间隔或速率(例如:90Hz)收集当前指令地址(Program Counter)或整个堆栈回溯跟踪的快照。这将给出正在运行的函数或堆栈跟踪计数,从而可以合理估计CPU周期是花费在哪些地方。在linux上我们可以使用perftool来对cpu进行定时采样。
2)应用程序跟踪
在函数的enter和exit会被记录,Off-CPU也是没有记录。
3)Off-CPU跟踪
记录的是Off-CPU的时间段
4)Off-CPU采样
Off-CPU的时间段内的采样
这种方法使用的是定时从未在CPU上运行的线程捕获阻塞的堆栈跟踪,同样它也可以通过墙上时间profiler:一个始终对所有线程所有时间进行采样的profiler。然后可以过滤掉On-CPU的时间,以留下Off-CPU进行分析。
系统很少使用Off-CPU采样。采用通常作为每个CPU计时器中断,然后检查当前正在运行的中断进程,生成On-CPU profile,一个Off-CPU采样器需要不同的方式工作:在每个应用程序线程中设置计时器以唤醒他们并捕获堆栈,或者让内核按一定间隔遍历所有线程并捕获其堆栈。