1. 程式人生 > 實用技巧 >JVM效能監控工具

JVM效能監控工具

>>> hot3.png

效能監控工具

大綱:

n 系統性能監控

– 確定系統執行的整體狀態,基本定位問題所在

n Java自帶的工具

– 檢視Java程式執行細節,進一步定位問題

n 實戰分析

– 案例問題

系統性能監控- linux

uptime

n uptime

作用:查詢和定位問題程序 問題執行緒

185748_bx8k_3512041.png

– 系統時間

– 執行時間

• 例子中為7分鐘(系統執行時間是指系統從開機到現在一共運行了多長時間。)

– 連線數

• 每一個終端算一個連線

– 1,5,15分鐘內的系統平均負載

• 執行佇列中的平均程序數

Linux系統監控的過程中少不了對主機執行時間和系統負責等資訊進行查詢,這時候就可以使用Linux uptime命令。uptime命令可以顯示系統執行多久、當前有多少的使用者登入、在過去的1,5,15分鐘裡平均負載時多少。資訊顯示依次為:現在時間、系統已經運行了多長時間、目前有多少登陸使用者、系統在過去的1分鐘、5分鐘和15分鐘內的平均負載。

那麼什麼是系統平均負載呢? 系統平均負載是指在特定時間間隔內執行佇列中的平均程序數。

如果每個CPU核心的當前活動程序數不大於3的話,那麼系統的效能是良好的。如果每個CPU核心的任務數大於5,那麼這臺機器的效能有嚴重問題。

如果你的linux主機是1個雙核CPU的話,當Load Average(系統平均負載) 為6的時候說明機器已經被充分使用了。

top

n Top

作用:可以知道哪個程式佔CPU最多

185812_Cw2W_3512041.png

top命令是Linux下常用的效能分析工具,能夠實時顯示系統中各個程序的資源佔用狀況,類似於Windows的工作管理員。下面詳細介紹它的使用方法。top是一個動態顯示過程,即可以通過使用者按鍵來不斷重新整理當前狀態

.如果在前臺執行該命令,它將獨佔前臺,直到使用者終止該程式為止.比較準確的說,top命令提供了實時的對系統處理器的狀態監視.它將顯示系統中CPU敏感的任務列表.該命令可以按CPU使用.記憶體使用和執行時間對任務進行排序;而且該命令的很多特性都可以通過互動式命令或者在個人定製檔案中進行設定.

1命令格式:

top[引數]

2命令功能:

顯示當前系統正在執行的程序的相關資訊,包括程序ID、記憶體佔用率、CPU佔用率等

3命令引數:

-b批處理

-c顯示完整的治命令

-I忽略失效過程

-s保密模式

-S累積模式

-i<時間>設定間隔時間

-u<使用者名稱>指定使用者名稱

-p<程序號>指定程序

-n<次數>迴圈顯示的次數

vmstat

n vmstat

– 可以統計系統的CPU,記憶體,swap(虛擬記憶體),io等情況

185834_rheW_3512041.png

– CPU佔用率很高,上下文切換頻繁,說明系統有執行緒正在頻繁切換

命令:vmstat14

表示在1秒時間內進行4次取樣。將得到一個數據彙總他能夠反映真正的系統情況。

vmstat是VirtualMeomoryStatistics(虛擬記憶體統計)的縮寫可對作業系統的虛擬記憶體、程序、CPU活動進行監控。他是對系統的整體情況進行統計,不足之處是無法對某個程序進行深入分析。vmstat工具提供了一種低開銷的系統性能觀察方式。因為vmstat本身就是低開銷工具,在非常高負荷的伺服器上,你需要檢視並監控系統的健康情況,在控制視窗還是能夠使用vmstat輸出結果。在學習vmstat命令前,我們先了解一下Linux系統中關於實體記憶體和虛擬記憶體相關資訊。

實體記憶體和虛擬記憶體區別:

我們知道,直接從實體記憶體讀寫資料要比從硬碟讀寫資料要快的多,因此,我們希望所有資料的讀取和寫入都在記憶體完成,而記憶體是有限的,這樣就引出了實體記憶體與虛擬記憶體的概念

實體記憶體就是系統硬體提供的記憶體大小,是真正的記憶體,相對於實體記憶體,在linux下還有一個虛擬記憶體的概念,虛擬記憶體就是為了滿足實體記憶體的不足而提出的策略,它是利用磁碟空間虛擬出的一塊邏輯記憶體,用作虛擬記憶體的磁碟空間被稱為交換空間(SwapSpace)。

