什么會導致Java應用程序的CPU使用率飆升?


問題

無限循環的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自動機,它將在字符匹配期間執行回溯。我寫了一篇文章“ 正則表達式中的隱藏陷阱 ”來詳細解釋原因。
  • 線程上下文切換; 有許多已啟動的線程,這些線程的狀態在Blocked(鎖定等待,IO等待等)和Running之間發生變化。當鎖爭用激烈時,這種情況很容易發生。
  • 有些線程正在執行非阻塞操作,例如while (true)語句。如果在程序中計算需要很長時間,則可以使線程休眠。

3. CPU是否與進程和線程相關?

現在,分時操作系統使用循環方式為進程調度分配時間片。如果進程正在等待或阻塞,那么它將不會使用CPU資源。線程稱為輕量級進程,並共享進程資源。因此,線程調度在CPU中也是分時的。但在Java中,我們使用JVM進行線程調度。因此,通常,線程調度有兩種模式:時間共享調度和搶占式調度。

答案

1. while的無限循環會導致CPU使用率飆升嗎?

是。

首先,無限循環將調用CPU寄存器進行計數,此操作將占用CPU資源。那么,如果線程始終處於無限循環狀態,CPU是否會切換線程?

除非操作系統時間片到期,否則無限循環不會放棄占用的CPU資源,並且無限循環將繼續向系統請求時間片,直到系統沒有空閑時間來執行任何其他操作。

2.頻繁的Young GC會導致CPU占用率飆升嗎?

是。

Young GC本身就是JVM用於垃圾收集的操作,它需要計算內存和調用寄存器。因此,頻繁的Young GC必須占用CPU資源。

讓我們來看一個現實世界的案例。for循環從數據庫中查詢數據集合,然后再次封裝新的數據集合。如果內存不足以存儲,JVM將回收不再使用的數據。因此,如果所需的存儲空間很大,您可能會收到CPU使用率警報。

3.具有大量線程的應用程序的CPU使用率是否較高?

不時。

如果通過jstack檢查系統線程狀態時線程總數很大,但處於Runnable和Running狀態的線程數不多,則CPU使用率不一定很高。

我遇到過這樣一種情況:系統線程的數量是1000+,其中超過900個線程處於BLOCKED和WAITING狀態。該線程占用很少的CPU。

但是大多數情況下,如果線程數很大,那么常見的原因是大量線程處於BLOCKED和WAITING狀態。

4.對於CPU占用率高的應用程序,線程數是否較大?

不是。

高CPU使用率的關鍵因素是計算密集型操作。如果一個線程中有大量計算,則CPU使用率也可能很高。這也是數據腳本任務需要在大規模集群上運行的原因。

5.處於BLOCKED狀態的線程是否會導致CPU占用率飆升?

不會。

CPU使用率的飆升更多是由於上下文切換或過多的可運行狀態線程。處於阻塞狀態的線程不一定會導致CPU使用率上升。

6.如果分時操作系統中CPU的值us或sy值很高,這意味着什么?

您可以使用命令查找CPU的值us和sy值top,如以下示例所示:

image.png

us:用戶空間占用CPU的百分比。簡單來說,高我們是由程序引起的。通過分析線程堆棧很容易找到有問題的線程。
sy:內核空間占用CPU的百分比。當sy為高時,如果它是由程序引起的,那么它基本上是由於線程上下文切換。

經驗

如何找出CPU使用率高的原因?下面簡要描述分析過程。

如果發現應用程序服務器的CPU使用率很高,請首先檢查線程數,JVM,系統負載等參數,然后使用這些參數來證明問題的原因。其次,使用jstack打印堆棧信息並使用工具分析線程使用情況(建議使用fastThread,一個在線線程分析工具)。

以下是一個真實案例:

一天晚上,我突然收到一條消息,說CPU使用率達到了100%。然后我用jstack導出了線程棧信息。

image.png

進一步檢查日志:

onsumer_ODC_L_nn_jmq919_1543834242875 - priority:10 - threadid:0x00007fbf7011e000 - nativeid:0x2f093 - state:RUNNABLE
stackTrace:
java.lang.Thread.State:RUNNABLE
at java.lang.Object.hashCode(Native Method)
at java.util.HashMap.hash(HashMap.java:362)
at java.util.HashMap.getEntry(HashMap.java:462)
at java.util.HashMap.containsKey(HashMap.java:449)
at com.project.order.odc.util.XmlSerializableTool.deSerializeXML(XMLSerializableTool.java:100)
at com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:55)
at com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:21)
at com.project.plugin.service.message.resolver.impl.AbstractResolver.resolve(AbstractResolver.java:28)
at com.project.plugin.service.jmq.AbstractListener.onMessage(AbstractListener.java:44)
復制代碼

現在通過這個日志找到了問題:用於反序列化MQ消息實體的方法導致CPU使用率飆升。

看完三件事❤️

如果你覺得這篇內容對你還蠻有幫助,我想邀請你幫我三個小忙:

  1. 點贊,轉發,有你們的 『點贊和評論』,才是我創造的動力。

  2. 關注公眾號 『 java爛豬皮 』,不定期分享原創知識。

  3. 同時可以期待后續文章ing🚀

出處:club.perfma.com/article/186…

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM