CPU到底在忙啥?CPU利⽤率的正确计算⽅法
我们平时使⽤的CPU利⽤率⽅法是极具误导性的,并且⼀年更甚⼀年。那么什么是CPU利⽤率?是你的CPU到底有多忙,是像“% CPU”这样到处在⽤的指标所显⽰的那样吗?
在top命令⾥,你看到90%的CPU利⽤率是这样:
然⽽它真正想表达的是这个意思:
Stall(这⾥译作“怠速”)是说这个处理器没有在跑指令,⽐如在等待内存I/O的时候。我上图所画的⽐例(“忙”与“怠速”之间)是我在真实⽣产环境中遇到的,并且你的CPU也很可能是处于“怠速”状态。
这些对你有什么意义呢?理解CPU怠速多少,会直接影响到你在减少代码或者减少内存I/O的调优⼯作。
那么真正的CPU利⽤率怎么算呢?
平时的CPU利⽤都是⾮空闲时间,即CPU不运⾏idle线程(⽐如Windows⾥的空闲进程)的时间。你的操作系统那会平时会在上下⽂切换的时候跟踪它,但是假如⼀个⾮idle线程开始运⾏100毫秒后停⽌,那内核会认为后⾯这段时间CPU 也在这个⾮idle线程上。
那么它有什么⽑病呢?
现在的CPU⽐内存已经快了很多倍,但等待内存的时间仍然被算进CPU时间中。当你在top命令中看到较⾼
的“%CPU”的时候,你可能认为它到达了⼀个性能瓶颈,就是散热⽚和风扇下⾯的那个CPU,但实际上,这是那⼀根根内存条的锅。
如何分辨CPU到底在忙啥?
使⽤性能监测计数器(PMC)——⼀种能够⽤perf或者其他⼯具命令查看的硬件计数器。⽐如,观测整个系统10秒钟:# perf stat -a -- sleep 10
Performance counter stats for 'system wide':
641398.723351 task-clock (msec) # 64.116 CPUs utilized (100.00%)
379,651 context-switches # 0.592 K/sec (100.00%)
51,546 cpu-migrations # 0.080 K/sec (100.00%)
13,423,039 page-faults # 0.021 M/sec
1,433,972,173,374 cycles # 2.236 GHz (75.02%)
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
1,118,336,816,068 instructions # 0.78 insns per cycle (75.01%)
249,644,142,804 branches # 389.218 M/sec (75.01%)
7,791,449,769 branch-misses # 3.12% of all branches (75.01%)
10.003794539 seconds time elapsed
这⾥的⼀个关键指标就是instructions per cylce(IPC,每CPU周期执⾏指令数),它能够显⽰每CPU
周期内每个CPU 运⾏了多少指令,越⾼说明效率越⾼。上述⽰例中,这⼀值为0.78,但这并不说明CPU利⽤率为78%,因为现代CPU 的IPC最⼤值为4.0(新的已经到了5.0),也就是4-wide。CPU在执⾏指令时,单个指令会被分割为多个步骤,⽐如取指令、解码、执⾏、内存访问、写寄存器等,这些命令如果在单个CPU周期内最多执⾏⼀个,那么需要5个CPU周期来完成⼀条命令,IPC就是0.2,如果采⽤指令流⽔线,即3~5-wide的CPU,那么完美状态下1个CPU周期就可以完成⼀条命令,IPC就是1。(译者注:作者⽂中使⽤了CPU clock cycle表⽰通常所说的CPU周期,为了避免与晶振时钟周期混肴我并没有将其译为CPU时钟周期。)
当然,还有数百个其他你可以⽤来测量的性能计数器。
最佳实践
如果你的IPC⼩于1.0,你可能遇到了内存操作密集型,软件调优策略可以有减少内存I/O,增强内存本地访问性,尤其是在NUMA系統上。硬件调优策略则是使⽤CPU cache较⼤以及更快的内存、总线和内联技术。
性能检测产品应该告诉你什么呢?
性能检测⼯具都应该显⽰出每个进程的IPC,或者是按照指令周期与怠速周期,⽐如%INS和%STL,下图为Linux中的tiptop命令:
tiptop - [root]
Tasks: 96 total, 3 displayed screen 0: default
PID [ %CPU] %SYS P Mcycle Minstr IPC %MISS %BMIS %BUS COMMAND
3897 35.3 28.5 4 274.06 178.23 0.65 0.06 0.00 0.0 java
1319+ 5.5 2.6 6 87.32 125.55 1.44 0.34 0.26 0.0 nm-applet
900 0.9 0.0 6 25.91 55.55 2.14 0.12 0.21 0.0 dbus-daemo
CPU利⽤率具有误导性的其他理由
1.
使得这个%CPU指标错误的理由除了CPU在内存的怠速周期外,还有如下因素:
2.
温度也能使CPU进⼊怠速;
3.
Turboboost(睿频)引起时钟频率变化;
4.
SpeedStep引起时钟频率变化;
SpeedStep引起时钟频率变化;
5.
⼀分钟内的80%的平均利⽤率并不能表⽰100%的突发利⽤率(类似⽹络QoS);
6.
⾃旋锁:CPU在很严肃地瞎忙;
Update: CPU利⽤率真的错了吗?
⾃这篇⽂章发布以后,留⾔讨论⾮常激烈,已经有了上百条了。⾸先谢谢你们对这话题感兴趣并花时
间阅读,但我在这⾥还是要统⼀回复:我对disk的iowait并不关⼼(译者注:PC CPU不能直接操作外部存储),并且⽂中也已经给出了内存操作密集型的对应调优措施。
然⽽,CPU利⽤率到底是从本质上错了还是仅仅是有误导性了?我认为需要⼈将⾼CPU利⽤率视为处理单元的瓶颈的事⼉,是错的。那么这个指标的计算⽅法从技术上讲正确吗?如果CPU在怠速期间不能被其他任何进程使⽤,那么这不就是所谓的“使⽤等待”(听起来有点⽭盾)。某些情况下,%CPU作为⼀个操作系统层⾯的指标是技术正确但是容易误导⼈的。在超线程中,怠速周期可以被其他线程使⽤,所以%CPU的算法也会将其算在内,⽽实际上并没有利⽤。那样是不对的,这篇⽂章中我强调的是解释问题并提出对策,并且,这个指标也有技术上的问题。
结论update是什么
CPU利⽤率已成为⼀个极具误导性的指标:它算进了等待主存的周期,⽽这类周期在现代的CPU负载中占据不少。如果使⽤额外指标,你就能搞清楚%CPU到底意味着什么,包括每CPU周期执⾏指令数(IPC)。IPC < 1.0可能意味着你的应⽤是内存密集型,⽽IPC > 1.0则可能是指令密集型。我在之前的⼀篇⽂章,显⽰%CPU的性能监控产品也应该显⽰PMC测量指标,并给予充分解释,这样才不会误导⽤户。⽐如,它们可以⼀起显⽰%CPU和IPC,或者指令周期与怠速周期。有了这些指标,开发或管理⼈员才能在应⽤和操作系统中选择正确的调优⽅式。
译者的话
PS:为什么要翻译这个⽂章呢?因为很多时候总感觉PC的这个CPU利⽤率的百分⽐显⽰没能真实反应我的CPU到底忙不忙,在学校的时候⽤单⽚机也是算idle,但到了PC后隐约感觉这么算不对,看了BG的⽂章后才恍然⼤悟。另外这篇⽂章之前已经被翻译过,但作者⼜有更新,也挺有意思的,我就重新翻了⼀遍,并加了⼀些弹幕。
译者介绍:云技术社区专家蒋迪
蒋迪,资深虚拟化基础设施⼯程师,《KVM私有云架构设计与实践》作者,云技术社区专家,擅长KVM云平台架构解析与虚拟化POC,具有⼀线开发与交付经验。
加⼊中国最活跃的kubernetes技术讨论QQ,加主QQ:502207183,并注明城市、⾏业、技术⽅向。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。