作為實體記憶體的擴充套件,linux會在實體記憶體不足時,使用交換分割槽的虛擬記憶體,更詳細的說,就是核心會將暫時不用的記憶體塊資訊寫到交換空間,這樣一來,實體記憶體得到了釋放,這塊記憶體就可以用於其它目的當需要用到原始的內容時,這些資訊會被重新從交換空間讀入實體記憶體

linux的記憶體管理採取的是分頁存取機制為了保證實體記憶體能得到充分的利用核心會在適當的時候將實體記憶體中不經常使用的資料塊自動交換到虛擬記憶體中而將經常使用的資訊保留到實體記憶體

要深入瞭解linux記憶體執行機制,需要知道下面提到的幾個方面:

首先,Linux系統會不時的進行頁面交換操作,以保持儘可能多的空閒實體記憶體即使並沒有什麼事情需要記憶體,Linux也會交換出暫時不用的記憶體頁面這可以避免等待交換所需的時間

其次,linux進行頁面交換是有條件的,不是所有頁面在不用時都交換到虛擬記憶體,linux核心根據”最近最經常使用“演算法,僅僅將一些不經常使用的頁面檔案交換到虛擬記憶體,有時我們會看到這麼一個現象:linux實體記憶體還有很多,但是交換空間也使用了很多。其實,這並不奇怪,例如,一個佔用很大記憶體的程序執行時,需要耗費很多記憶體資源,此時就會有一些不常用頁面檔案被交換到虛擬記憶體中,但後來這個佔用很多記憶體資源的程序結束並釋放了很多記憶體時,剛才被交換出去的頁面檔案並不會自動的交換進實體記憶體,除非有這個必要,那麼此刻系統實體記憶體就會空閒很多,同時交換空間也在被使用,就出現了剛才所說的現象了。關於這點,不用擔心什麼,只要知道是怎麼一回事就可以了。

最後,交換空間的頁面在使用時會首先被交換到實體記憶體,如果此時沒有足夠的實體記憶體來容納這些頁面,它們又會被馬上交換出去,如此以來,虛擬記憶體中可能沒有足夠空間來儲存這些交換頁面,最終會導致linux出現假宕機、服務異常等問題,linux雖然可以在一段時間內自行恢復,但是恢復後的系統已經基本不可用了。

因此,合理規劃和設計linux記憶體的使用,是非常重要的。

虛擬記憶體原理:

在系統中執行的每個程序都需要使用到記憶體,但不是每個程序都需要每時每刻使用系統分配的記憶體空間。當系統執行所需記憶體超過實際的實體記憶體,核心會釋放某些程序所佔用但未使用的部分或所有實體記憶體,將這部分資料儲存在磁碟上直到程序下一次呼叫,並將釋放出的記憶體提供給有需要的程序使用

在Linux記憶體管理中,主要是通過“調頁Paging”“交換Swapping”來完成上述的記憶體排程。調頁演算法是將記憶體中最近不常使用的頁面換到磁碟上把活動頁面保留在記憶體中供程序使用交換技術是將整個程序,而不是部分頁面,全部交換到磁碟上。

分頁(Page)寫入磁碟的過程被稱作Page-Out分頁(Page)從磁碟重新回到記憶體的過程被稱作Page-In。當核心需要一個分頁時,但發現此分頁不在實體記憶體中(因為已經被Page-Out了),此時就發生了分頁錯誤(PageFault)。

當系統核心發現可執行記憶體變少時,就會通過Page-Out來釋放一部分實體記憶體。經管Page-Out不是經常發生,但是如果Page-out頻繁不斷的發生,直到當核心管理分頁的時間超過執行程式的時間時,系統效能會急劇下降。這時的系統已經執行非常慢或進入暫停狀態,這種狀態亦被稱作thrashing(顛簸)。

1.命令格式:

vmstat[-a][-n][-Sunit][delay[count]]

vmstat[-s][-n][-Sunit]

vmstat[-m][-n][delay[count]]

vmstat[-d][-n][delay[count]]

vmstat[-pdiskpartition][-n][delay[count]]

vmstat[-f]

vmstat[-V]

2.命令功能:

用來顯示虛擬記憶體的資訊

3.命令引數:

-a:顯示活躍和非活躍記憶體

-f:顯示從系統啟動至今的fork數量。

-m:顯示slabinfo

-n:只在開始時顯示一次各欄位名稱。

-s:顯示記憶體相關統計資訊及多種系統活動數量。

delay:重新整理時間間隔。如果不指定,只顯示一條結果。

count:重新整理次數。如果不指定重新整理次數,但指定了重新整理時間間隔,這時重新整理次數為無窮。

-d:顯示磁碟相關統計資訊。

-p:顯示指定磁碟分割槽統計資訊

