首頁 > 科技

10分鐘掌握Java效能分析訣竅

2021-07-18 03:08:21

概要

Java效能分析是一門藝術和科學。科學指的是效能分析一般都包括大量的數字、測量和分析;藝術指的是知識、經驗和直覺的使用。效能分析的工具或者手段各有千秋,但效能的分析的過程卻都大相徑庭。本文就已知適用的Java效能分析竅門進行一些分享,幫助使用者更好的理解和運用。

竅門一:執行緒棧剖析

執行緒棧分析是對正在運行的Java執行緒的快照分析,是一種輕量級的分析手段,使用者在不清楚應用存在什麼效能問題的時候可優先嚐試。雖然判定Java執行緒是否異常並沒有統一的標準,但使用者可以通過一些指標進行定量的評估。以下分享4個檢測指標:

1)執行緒死鎖檢查 執行緒死鎖檢查是一個非常有價值的檢測指標。如果執行緒死鎖,則一般存在系統資源的浪費或服務能力下降等問題,一旦發現就需要及時處理。執行緒死鎖檢測會展示執行緒死鎖關係以及對應的棧資訊,通過分析即可定位到觸發死鎖的程式碼。如圖-1所示死鎖模型展示了一個複雜的4執行緒死鎖場景。

2)執行緒統計檢查 狀態統計是對運行的執行緒按照運行狀態進行的統計和彙總。使用者在不完全瞭解自己業務壓力的情況下,對於可用執行緒數一般會配置一個非常充裕的範圍,這樣反而會因為過多的執行緒導致效能下降或者系統資源耗盡。如圖-2所示,可以發現超過90%的執行緒處於阻塞和等待狀態,那麼適當優化執行緒數量是可以減少執行緒排程帶來的開銷以及不必要的資源浪費。

如圖-3所示,處於運行階段的執行緒數已經超過90%,進一步分析可能存線上程洩露的問題。同時,運行的執行緒太多,執行緒切換的開銷也是非常大的。

3)執行緒CPU使用率檢查 對各Java執行緒CPU使用情況進行統計和排序,針對CPU使用率極高的執行緒執行緒棧進行分析,可以快速定位到程式熱點。如圖-4所示,首個任務執行緒的CPU使用率達已經到100%,則開發人員可根據業務邏輯確定是否進行程式碼優化。

4)GC執行緒數檢查 GC執行緒數往往是容易被使用者忽視的指標。使用者在設定並行GC執行緒數的時候容易忽視系統的資源情況,或者隨意將應用部署在CPU核數較多的物理機。如圖-5所示,我們發現在一個4核8GB的容器中G1的併發收集執行緒數為9(一般情況下並行GC的執行緒數是GC任務執行緒數的1/4),也就是在GC發生的時候可能會出現9個並行的GC執行緒,這種情況下CPU資源會被短時間直接耗盡而系統和業務阻塞。所以在使用GC收集器(如CMS、 G1)的時候儘可能設定或者關注GC的執行緒數。

竅門二:GC日誌剖析

日誌分析是對Java程式GC收集記錄資料的分析,而這部分資料的收集是需要開啟特定選項的。所以,在啟動Java程式前一定要增加日誌參數(如JDK8:-Xloggc:logs/gc-%t.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps;JDK11:-Xlog:gc*:logs/gc-%t.log:time,uptime)。GC日誌分析的結果描述的是在過去一段時間內Java程式就記憶體回收的狀態。通過分析這些狀態資訊,使用者可以非常方便的獲得到GC參數甚至Java程式碼優化的指標資料。以下就3個分析指標進行展開:

1)GC的吞吐率 吞吐率描述的是在JVM運行時間段可用於業務處理的時間佔比,即非GC佔用時間。該值越大表示使用者GC佔用的時間越少,JVM效能越好。JVM內部指定該值不能低於90%,否則JVM本身所帶來的效能損耗就會嚴重影響業務效能。如圖-6所示是JDK8的CMS運行3小時左右的日誌分析結果,分析結果顯示其吞吐率超過99.2%,JVM(GC)導致的效能損耗是比較低的。

2)暫停時間統計 GC暫停時間指的是在GC過程中需要停止業務執行緒運行的時間,該時間需要在在一個合理的範圍內。如果絕大部分的暫停時間超過預期(使用者可以接受的範圍),則很有需要去調整GC參數以及堆大小,甚至設定並行GC執行緒數。如圖-7所示,95%以上的GC暫停時間是在40ms以內;而超過100ms的暫停可能是導致業務請求時間毛刺的主要因素。為了消除暫停時間波動問題,可以選擇如G1 GC或ZGC,或者調整並行執行緒數或者GC參數等。

3)GC階段散點圖 散點圖反映的是每一次GC操作釋放的記憶體大小的分佈情況。如圖-8所示,每次GC釋放的記憶體大小基本一致,說明記憶體釋放過程比較穩定。但如果出現比較大的波動或者出現比較多的Full GC則有可能是新生代區堆空間不足導致晉升量較大;如果每次GC的釋放量比較少有可能是G1 GC自適應演算法導致的新生代空間較小等等。因為散點圖展示的資料有限,所以一般需要結合其它指標以及使用者的JVM參數進行聯合分析。

竅門三:JFR事件剖析

