1. 程式人生 > >cpu 性能

cpu 性能

netflix 總線 一分鐘 ons 毫秒 apol 虛擬化 .html lock

我們平時使用的CPU利用率方法是極具誤導性的,並且一年更甚一年。那麽什麽是CPU利用率?是你的CPU到底有多忙,是像“% CPU”這樣到處在用的指標所顯示的那樣嗎?

在top命令裏,你看到90%的CPU利用率是這樣:

技術分享

然而它真正想表達的是這個意思:

技術分享

Stall(這裏譯作“怠速”)是說這個處理器沒有在跑指令,比如在等待內存I/O的時候。我上圖所畫的比例(“忙”與“怠速”之間)是我在真實生產環境中遇到的,並且你的CPU也很可能是處於“怠速”狀態。

這些對你有什麽意義呢?理解CPU怠速多少,會直接影響到你在減少代碼或者減少內存I/O的調優工作。

那麽真正的CPU利用率怎麽算呢?

平時的CPU利用都是非空閑時間,即CPU不運行idle線程(比如Windows裏的空閑進程)的時間。你的操作系統那會平時會在上下文切換的時候跟蹤它,但是假如一個非idle線程開始運行100毫秒後停止,那內核會認為後面這段時間CPU也在這個非idle線程上。

在老舊的分時系統裏,這麽算沒毛病。阿波羅登月艙的導航系統計算機將這裏的idle線程叫做“DUMMY JOB”,工程師用利用它來測算計算機的利用率,可以參考之前我寫過的這樣一篇文章(鏈接地址:http://www.brendangregg.com/usemethod.html#Apollo)。

那麽它有什麽毛病呢?

現在的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時鐘周期。)

當然,還有數百個其他你可以用來測量的性能計數器。

如果在虛擬化環境中,guest一般不能直接訪問PMC,這取決於hypervisor是否支持。我最近寫的一篇The PMCsof EC2: Measuring(鏈接地址:http://www.brendangregg.com/blog/2017-05-04/the-pmcs-of-ec2.html) IPC展示了AWS EC2中基於Xen的虛擬機如何使用PMC。

最佳實踐

如果你的IPC小於1.0,你可能遇到了內存操作密集型,軟件調優策略可以有減少內存I/O,增強內存本地訪問性,尤其是在NUMA系統上。硬件調優策略則是使用CPU cache較大以及更快的內存、總線和內聯技術。

如果你的IPC > 1.0,你可能是指令密集型。可以試圖減少指令的執行數量,比如消除不必要的工作和緩存操作等,可以用一下CPU火焰圖(鏈接地址:http://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html)。硬件調優方面,可以嘗試高主頻、多核、超線程的CPU。

性能檢測產品應該告訴你什麽呢?

性能檢測工具都應該顯示出每個進程的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引起時鐘頻率變化;

  5. 一分鐘內的80%的平均利用率並不能表示100%的突發利用率(類似網絡QoS);

  6. 自旋鎖:CPU在很嚴肅地瞎忙;

Update: CPU利用率真的錯了嗎?


自這篇文章發布以後,留言討論非常激烈,已經有了上百條了。首先謝謝你們對這話題感興趣並花時間閱讀,但我在這裏還是要統一回復:我對disk的iowait並不關心(譯者註:PC CPU不能直接操作外部存儲),並且文中也已經給出了內存操作密集型的對應調優措施。

然而,CPU利用率到底是從本質上錯了還是僅僅是有誤導性了?我認為需要人將高CPU利用率視為處理單元的瓶頸的事兒,是錯的。那麽這個指標的計算方法從技術上講正確嗎?如果CPU在怠速期間不能被其他任何進程使用,那麽這不就是所謂的“使用等待”(聽起來有點矛盾)。某些情況下,%CPU作為一個操作系統層面的指標是技術正確但是容易誤導人的。在超線程中,怠速周期可以被其他線程使用,所以%CPU的算法也會將其算在內,而實際上並沒有利用。那樣是不對的,這篇文章中我強調的是解釋問題並提出對策,並且,這個指標也有技術上的問題。

結論

CPU利用率已成為一個極具誤導性的指標:它算進了等待主存的周期,而這類周期在現代的CPU負載中占據不少。如果使用額外指標,你就能搞清楚%CPU到底意味著什麽,包括每CPU周期執行指令數(IPC)。IPC < 1.0可能意味著你的應用是內存密集型,而IPC > 1.0則可能是指令密集型。我在之前的一篇文章,顯示%CPU的性能監控產品也應該顯示PMC測量指標,並給予充分解釋,這樣才不會誤導用戶。比如,它們可以一起顯示%CPU和IPC,或者指令周期與怠速周期。有了這些指標,開發或管理人員才能在應用和操作系統中選擇正確的調優方式。

譯者的話

本文翻譯自Brendan Gregg的博客文章《CPU Utilization is Wrong》,原文鏈接為http://www.brendangregg.com/blog/2017-05-09/cpu-utilization-is-wrong.html,就是那本《性能之巔(中譯)》的作者,調試工具dtrace的作者,現就職於NetFlix。

PS:為什麽要翻譯這個文章呢?因為很多時候總感覺PC的這個CPU利用率的百分比顯示沒能真實反應我的CPU到底忙不忙,在學校的時候用單片機也是算idle,但到了PC後隱約感覺這麽算不對,看了BG的文章後才恍然大悟。另外這篇文章之前已經被翻譯過,但作者又有更新,也挺有意思的,我就重新翻了一遍,並加了一些彈幕。

cpu 性能