-S:使用指定單位顯示。引數有k、K、m、M,分別代表1000、1024、1000000、1048576位元組(byte)。預設單位為K(1024bytes)

-V:顯示vmstat版本資訊。

欄位說明:

Procs(程序):

r:執行佇列中程序數量

b:等待IO的程序數量

Memory(記憶體):

swpd:使用虛擬記憶體大小

free:可用記憶體大小

buff:用作緩衝的記憶體大小

cache:用作快取的記憶體大小

Swap:

si:每秒從交換區寫到記憶體的大小

so:每秒寫入交換區的記憶體大小

IO:(現在的Linux版本塊的大小為1024bytes)

bi:每秒讀取的塊數

bo:每秒寫入的塊數

系統:

in:每秒中斷數,包括時鐘中斷。

cs:每秒上下文切換數。

CPU(以百分比表示):

us:使用者程序執行時間(usertime)

sy:系統程序執行時間(systemtime)

id:空閒時間(包括IO等待時間),中央處理器的空閒時間。以百分比表示。

wa:等待IO時間

備註:如果r經常大於4,且id經常少於40,表示cpu的負荷很重。如果pi,po長期不等於0,表示記憶體不足。如果disk經常不等於0,且在b中的佇列大於3,表示io效能不好。Linux在具有高穩定性、可靠性的同時,具有很好的可伸縮性和擴充套件性,能夠針對不同的應用和硬體環境調整,優化出滿足當前應用需要的最佳效能。因此企業在維護Linux系統、進行系統調優時,瞭解系統性能分析工具是至關重要的。

pidstat

n pidstat

細緻觀察程序

– 需要安裝

• sudo apt-get install sysstat

– 監控CPU

– 監控IO

– 監控記憶體

簡介

pidstat主要用於監控全部或指定程序佔用系統資源的情況,如CPU,記憶體、裝置IO、任務切換、執行緒等。pidstat首次執行時顯示自系統啟動開始的各項統計資訊,之後執行pidstat將顯示自上次執行該命令以後的統計資訊。使用者可以通過指定統計的次數和時間來獲得所需的統計資訊。

執行pidstat,不加引數,將輸出系統啟動後所有活動程序的cpu統計資訊。使用-u選項,pidstat將顯示各活動程序的cpu使用統計,執行”pidstat -u”與單獨執行”pidstat”的效果一樣。

引數使用示例及列印結果講解:

185903_vBMD_3512041.png

· PID- 被監控的任務的程序號

· %usr- 當在使用者層執行(應用程式)時這個任務的cpu使用率,和 nice 優先順序無關。注意這個欄位計算的cpu時間不包括在虛擬處理器中花去的時間。

· %system- 這個任務在系統層使用時的cpu使用率。

· %guest- 任務花費在虛擬機器上的cpu使用率(執行在虛擬處理器)。

· %CPU- 任務總的cpu使用率。在SMP環境(多處理器)中,如果在命令列中輸入-I引數的話,cpu使用率會除以你的cpu數量。

· CPU- 正在執行這個任務的處理器編號。

· Command- 這個任務的命令名稱。

通過使用-t引數來顯示每個執行緒的記憶體使用情況。

185924_y57v_3512041.png

通過使用-d引數來得到I/O的統計資料。

185936_K77x_3512041.png

IO 輸出會顯示一些內的條目:

· kB_rd/s- 任務從硬碟上的讀取速度(kb)

· kB_wr/s- 任務向硬碟中的寫入速度(kb)

· kB_ccwr/s- 任務寫入磁碟被取消的速率(kb)

使用-r標記你能夠得到記憶體使用情況的資料。

185945_Q8Qe_3512041.png

重要的條目:

· minflt/s- 從記憶體中載入資料時每秒出現的小的錯誤的數目,這些不要求從磁碟載入記憶體頁面。

· majflt/s- 從記憶體中載入資料時每秒出現的較大錯誤的數目,這些要求從磁碟載入記憶體頁面。

· VSZ- 虛擬容量:整個程序的虛擬記憶體使用(kb)

· RSS- 長期記憶體使用:任務的不可交換實體記憶體的使用量(kb)

系統性能監控 - windows

工作管理員

190001_T4aM_3512041.png

定製工作管理員顯示的列資訊:

190007_s5Zy_3512041.png

Perfmon(效能監視器)

n Perfmon

– Windows自帶多功能效能監控工具

190019_jJcI_3512041.png

開啟效能監視器:

方式一:執行命令

  1、開啟執行命令,輸入perfmon.msc後按回車鍵;

