1. 程式人生 > >CPU使用率度量指標是扯淡!

CPU使用率度量指標是扯淡!

作者簡介:Brendan D. Gregg目前在Netflix從事大規模雲端計算效能方面的工作。

我們用來衡量CPU使用率(CPU utilization)的指標具有極大的誤導性,而且一年比一年來得誤人子弟。CPU使用率到底是什麼?你的處理器有多忙碌?不,那不是CPU使用率衡量的方面。沒錯,我在這裡所說的是每個人在到處使用的“%CPU”這個度量指標,用於每一款效能監控產品中。用top(1)命令來檢視。

你可能認為90%的CPU使用率意味著:

而實際上它可能意味著:

停滯(stalled)意味著處理器在處理指令方面沒有進展,通常是由於處理器在等待記憶體輸入/輸出。我在上面劃分的比例(忙碌和停滯之間)是我在實際的生產環境中經常看到的情形。你很可能基本上處於停滯狀態,但渾然不知罷了。

這對你來說意味著什麼呢?瞭解你的多少CPU處於停滯狀態可以指導減少程式碼或減少記憶體輸入/輸出之間的效能調優工作。誰要是在關注CPU效能,尤其是在根據CPU自動擴充套件資源的雲,如果知道%CPU中停滯的部分,那將大有益處。

CPU使用率其實是什麼東東?

我們稱為CPU使用率的衡量指標其實是“非閒置時間”(non-idle time):也就是CPU未執行閒置執行緒的時間。你的作業系統核心(無論它是什麼核心)通常在上下文切換過程中跟蹤這個指標。如果非閒置程序開始執行,然後停止100毫秒,核心還是認為該CPU在那整段時間都被使用。

這個度量指標的歷史與分時系統一樣久遠。Apollo Lunar Module制導計算機(一種開創性的分時系統)稱其閒置執行緒為“DUMMY JOB”,工程師們跟蹤了執行該閒置執行緒的週期和執行實際任務的週期,將這視作是一個衡量計算機使用率的重要指標。

那麼這個指標哪裡不對勁呢?

現如今,CPU的速度已變得比主記憶體快得多,等待記憶體在仍然所謂的“CPU使用率”中佔了大頭。如果你看到數值很高的%CPU,可能認為處理器是瓶頸(即散熱片和風扇下面的CPU封裝件),而實際上那些DRAM模組才是瓶頸。

這方面的情形一直變得越來越嚴峻。長期以來,處理器廠商提高時鐘速度的幅度超過DRAM提高訪問延遲的幅度,這就是所謂的“CPU DRAM缺口”( CPU DRAM gap)。這種情形在3 GHz處理器面世的2005年前後趨穩;自那以後,處理器使用更多的核心和超執行緒來提升效能,另外使用多插座配置,這一切給記憶體子系統提出了更高的要求。處理器廠商試圖採用更龐大、更智慧的CPU快取以及更快速的記憶體匯流排和互連技術來緩解這個記憶體瓶頸。但是我們仍然通常處於停滯狀態。

如何表明CPU到底在處理什麼?

不妨使用效能監控計數器(PMC):這是使用Linux perf(http://www.brendangregg.com/perf.html)及其他工具可以讀取的硬體計數器。比如說,將整個系統測量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),該度量指標顯示了我們在每個CPU時鐘週期平均完成了多少個指令。簡單來說,這個值越高越好。上面例子中的0.78聽起來不賴(78%的時間段處於忙碌狀態);但如果你意識到該處理器的最高速度下IPC是4.0,就不這麼認為了。這又叫4-wide,是指指令取出/解碼路徑。這意味著,CPU每個時鐘週期可以retire(完成)四個指令。所以,在4-wide系統上IPC為0.78,意味著CPU的執行速度是其最高速度的19.5%。新的英特爾Skylake處理器是5-wide。

你可以用來進一步鑽研的PMC要多數百個:可以按不同的型別,直接測量停滯的週期。

在雲端

如果你在虛擬環境中,可能無法訪問PMC,這要看虛擬機器管理程式是否為訪客(guest)支援PMC。我最近寫過一篇文章:《EC2的PMC:測量IPC》(http://www.brendangregg.com/blog/2017-05-04/the-pmcs-of-ec2.html),表明瞭如今PMC如何可用於基於Xen的AWS EC2雲上面的專用主機型別。

實際對策

如果你的IPC < 1.0,你可能遇到了記憶體停滯,軟體調優策略包括減少記憶體輸入/輸出,改進CPU快取和記憶體區域性性(memory locality),尤其是在NUMA系統上。硬體調優策略包括:使用CPU快取比較大的處理器以及速度比較快的記憶體、匯流排和互連技術。

如果你的IPC > 1.0,你可能是指令密集型。想方設法減少程式碼執行:消除不必要的工作和快取操作等。CPU火焰圖(http://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html)是一款很適合開展這項調查的工具。至於硬體調優,不妨試一試更快的時鐘頻率和數量更多的核心/超執行緒。

效能監測產品應該能告訴你什麼?

每一款效能工具應該顯示IPC以及%CPU。或者將%CPU分解成指令完成周期與停滯週期,比如%INS和%STL。

面向Linux的tiptop(1)可按程序顯示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

CPU使用率具有誤導性的其他理由

讓CPU使用率具有誤導性的不僅僅是記憶體停滯週期。其他因素包括如下:

  • 溫度過高導致處理器停滯。
  • 睿頻加速(Turboboost)導致時鐘頻率不一。
  • 核心因speedstep導致時鐘頻率不一。
  • 平均值方面的問題:1分鐘內的使用率為80%,隱藏了100%的突發使用率。
  • 自旋鎖:CPU被使用,有很高的IPC,但是應用程式在處理指令方面沒有合理的進展。

結束語

CPU使用率已成為一個極具誤導性的度量指標:它包括了等待主記憶體的週期,而這類週期在現代工作負載中佔了大頭。如果使用額外的度量指標,你就能搞清楚%CPU到底意味著什麼,包括每個週期指令(IPC)。IPC < 1.0可能意味著記憶體密集型,而IPC > 1.0可能意味著指令密集型。我在之前的一篇文章(http://www.brendangregg.com/blog/2017-05-04/the-pmcs-of-ec2.html)中介紹了IPC,包括介紹了衡量IPC所需要的效能監控計數器(PMC)。

顯示%CPU的效能監控產品還應該顯示PMC度量指標,解釋那個值意味著什麼,那樣才不會誤導終端使用者。比如說,它們可以一併顯示%CPU及IPC,以及/或指令完成周期與停滯週期。有了這些度量指標,開發人員和操作人員才能決定如何才能更好地調優應用程式和系統。