某測試模擬器性能優化-用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自動化測試常用庫整理

TAG:Python | 软件测试 | 自动化测试 |