190033_z4Vi_3512041.png

  2、在效能監視器主介面,點選選擇左側的效能監視器,即可檢視實時資訊。

方式二:開始選單

190054_Zm0c_3512041.png

  點開開始選單,找到並點開Windows管理工具,然後找到並點選效能監視器即可開啟相同視窗。

使用效能監視器:

新增計數器:

190055_Vg8l_3512041.png

190104_fwZd_3512041.png

生成報告:

190110_tvCT_3512041.png

Process Explorer(程序資源管理器)

Process Explorer可以看成是一個加強版的工作管理員。在較早的Windows版本中,工作管理員提供的功能是非常簡單的(比如檢視CPU、記憶體的使用情況,強制結束程序等),很難滿足我們高階一些的需求。在這種情況下,Process Exploere就應運而生了,大大的方便了我們工作中監測程序和排除故障的工作。

190126_OswF_3512041.png

190135_QqoU_3512041.png

1. 替換工作管理員

Process Explorer提供了相對與工作管理員更加強大實用的功能,所以有的時候就會想著直接把工作管理員給替換掉得了。Process Explorer提供了這樣一個功能,可以在使用者觸發開啟工作管理員的操作的時候直接開啟Process Explorer。下載地址

操作步驟:

Options -> Replace Task Manager
190150_VpXh_3512041.png

之後在我們執行Win+Esc、Ctrl+Shift+Del的時候開啟的就是Process Explorer了。

2. 檢視當前系統中執行的程序

Process Explorer對程序以樹形圖的形式進行展示,這樣方便我們觀察父子程序之間的關係。從這裡我們可以看出來,絕大部分的窗體應用程式都是explorer.exe的子程序,大部分的後臺程序都在services.exe下面:
190231_V7nT_3512041.png

Process Explorer會以不同的顏色標示不同狀態的程序,比如:
190215_ooqM_3512041.png

· 淺藍色: 和Process Explorer屬於同一個使用者的程序。

· 粉紅色: 服務程序,通常會包含一個或多個Windows服務。

· 黃色: .NET程序。

· 深灰色: 掛起的程序。

· 紫色: 標識包含壓縮或者加密的可執行程式碼的程序。一些病毒軟體經常會利用這種方式繞過防毒軟體。

· 紅色: 剛剛退出的程序。

我們還可以通過右鍵點選右側列頭選擇顯示我們感興趣的屬性:
190237_Bbti_3512041.png

3. 檢視程序的詳細資訊

如果我們對某個程序的感興趣,我們可以雙擊這個程序檢視它的詳細資訊:
ProcessInfo.jpg

這裡值得一提的是Command line和Current directory這兩個屬性。

Command line: 啟動程序的時候呼叫的命令。從這裡我們可以瞭解怎麼樣去呼叫這個程序,和有關當前程序啟動的詳細資訊。

Current directory: 當前程序活動所在的資料夾。

4. 檢視檔案正在被什麼程序佔用

我們在操作檔案(刪除、重新命名等)的時候遇到錯誤提示,說檔案正在被其他程序佔用,無法執行操作。這個時候可以開啟Process Explorer對檔案進行查詢:

Ctrl + f

190240_6D77_3512041.png

輸入要查詢的檔名就可以看到有那些程序正在使用這個檔案了: Search File

雙擊搜到的程序Process Explorer會在下面高亮顯示出對應的檔案控制代碼。從這裡我們可以強制關閉對應的控制代碼以達到不讓檔案被繼續佔用的目的。

5. 實時監控系統的效能

通過View -> System Info我們可以開啟Performance視窗檢視過去一段時間內系統的效能資料:
190255_wivt_3512041.png

我們也可以通過設定把感興趣的效能資料固定在工作列裡顯示:
190317_Dycw_3512041.png

6. 獲取Dump檔案

借用百度百科的介紹,Dump檔案是程序的記憶體映象。通常在程序沒有反應或者崩潰的時候我們需要藉助Dump檔案來分析程序裡面發生了什麼。 Process Explorer提供了一個快捷的方式來獲取Dump檔案:
190325_ygFZ_3512041.png

右鍵點選程序 -> Create Dump

我們可以根據需要選擇獲取最小的dump還是完整的dump檔案。

7. 程序操作

Process Explorer提供了很多程序級別的操作:
190321_3RNs_3512041.png

8. 安全驗證

Process Explorer提供了強大的程序檢視功能幫助我們對程序資訊的合法性進行檢驗,包括:

· 程序簽名

· 程序路徑

· 執行路徑

· …

9. 設定Symbols顯示更詳細的堆疊資訊

設定Symbol之前:
190333_iDwI_3512041.png

設定Symbol之後:
190342_VQYj_3512041.png

