標籤:
在開發過程中經常會出現這樣那樣的效能問題,讓人很糾結,下面我會列舉一些常用的效能調試手段來找出對應的效能問題的原因
一、CPU過高
這是最常發生的讓人很糾結的問題,CPU 100%了 ,但到底是什麼引發的呢?
使用Jprofiler之類的工具可以查看CPU問題,能列出CPU具體堆棧,但是有個問題是Jprofiler本身會佔用很高的CPU,用Jprofiler來查看CPU問題的時候會很不靠譜。
下面介紹一些比較簡單的查看CPU高的方法。
首先來看哪些線程佔用了最多的CPU
(1)ps -eLo pid,lwp,pcpu | grep <pid>|sort -nk 3
該方法可以找到CPU佔用前3的線程
(2) top -H
該方法能列出佔用最高的那些線程
通過上述方法可以知道有問題的線程的pid,然後將該線程號由10進位改為16進位。
接下來來看線程的堆棧
jstack -l <pid>
該方法打出進程的所有線程堆棧,尋找16進位的線程號,nid=0x17a1 這個就是線程號的位置
比如
"FelixStartLevel-SendThread(db-3.photo.163.org:2181)" daemon prio=10 tid=0x00007fba6406a800 nid=0x17a1 runnable [bidw:0x000000004027c000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:228)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:83)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87)
- locked <0x00007fba7d9c2d80> (a sun.nio.ch.Util$1)
- locked <0x00007fba7d9c31c0> (a java.util.Collections$UnmodifiableSet)
- locked <0x00007fba7d9c2dd8> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:98)
at org.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1107)
Locked ownable synchronizers:
- None
這個jstack只是一個採樣的方法,看當前線程執行的位置。
但我們可以假設在CPU100%的情況下,你基本上採樣都是在出問題的語句上。因此這個堆棧的第一行
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
就是CPU出問題的地方。可以多用jstack採樣幾次 ,看看是否都在同一個地方。
這個方法很簡單,屢試不爽,也不需要安裝軟體,方便使用。
二、記憶體OOM
記憶體OOM是大家常見的問題,線上遇到OOM不要慌,別先記著重啟,第一步先把記憶體堆棧列印出來
jmap -dump:live,format=b,file=<filename>
如果線上經常經常出現OOM問題也可以在JVM參數裡加上-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<filePath> 在進程OOM時自動dump出記憶體堆棧
有了記憶體堆棧就好辦了,給大家介紹個工具MAT,是我覺得最好用的記憶體分析工具http://www.eclipse.org/mat/
leak suspects協助你分析記憶體泄露可能的地方,像我上面的例子就看出ShutDownHook有問題,溢出了
但是溢出的對象從哪裡來,可以在details中點擊list objects-> Incoming references
就能夠看到引用對象的引用來源,這樣就一目瞭然了哪裡有泄露
三、控制代碼泄露
這是大部分java開發人員不太會關心的一個問題,寫過C程式的開發人員會比較容易重視這個問題。正因為不重視所以還是很容易出現的。
大部分的監控平台都有CPU、記憶體、硬碟的監控,但很多沒有控制代碼的監控。最後程式發生too many open files了,卻不知道。
控制代碼泄露的查看方式很簡單,可以用lsof -p <pid>,查看進程所佔用的所有控制代碼,當控制代碼泄露的時候肯定會有部分控制代碼出現極為異常的數量。
lsof -p 6022
java 6022 fs 1w REG 8,8 5006 3014678 /home/xxx/log.log
java 6022 fs 2w REG 8,8 5006 3014678 /home/xxx/log.log
需要仔細檢查控制代碼佔用過多的檔案代碼是否有問題。
我之前就發生過一次控制代碼泄露。也是代碼寫的有問題(第三方軟體內部源碼沒研究透),不斷重複開FileInputStream而沒有複用,導致控制代碼泄露。哎。。。沒監控,搞得很大個事
效能問題大家都容易碰到,分享一些個人的心得,協助大家定位效能問題。大家有更好的方法也告訴我。
常用效能調試手段