JAVA 應用 CPU 使用率爲什麼飈升?

來自京東技術公衆號

作爲一個Java開發者,會不會有這樣的疑問?

  • 一個 while 死循環,會不會引起 CPU 使用率飈升?

  • 頻繁 Young GC 會不會引起 CPU 使用率飈升?

  • 線程數很高的應用,CPU 使用率一定高麼?

  • CPU 使用率高的應用,線程數一定高麼?

  • BLOCKED 狀態的線程會不會引起 CPU 使用率飈升?

  • 分時操作系統 CPU 是耗費 us ? 還是耗費 sy ?

1、CPU 使用率怎麼計算?

CPU% = 1 - idleTime / sysTime * 100

  • idleTime:CPU處於空閒狀態的時間

  • sysTime:CPU處於用戶態和內核臺的時間總和

2、CPU 使用率跟啥有關係?

常聽說計算密集型的程序是比較耗 CPU 使用率的。

那 JAVA 應用中哪些操作是比較耗 CPU 使用的?

列舉日常程序中常見的耗CPU的操作:

  • 頻繁GC,訪問量高時,有可能造成頻繁的GC、甚至FGC。當調用量大時,內存分配過快,就會造成GC線程不停的執行,導致CPU飆高

  • 序列化與反序列化,後文中舉了一個真實的案例,程序執行xml解析的時,調用量增大的情況下,導致了CPU被打滿

  • 加密、解密

  • 正則表達式校驗,曾經線上發生一次血案,正則校驗將CPU打滿。大概原因是:Java 正則表達式使用的引擎實現是 NFA 自動機,這種引擎在進行字符匹配會發生回溯(backtracking)

  • 線程上下文切換、當啓動了很多線程,而這些線程都處於不斷的阻塞狀態(鎖等待、IO等待等)和執行狀態的變化過程中。當鎖競爭激烈時,很容易出現這種情況

  • 某些線程在做無阻塞的運算,簡單的例子while(true)中不停的做運算,沒有任何阻塞。寫程序時,如果需要做很久的計算,可以適當將程序sleep下

3、CPU 與進程、線程有關係麼?

現在分時操作系統是通過循輪方式分配時間片進行進程調度的,如果進程在等待或阻塞,不會造成 CPU 資源使用。線程稱爲輕進程,共享進程資源,關於線程的調度,CPU 對於線程也是分時調度。而在 Java 中,線程的調用由 JVM 負責,線程的調度一般有兩種模式,分時調度和搶佔式調度。

解惑

1、一個 while 死循環,會不會引起 CPU 使用率飈升?

會的。

先不說別的,死循環會調用 CPU 寄存器進行計數,這個操作就會佔用 CPU。其次,如果線程一直處於死循環狀態,CPU 調用會進行線程切換麼?

死循環不會讓出 CPU,除非操作系統時間片到期,但死循環會不斷向系統申請時間片,直到系統沒有空閒時間做別的事情。

這個問題在 stackoverflow 也有人提問:why does an infinite loop of the unintended kind increase the CPU use?

地址:https://stackoverflow.com/questions/2846165/why-does-an-infinite-loop-of-the-unintended-kind-increase-the-cpu-use

2、頻繁 Young GC 會不會引起 CPU 使用率飈升?

 

會的。

Young GC 本身是 JVM 進行垃圾回收的操作,會計算內存和調用寄存器,頻繁 Young GC 一定是會佔用 CPU。

之前有個一個案例,for 循環從數據庫查詢數據集合,二次封裝新的數據集合,這時如果量比較大時,內存沒有足夠的空間存儲,那麼 JVM 就會 GC 回收那些不再使用的數據,因此量大的時候,就會收到 CPU 使用率報警。

3、線程數很高的應用,CPU 使用率一定高麼?

不會。

通過 jstack 查看系統線程狀態,查看整個線程數很多,但 Runable 和 Running 狀態的線程不多,這時 CPU 使用率不一定會高。

之前有過一個案例,查看系統線程數 1000+,jstack 分析 900多個線程是 BLOCKED 和 WAITING 狀態的,這種線程是不會佔用 CPU 的。

如果線程數很高,其實大多數原因是死鎖,大量線程處於 BLOCKED 和 WAITING 狀態。

4、CPU 使用率高的應用,線程數一定高麼?

不會。

同上,CPU 使用率高的關鍵因素還是計算密集型操作,一個線程如果有大量計算,也會造成 CPU 使用率高,也是現在爲什麼一個大數據腳本任務,要大規模集羣共同運算才能運行的原因。

5、BLOCKED 狀態的線程會不會引起 CPU 使用率飈升?

不一定。

CPU使用率的飆升,更多是因爲上下文的切換或者runnable狀態線程過多導致。Blocked狀態,未必會引起CPU上升。

6、分時操作系統 CPU us高或者sy高是什麼意思?

通過top命令,可以觀察到CPU的us,sy值,示例如下:

  • us 用戶空間佔用CPU百分比,簡單來說,us高是因爲程序導致的,通過分析線程堆棧,可以很容易的定位到問題線程。

  • sy 內核空間佔用CPU百分比,sy高的時候,如果是程序問題導致,基本是因爲線程上下文切換造成的。

經驗

平時怎麼定位 CPU 使用率高的原因?網上有個教程和方法,下面簡述一下分析過程。首先發現某臺應用 CPU 使用率高,一要看先線程數、JVM、系統 load 等參數,共同作證。二要打印 jstack,通過工具分析線程情況,推薦 fastThread 這個在線的 Thread 分析工具。

以下是線上發生的真實案例,簡要介紹下:

某日晚,突然收到短信報警,CPU利用率100%。立刻dump該機器jstack,通過 http://fastthread.io/ 查看日誌如下:

 

進一步查看具體日誌:

通過這段日誌,已經定位到了具體CPU被打滿的方法,接收MQ之後,MQ消息體爲xml,反序列化的時候,造成了CPU飆高。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章