pslist

n pslist

– 命令列工具

– 可用於自動化資料收集

– 顯示java程式的執行情況

190351_3OFD_3512041.png

190401_k1g1_3512041.png

Java自帶的工具

190410_C4Dp_3512041.png

190418_yQii_3512041.png

jps

n jps

– 列出java程序,類似於ps命令

– 引數-q可以指定jps只輸出程序ID ,不輸出類的短名稱

– 引數-m可以用於輸出傳遞給Java程序(主函式)的引數

– 引數-l可以用於輸出主函式的完整路徑

– 引數-v可以顯示傳遞給JVM的引數

190429_82Cr_3512041.png

190440_H13z_3512041.png

jinfo

n jinfo

– 可以用來檢視正在執行的Java應用程式的擴充套件引數,甚至支援在執行時,修改部分引數

– -flag <name>:列印指定JVM的引數值

– -flag [+|-]<name>:設定指定JVM引數的布林值

– -flag <name>=<value>:設定指定JVM引數的值

– 執行時引數修改,功能比較有限

190448_dVMh_3512041.png

jmap

n jmap

生成Java應用程式的堆快照和物件的統計資訊

jmap -histo 2972 >c:\s.txt

190457_46Ze_3512041.png

Dump堆

jmap -dump:format=b,file=c:\heap.hprof 2972

190512_mE35_3512041.png

jstack

n jstack

– 列印執行緒dump

– -l 列印鎖資訊

– -m 列印java和native的幀資訊

– -F 強制dump,當jstack沒有響應時使用

n jstack 120 >>C:\a.txt

"main" #1 prio=6 os_prio=0 tid=0x0831c400 nid=0xecc runnable [0x0018f000]

java.lang.Thread.State: RUNNABLE

at org.eclipse.swt.internal.win32.OS.WaitMessage(Native Method)

at org.eclipse.swt.widgets.Display.sleep(Display.java:4657)

at org.eclipse.ui.application.WorkbenchAdvisor.eventLoopIdle(WorkbenchAdvisor.java:364)

at org.eclipse.ui.internal.ide.application.IDEWorkbenchAdvisor.eventLoopIdle(IDEWorkbenchAdvisor.java:917)

at org.eclipse.ui.internal.Workbench$3.eventLoopIdle(Workbench.java:487)

at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:1117)

at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)

at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:997)

at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:140)

at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:611)

at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)

at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:567)

at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:150)

at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:124)

at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)

at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)

at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)

at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:354)

at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:181)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

at java.lang.reflect.Method.invoke(Unknown Source)

at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:636)

at org.eclipse.equinox.launcher.Main.basicRun(Main.java:591)

at org.eclipse.equinox.launcher.Main.run(Main.java:1450)

JConsole

n JConsole

– 圖形化監控工具

– 可以檢視Java應用程式的執行概況,監控堆資訊、永久區使用情況、類載入情況等

190525_8H65_3512041.png

190535_z4Ly_3512041.png

190545_DyMq_3512041.png

190550_zUol_3512041.png

Visual VM

n Visual VM

– Visual VM是一個功能強大的多合一故障診斷和效能監控的視覺化工具

190601_Qt6a_3512041.png

190613_CLIS_3512041.png

190625_CRv8_3512041.png

190629_ybDm_3512041.png

190637_Ugvi_3512041.png

實戰分析

(java自帶工具)執行一程式ThreadBlockMain,期望輸出Hello,World ,結果在程式執行後,程式卡死,沒有預期輸出。

n 執行一程式ThreadBlockMain,期望輸出Hello,World ,結果在程式執行後,程式卡死,沒有預期輸出。

190646_RbcH_3512041.png

程序匯出檔案的內容:(程式卡在socket相關的io上了)

190658_vS03_3512041.png

(Linux+java自帶工具)Java程式HoldCPUMain執行後,發現佔用CPU很高,希望能找到原因。

n Java程式HoldCPUMain執行後,發現佔用CPU很高,希望能找到原因。

190704_nMQz_3512041.png

190717_wnIN_3512041.png

190729_dvVV_3512041.png

接下來,到HoldCPUMain.java檔案,看一下它的第8行做了些什麼,導致CPU佔用很高。

死鎖

n 死鎖

n 死鎖的結果是,程式卡死

n 可以用jstack查詢死鎖

4輛小汽車,相互堵住了去路,結果誰也無法前進。

如何從jstack的輸出中找出死鎖?

有時候,即使沒有死鎖,但是持有鎖的執行緒發生等待也會阻塞請求該鎖的執行緒

轉載於:https://my.oschina.net/kangxi/blog/1823454