1.CPU 利用率
对于一个应用来说,为了让应用达到最好的性能和可扩展性,我们不仅仅要充分利用 CPU 周期内可用的部分,而且要让这部分 CPU 的使用更有价值,而不是浪费。能够让 CPU 的周期利用的更充分对于多线程应用运行在多处理器和多核系统上至很有挑战性的。另外,当 CPU 达到饱和状态的时候并不能说明 CPU 的性能和伸缩性已经达到了最佳的状态。
为了区分应用是如何利用 CPU 资源的,我们必须从操作系统级别来检测。在很多操作系统上,CPU 的利用率统计报告通常包括用户和系统或内核对操作系统的使用。用户对 CPU 的使用是指应用用来执行应用代码执行所需要的时间。相比之下,内核和系统对 CPU 的使用是指应用用来执行操作系统内核代码锁花费的时间。高的内核或者系统 CPU 使用率可以表明共享资源紧迫,或者是有大量的 I/O 设备交互。理想的状态为了提高应用的性能和伸缩性,让内核或系统 CPU 时间为 0%,因为花在执行内核或系统代码的时间是可以用来执行应用代码的。因此 CPU 使用优化的一个正确方向就是尽可能减少 CPU 花在执行内核代码或者系统代码上的时间。
对于计算密集型应用,性能监控比监测用户 CPU 使用和内核或系统 CPU 使用要更深层次,在计算密集型应用中,我们需要监测 CPU 时钟周期内的执行执行条数(Instructions per clock;IPC),或者是每条 CPU 执行所使用的CPU周期(cycles per instruction;CPI)。对于计算密集型应用来说我们从这两个维度来监测 CPU 是不错的选择,因为现代操作系统的打包 CPU 性能报告工具通常只会打印 CPU 的利用率,而不会打印 CPU 周期内 CPU 用来执行指令的时间。这意味着当 CPU 正在等待内存中的数据的时候,操作系统CPU性能报告工具也会认为 CPU 是正在使用的状态,我们把这个场景叫做「Stall」,这种场景经常会发生,比如在 CPU 正在执行指令的任何时候,只要是指令需要的数据没有准备好,也就是没有在寄存器或者CPU缓存内,都会发生「Stall」场景。
当「Stall」场景发生的时候 CPU 会浪费时钟周期,因为 CPU 必须要等待指令需要的数据到达寄存器或者缓冲器。而且在这个场景中,数百个 CPU 时钟周期被浪费是很正常的事情,因此在计算密集型应用中,提高性能的策略是减少「Stall」场景的发生或者是增强 CPU 的缓存使用从而使得更少的 CPU 周期因为等待数据而浪费掉。这类的性能监控知识已经超越了本书的内容,需要性能专家的帮助了。然而,后面讲到的 Oracle Solaris Studio Performance Analyzer 这种性能剖析工具将会包括此类数据。