我們對一個多線程系統通常需要知道:
- 系統的瓶頸所在
- 系統性能表現不佳(如響應慢、吞吐低)時如何優化
先做一個類比
某技術團隊
- 由100個開發人員組成
- 每個開發人員接到任務之后,都會按如下流程進行工作:
- 技術評審會
- 構思解決方案
- coding
- 測試
- bugfix
- merge代碼
- 上線
那么,管理者如何找到此團隊效率的瓶頸所在呢?方法很簡單:
假設管理者有一部神奇的照相機,能同時將100名開發人員拍下來
在拍照之后,管理者將100名開發人員正在做的事記錄下來,做整理后得到:
人數 工作內容
10 技術評審會
5 構思解決方案
15 coding
12 測試
8 bugfix
38 merge代碼
12 上線-
很顯然,管理者可以直接得出結論:
merge代碼是當前團隊的主要瓶頸,且約占整體時間的38 / 100 = 38% 員隊人數越多時這個比例估算的越準確
至于瓶頸是否合理,是否需要優化,就交給該管理者去做好了,我們回到主題
可見,擁有一部神奇的照相機是非常牛逼的
-
對上面的技術團隊而言:
用一部神奇相機記錄下某一瞬間所有人在做的事情,并統計他們各自在做些什么 然后找到哪件事在做的人最多,從而知道團隊效率的問題所在
-
對一個多線程系統而言:
將服務暫停,并將所有線程正在做的事情dump下來后再讓服務繼續,統計所有線程的邏輯,從而知道性能瓶頸所在
是不是很想擁有此技能?其實很簡單,現有的工具就可以幫助你做到這一點:
- jstack:適用于java進程,可以取到所以線程的堆棧dump
- pstack:適用于所有linux進程,是對gdb的功能封裝
實踐示例
實踐要點
- 此方法能定位大多常見的性能問題,但不要迷信
- 取stack dump會導致服務有一定時間的暫停,但通常較快,可以對線上服務執行
- 一些方法調用耗時較小時,取stack dump可能是抓不到的
- 可以給系統較大的壓力以使得更多線程在處理任務,此時用本文方法會更加快速準確
- 需要注意:同一個系統在不同的壓力下,瓶頸點可能不同
- jstack/pstack工具僅會給出dump的內容,而不會做統計,而dump的內容可能有幾萬行,查看起來不太方便。因此我寫了個腳本用來做統計處理,可參考使用,歡迎提交PR