效能優化-CPU佔用過高問題排查
阿新 • • 發佈:2018-11-02
1. 效能優化是什麼?
1.1 效能優化就是發揮機器本來的效能
1.2 效能瓶頸在哪裡,木桶效應。
CPU佔用過高
1、現象重現
CPU佔用過高一般情況是程式碼中出現了迴圈呼叫,最容易出現的情況有幾種:
a)遞迴呼叫,退出機制設計的不夠合理;
b)定時器啟動過頻繁;
c)程式碼出現死迴圈
GC頻繁也可能導致CPU佔用過高
我用最簡單的死迴圈來舉例:
2、定位方法
首先可以確定佔用CPU的程序pid為21270
然後按shift + h 可以切換成tid(執行緒id)
可以看到佔用cpu的tid為21318
也可以用命令# top -H -p21270 說明: -H 指顯示執行緒,-p 是指定程序
或者用命令ps -mp pid -o THREAD,tid,time 檢視pid的執行緒
再將得到的tid轉換成16進位制
printf %x 21318 得到 5346
執行
jstack -l pid > test.txt
得到執行緒資訊
然後再在test.txt中查詢5346會看到一個nid=ox5346的異常資訊
這裡可以很清晰的看到是TestController類的28行有問題(此處是一個死迴圈)
以上是一次程式碼導致cpu佔用過高的問題排查過程
GC過於頻繁也會導致CPU佔用過高
===================================待完善===============================================
2. 效能的幾個唯度
2.1 CPU
2.2 Memory
2.3 IO
2.4 network 網路
2.1
命令 vmstat
http://www.man7.org/linux/man-pages/man8/vmstat.8.html
首先檢查 cpu,cpu 使用率要提升而不是降低
CPU 空閒並不一定是沒事做,也有可能是鎖或者外部資源瓶頸。
命令 Top
http://man7.org/linux/man-pages/man1/top.1.html
2.2 Memory
命令 free -h
http://www.man7.org/linux/man-pages/man1/free.1.html
2.3 IO
命令 iostat -dx 1
http://www.man7.org/linux/man-pages/man1/iostat.1.html
rrqm/s:佇列中每秒鐘合併的讀請求數量
wrqm/s:佇列中每秒鐘合併的寫請求數量
r/s:每秒鐘完成的讀請求數量
w/s:每秒鐘完成的寫請求數量
rsec/s:每秒鐘讀取的扇區數量
wsec/s:每秒鐘寫入的扇區數量
avgrq-sz:平均請求扇區的大小
avgqu-sz:平均請求佇列的長度
await:平均每次請求的等待時間
svctm:平均每次請求的服務時間
util:裝置的利用率
注:建議對照原始碼來記憶這些引數都是如何計算出來的。
2.4 Network
命令 nicstat (需要安裝)
wget http://sourceforge.net/projects/nicstat/files/nicstat-1.92.tar.gz
tar -zxvf nicstat-1.92.tar.gz
sudo vim Makefile
CFLAGS = $(COPT) -m32#將此行修改為如下:
CFLAGS = $(COPT)
sudo make -f Makefile install
3. 術語
吞吐量:對單位時間內完成的工作量的度量
平均響應時間:提交請求和返回該請求的響應之間使用的時間
平均響應時間越短,系統吞吐量越大;平均響應時間越長,系統吞吐量越
小;但是,系統吞吐量越大,未必平均響應時間越短;因為在某些情況(例
如,不增加任何硬體配置)吞吐量的增大,有時會把平均響應時間作為犧牲,
來換取一段時間處理更多的請求。
4、top找到CPU過高的那行程式碼
4.1、top 找到Pid,shift+h,找到tid
4.2、jstack pid > p.txt 匯出執行緒dump
4.3、把執行緒號找到16進位制 printf "%x \n" tid
4.4、在p.txt中找到16進位制對應的執行緒資訊
5、heap記憶體分析
jmap -heap 23451
jmap -dump:format=b,file=aa 23451
獲取檔案之後使用MAT去檢視記憶體被佔用的物件。
http://www.importnew.com/28916.html
while (true){ ... }執行後用top 命令檢視系統情況 這個時候可以看大pid 21270 的程序 cpu佔用率為100% 這裡有一個小細節,就是總體cpu佔用率卻為6.8 原因是伺服器為多核的,而示例程式碼為單執行緒,只會一直佔用其中一核 假如在while 裡面不斷建立執行緒就會把整個CPU佔滿
while (true){ Thread thread = new Thread(new MyRunnable()); thread.start(); }