JFR是Java Flight Record的縮寫,是JVM內建的基於事件的JDK監控記錄框架。社群中,JFR優先於OpenJDK11上釋出,後移植到OpenJDK8的較高版本260上,且沿用了統一的使用介面與操作命令jcmd。同時,由於JFR錄製一般對應用影響很小(預設開啟的效能影響在1%以內),適合長時間開啟;且JFR能收集到如Runtime、GC、執行緒棧、堆、IO等在內的豐富資訊,非常方便使用者瞭解Java程式的運行狀況。 JFR錄製的事件有100多種,如果程式複雜往往不到10分鐘錄製的JFR檔案大小就會超過500MB,所以使用者在分析時往往並不是所有的資訊都會關注。以下就業務效能中常見幾個做一下分享:

1)程序CPU佔用率 CPU取樣預設間隔是1s,基本能及時反映當前程序的CPU平均使用情況。在出現CPU持續偏高,或者CPU出現類似圖-9所示的CPU偶發飆高的情況時,都可以進行一定的檢測和分析。通過進一步定位,此處CPU飆高與GC觸發時間一致,初步確認是GC導致的CPU變化。

2)GC配置及暫停分佈 GC配置可以幫助我們瞭解到當前程序的GC收集器及其主要的配置參數,因為不用的收集器特性會不同,分析堆空間、觸發控制等參數也是非常重要的。控制參數可以幫助我們理解GC收集過程,比如圖-10所示的G1收集器,設定的最大堆為8GB,GC暫停時間在40ms左右(預設預期200ms),是遠低於預期值的。進一步分析參數發現設定了NewRatio值為2(對G1 GC不太熟悉的情況下,使用者很容易設定該參數),導致新生代區的GC觸發頻繁,而且從資料看未觸發混合GC。為了增加對堆空間的利用,可以移除NewRatio參數,增加新生代區的最大值比例(因為未觸發混合GC,說明堆回收時晉升量非常低),降低迴收塊的回收門檻等,進而增加對整堆的使用。通過優化,堆空間的使用從原來的4GB提高到7GB,YGC頻率從20s/次提高到平均40s/次,GC暫停時間沒有明顯變化。

3)方法取樣火焰圖 方法火焰圖是對呼叫方法取樣次數的統計,比例越大表示呼叫次數越多。因為取樣過程中有棧的完整資訊,對於使用者來說是非常比較直觀的,效能優化的幫助性大增。如圖-11所示,可以很清楚的看到GroupHeap.match執行次數比例接近30%,可以作為效能優化點。

4)IO讀寫效能 檢查IO效能多半是對程式處理效能出現突變的場景,比如下降或飆升。如從socket讀入的資料量飆升,導致處理業務的CPU飆高;或者因為需要寫出的資料變多,導致業務執行緒阻塞,處理能力下降等。如圖-11所示,可以通過讀取/寫入趨勢圖判斷在監控時間段的IO能力。

竅門四:堆內容剖析

堆內容分析是分析Java堆OOM(OutOfMemoryError)原因的常用手段。OOM主要有堆空間溢位、元空間溢位、棧空間溢位和直接記憶體溢位等,但並不是所有溢位情況都可以通過堆內容分析獲得。對於堆轉儲的檔案而言,記憶體溢位的可能性是不確定的,但可以通過一些定量的指標或者約定的條件作出判斷,再通過開發或者測試人員進行最後的確認。以下分享三個有價值的衡量指標:

1)大物件檢查 統計大物件分佈資訊可以幫助我們瞭解記憶體消耗在這部分物件上的比重,以及存在的大物件是否合理。過多的大物件無法釋放會更快的耗盡記憶體而出現OOM,相比全量的分析所有物件而言,大物件的檢查是具有代表性的,如圖-13所示。

2)類載入檢查 類載入統計主要統計的是程式當前載入的全部類資訊,是計算元空間佔用的重要資料。過多的載入類資訊也會導致元空間被大量佔用,在類似RPC場景下,快取載入類資訊是容易觸發OOM的。

3)物件洩露檢查 首先引入三個概念; 淺堆:一個物件所佔用的記憶體大小,和物件的內容無關,只和物件的結構有關。 深堆:一個物件被GC回收後,可以真實釋放的記憶體大小,即通過該物件訪問到的所有物件的淺堆之和(支配樹)。 支配樹:在物件的引用圖中,所有指向物件B的路徑都經過物件A,則認為物件A支配物件B;如果物件A是離物件B最近的一個支配物件,則認為物件A為物件B的直接支配者。 按照GC策略,堆中的物件只可能有兩種狀態,一種是通過GC的根可達的物件;另一種是通過GC根不可達的物件。不可達的物件會被GC收集器回收,對應的記憶體就會返回到系統中去。而可達物件都是被使用者直接或者間接引用的物件,所以物件洩露針對的就是被使用者間接引用但永遠不會被使用的物件,這些物件因為被引用而無法釋放。物件洩露不是絕對的,而是相對的,一般沒有確切的標準,但可以通過對物件的深堆大小進行評估。比如檢測到HashMap存放了4844個物件(如圖-14所示),計算HashMap淺堆約115KB,看到這裡可能覺得沒有什麼問題;但通過計算物件的深堆發現其超過500MB。這種情況下,如果無法釋放HashMap而持續增加新的鍵值就有可能導致堆記憶體耗盡而出現OOM。

想了解更多精彩內容,快來關注計算機java程式設計


IT145.com E-mail:sddin#qq.com