# Linux 解密 —CPU 利用率

image-20210225213454924


Goal

  • 🔲什么是 CPU 的利用率

  • 🔲IPC 是什么

  • 🔲如何获取真正的 CPU 瓶颈根源

Preconditions

  • ✅了解 CPU

  • ✅了解计算机

  • ✅了解 Linux 的基本使用

# What ‘s the CPU Utilization

CPU 的时间由两部分组成:

  • 一是 CPU 用于处理程序指令或者操作系统指令的时间,也称之为 busy time
  • 二是 CPU 等待 I/O 操作或者进入 idle mode (也就是空闲线程模式) 的时间,也称之为 idle time

CPU 利用率:指的是 CPU 用于处理程序指令或者操作系统指令的时间占总时间的百分比

CPUUtilization=TbusyTbusy+TidleCPU_{ Utilization} = \frac{T_{busy}}{T_{busy}+T_{idle}}

CPU 使用率有两个主要用途

  1. 是量化系统的整体繁忙度。
    • 当 CPU 使用率很高时,用户可能会遇到延迟。如此高的 CPU 使用率表明处理能力不足。
    • 解决方法:要么需要升级 CPU,要么通过减少任务负载来使得整体体验回复。
  2. 是更好让程序共享处理器。
    • 在多任务系统中,如果单个程序的 CPU 使用率过高可能表明它对处理能力的要求很高,或者可能会发生故障(进入死循环)。
    • 解决方法:测量单个程序在设置的时间内的利用率,如果处在异常高的值,则触发 trap 然后进行任务调度。

From: Wiki CPU Time

CPU time (or process time) is the amount of time for which a CPU was used for processing instructions of a computer program or operating system, as opposed to elapsed time, which includes for example, waiting for I/O operations or entering low-power (idle) mode. The CPU time is measured in clock ticks or seconds. Often, it is useful to measure CPU time as a percentage of the CPU's capacity, which is called the CPU usage.

CPU time and CPU usage have two main uses. The first use is to quantify the overall busyness of the system. When the CPU usage is high, the user may experience lag. Such high CPU usage indicates insufficient processing power. Either the CPU needs to be upgraded, or the user experience reduced, for example, by switching to lower resolution graphics or reducing animations.

# How to measure

常用的工具有 toppshtop

ps :静态查看的进程状态的工具

$ ps -aux

image-20210227212318567

%CPU :就是程序对 CPU 的占用率,总和就是我们的 CPU 的利用率,这里我们看到总和为 0.9%

top :动态查看进程状态的工具

image-20210227212939643

htop :高亮可视化的查看进程状态的工具

image-20210227212622081

# It is True?

然而我们需要仔细思考这个问题,CPU 利用率这个指标真的能来衡量性能的发挥吗?如果 CPU 利用率处于一个较高水平,是否意味着性能瓶颈在别的地方呢?我们来看个例子,我们使用 Top 获取的信息:

img

你可能会认为 90%的 CPU 利用率意味着:CPU 百分之九十的时间都在忙!

然而他可能是这个样子:

img

CPU 只有一部分时间在忙,而其他时间在 Waiting

Waiting 表示处理器并没有在处理指令,因为它通常是正在等待内存 I/O。这意味着什么?了解您的 CPU Waiting 了多少,可以在减少指令或者减少内存 I/O 之间进行性能调整。

我们称为 CPU 利用率的指标实际上是 “非空闲时间”,如今,CPU 的速度已经比主内存快得多,而等待内存的问题仍然严重。当您在 top 中看到较高的 %CPU 时,你可能会认为瓶颈是 CPU,而实际上却是 DRAM

长期以来,CPU 制造商的时钟速度扩展速度比 DRAM 扩展其访问延迟速度要快。同时 CPU 使用更多的内核和超线程进行扩展,再加上多插槽配置,所有这些都对存储子系统提出了更高的要求。CPU 制造商已尝试通过更大更智能的 CPU Cache 以及更快的内存总线和互连来减少内存瓶颈。

# Back to Definition

从上面的问题我们可以发现,CPU 利用率无法真正告诉我们 CPU 的有效利用率是多少,他只是能告知 CPU 是否处于工作,而很有可能他此刻正在” 摸鱼 “,而造成这个问题的根本在于内存的” 偷懒 “。那么我们应该如何获取真正 CPU 的利用率呢?或者如果知道 CPU 是否在” 摸鱼 “?

回答这个问题,其实很简单,我们只需要了解 CPU 他最本质的工作定义:便是执行计算机的指令。

那么我们由此就能有以下的定义:
每条指令的平均周期 CPI:

CPI=1ICPI = \frac{1}{I}

每个周期的平均指令 IPC:

IPC=1CIPC = \frac{1}{C}

我们通过统计 CPU 最本质的工作内容来获取 CPU 的工作情况。

通过使用性能监视计数器(PMCs):可以使用 Linux 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

这里的关键指标是每个周期的指令数(IPC: insns per cycle),显示每个 CPU 时钟周期我们完成了多少条指令。

在例子中 IPC 的值是 0.78,也就是一个 CPU 时钟周期完了 0.78 条指令,而到该处理器的最高速度是 IPC:4.0。这也称为 4-wide,。这意味着,CPU 可以在每个时钟周期退出(完成)四条指令。这意味着 CPU 的真正利用率为:

CPUutilization=IPCmeasureIPCCPUmax=0.784=19.5CPU_{utilization} = \frac{IPC_{measure}}{IPC_{CPUmax}} = \frac{0.78}{4} = 19.5%

在 Linux 上,我们可以通过 Tiptop 工具获取 IPC

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

# Use and Understand it !

我们需要一个基础来告诉我们 IPC 的数据意味者什么?不然即使拿到 IPC 的数据,知道了利用率也无从下手。

那么首先我们需要编写两个虚拟的工作负载:

  • 一个只不断执行指令的任务(理想的工作 IPC)
  • 一个只不断执行内存访问(无序的)的任务(最糟糕内容延迟)

使用工具采集两个任务的 IPC,然后计算中点系数:

系数=IPCins+IPCmem2系数= \frac{IPC_{ins} + IPC_{mem}}{2}

这样是让我们获取计算机的平均基准 IPC,然后我们将这个基准定位 1。

然后对于特定程序进行测量获取 IPC,然后计算:

IPCt=IPCget系数IPC_{t} = \frac{IPC_{get}}{系数}

  • IPCtIPC_t <1.0:则可能是内存停滞了
    • 软件调整:包括减少内存 I / O 并改善 CPU 缓存和内存局部性,尤其是在 NUMA 系统上。
    • 硬件调整:使用具有更大 CPU 缓存,更快的内存,总线和互连的处理器。
  • IPCtIPC_t > 1.0:则很可能受指令约束。
    • 软件调整:寻找减少代码执行的方法:消除不必要的工作,缓存操作等。CPU 火焰图是进行此研究的好工具。
    • 硬件调整,使用更快的时钟速率和更多的内核 / 超线程。

对于 $IPC_t $> 1 的例子:

一个程序使用了自旋锁,此时有较高的 IPC,但该应用程序未在逻辑上前进。

# References

[1]Brendan Gregg.CPU Utilization is Wrong[EB/OL].http://www.brendangregg.com/blog/2017-05-09/cpu-utilization-is-wrong.html,2017-5-9.
[2]Brendan Gregg.The USE Method[EB/OL].http://www.brendangregg.com/usemethod.html#Apollo,2017-8-1.
[3]Brendan Gregg.Linux Load Averages: Solving the Mystery[EB/OL].http://www.brendangregg.com/blog/2017-08-08/linux-load-averages.html,2017-8-8.
[4]Wikipedia.CPU_time[EB/OL].https://en.wikipedia.org/wiki/CPU_time,2020-5-11.

更新于

请我喝[茶]~( ̄▽ ̄)~*

Junwide Xiao 微信支付

微信支付

Junwide Xiao 支付宝

支付宝