某測試模擬器性能優化-用vprof對Python程序性能調優
項目背景:
組裡的幾個同學最近在開發一個系統模擬器,當模擬20w節點在線的時候,發現有一個組件log_generator佔用CPU特別嚴重,經常出現佔用的CPU超過120%的情況。該組件使用的是多線程模型,所以雖然機器CPU是4核的,也無法利用其它CPU分擔負載。
考慮到我們下階段的目標是模擬100w節點同時在線,現在的模擬器性能肯定無法滿足要求,所以必須對該模擬器進行性能調優。
熟悉代碼:
為了解決這個問題,我首先把log_generator這個組件的代碼看了一遍。該組件同時訂閱10個不同的redis channel,將讀到的數據,寫成特定格式的日誌文件,供ELK讀取,然後再將這些數據寫入到不同kafka的topic中去。為了提高效率,該組件為每個redis channel啟動一個單獨的線程用於監聽,寫本地文件和寫kafka。
看完代碼後,初步懷疑兩個地方可能引起性能瓶頸,一個是監聽redis的channel寫日誌,一個是將讀取的內容寫到kafka中去。為了驗證自己的想法,開始著手對程序進行profiling.
vprof和火焰圖:
這裡,我選擇一個開源的性能分析工具vprof,原因是它可以很方便地生成火焰圖。火焰圖是類似下面的圖形,具體了解火焰圖,可以訪問《如何讀懂火焰圖》這篇文章。
安裝vprof很簡單
pip install vprofn
由於是多線程後台運行,如果要採集一段時間的性能統計數據,必須要讓子線程在一段時間內跟隨主線程退出,這個時候可以使用線程的t.setDaemon(True)方法,這樣,當主線程退出後,子線程也會自動停止運行。
收集性能數據可以使用
vprof -c cmh log_generator.pyn
這樣的命令,其中-c代表配置
配置裡面的c,表示cpu火焰圖,m表示內存圖,h表示代碼熱圖
當主程序退出後,vprof會自動收集這些數據,並且啟動一個http伺服器,自動打開瀏覽器將指定的圖表打開展示出來。
如果你是在遠程機器上收集數據,那麼可以通過下面的方法,先將數據收集為json文件,將其複製到本地,然後再在本地通過vprof展示結果。
vprof -c cmh log_generator.py --output-file profile.jsonnvprof --input-file profile.jsonn
分析結果:
通過vprof,我們採集到了log_generator組件的性能數據,發現有兩個函數的採樣特別多,一個是kafka相關的操作(包含requests操作),一個是根本就不可能用到的ORM模塊。
ORM這個問題特別不可思議,仔細看火焰圖上的調用關係,原來是誰不小心在公用的變數文件裡面定義了一個ORM操作的函數,當log_generator用from import *這樣的語句導入該文件的變數時,該ORM函數自動就被執行了~ 發現一個bug!
那麼requests操作為何有這麼多呢?原來是每次寫kafka的topic前,代碼都先通過http請求獲得該topic的schema格式,然後再進行編碼寫入。由於schema是不變的,所以完全沒有必要每次寫kafka都獲取一遍schema,此處也有bug,將其抽取到循環外面即可解決。
再次複測:
將修改後的代碼再次上機運行,發現log_generator組件還是有嚴重佔用CPU的情況,調優工作並未取得明顯的效果。
這才是真正的人生嘛,怎麼可能那麼簡單就解決問題的?
那,到底是什麼原因導致了log_generator組件的CPU佔用居高不下呢,且聽下回分解。
總結:
通過本文,您已基本了解如何使用vprof工具進行Python代碼性能調優了。
如果覺得本文對您有幫助,敬請點贊。
推薦閱讀:
※HiCircle的第一款產品TestBus beta版出來啦
※使用 iMacros 來自動化日常的工作
※手工測試如何轉向自動化測試
※自動化測試體系應該是什麼情形的?
※Python實踐-Python自動化測試常用庫整理