
原文來源 | Huy Nguyen
譯文來源 | 開源中國
雖然你所寫的每個Python程序并不總是需要嚴密的性能分析,但是當這樣的問題出現(xiàn)時,如果能知道Python生態(tài)系統(tǒng)中的許多種工具,這樣總是可以讓人安心的。
分析一個程序的性能可以歸結(jié)為回答4個基本的問題:
1.它運行的有多塊?
2.那里是速度的瓶頸?
3.它使用了多少內(nèi)存?
4.哪里發(fā)生了內(nèi)存泄漏?
下面,我們將用一些很酷的工具,深入細節(jié)的回答這些問題。
使用time工具粗糙定時
首先,我們可以使用快速然而粗糙的工具:古老的unix工具time,來為我們的代碼檢測運行時間。
上面三個輸入變量的意義在文章 stackoverflow article 中有詳細介紹。簡單的說:
real – 表示實際的程序運行時間
user – 表示程序在用戶態(tài)的cpu總時間
sys – 表示在內(nèi)核態(tài)的cpu總時間
通過sys和user時間的求和,你可以直觀的得到系統(tǒng)上沒有其他程序運行時你的程序運行所需要的CPU周期。
若sys和user時間之和遠遠少于real時間,那么你可以猜測你的程序的主要性能問題很可能與IO等待相關(guān)。
使用計時上下文管理器進行細粒度計時
我們的下一個技術(shù)涉及訪問細粒度計時信息的直接代碼指令。這是一小段代碼,我發(fā)現(xiàn)使用專門的計時測量是非常重要的:
timer.py
為了使用它,你需要用Python的with關(guān)鍵字和Timer上下文管理器包裝想要計時的代碼塊。它將會在你的代碼塊開始執(zhí)行的時候啟動計時器,在你的代碼塊結(jié)束的時候停止計時器。
這是一個使用上述代碼片段的例子:
我經(jīng)常將這些計時器的輸出記錄到文件中,這樣就可以觀察我的程序的性能如何隨著時間進化。
使用分析器逐行統(tǒng)計時間和執(zhí)行頻率
Robert Kern有一個稱作line_profiler的不錯的項目,我經(jīng)常使用它查看我的腳步中每行代碼多快多頻繁的被執(zhí)行。
想要使用它,你需要通過pip安裝該python包:
一旦安裝完成,你將會使用一個稱做“l(fā)ine_profiler”的新模組和一個“kernprof.py”可執(zhí)行腳本。
想要使用該工具,首先修改你的源代碼,在想要測量的函數(shù)上裝飾@profile裝飾器。不要擔心,你不需要導入任何模組。kernprof.py腳本將會在執(zhí)行的時候?qū)⑺詣拥刈⑷氲侥愕哪_步的運行時。
primes.py
一旦你已經(jīng)設置好了@profile裝飾器,使用kernprof.py執(zhí)行你的腳步。
-l選項通知kernprof注入@profile裝飾器到你的腳步的內(nèi)建函數(shù),-v選項通知kernprof在腳本執(zhí)行完畢的時候顯示計時信息。上述腳本的輸出看起來像這樣:
尋找具有高Hits值或高Time值的行。這些就是可以通過優(yōu)化帶來最大改善的地方。
程序使用了多少內(nèi)存?
現(xiàn)在我們對計時有了較好的理解,那么讓我們繼續(xù)弄清楚程序使用了多少內(nèi)存。我們很幸運,F(xiàn)abian Pedregosa模仿Robert Kern的line_profiler實現(xiàn)了一個不錯的內(nèi)存分析器。
首先使用pip安裝:
(這里建議安裝psutil包,因為它可以大大改善memory_profiler的性能)。
就像line_profiler,memory_profiler也需要在感興趣的函數(shù)上面裝飾@profile裝飾器:
想要觀察你的函數(shù)使用了多少內(nèi)存,像下面這樣執(zhí)行:
一旦程序退出,你將會看到看起來像這樣的輸出:
line_profiler和memory_profiler的IPython快捷方式
memory_profiler和line_profiler有一個鮮為人知的小竅門,兩者都有在IPython中的快捷命令。你需要做的就是在IPython會話中輸入以下內(nèi)容:
在這樣做的時候你需要訪問魔法命令%lprun和%mprun,它們的行為類似于他們的命令行形式。主要區(qū)別是你不需要使用@profiledecorator來修飾你要分析的函數(shù)。只需要在IPython會話中像先前一樣直接運行分析:
這樣可以節(jié)省你很多時間和精力,因為你的源代碼不需要為使用這些分析命令而進行修改。
內(nèi)存泄漏在哪里?
cPython解釋器使用引用計數(shù)做為記錄內(nèi)存使用的主要方法。這意味著每個對象包含一個計數(shù)器,當某處對該對象的引用被存儲時計數(shù)器增加,當引用被刪除時計數(shù)器遞減。當計數(shù)器到達零時,cPython解釋器就知道該對象不再被使用,所以刪除對象,釋放占用的內(nèi)存。
如果程序中不再被使用的對象的引用一直被占有,那么就經(jīng)常發(fā)生內(nèi)存泄漏。
查找這種“內(nèi)存泄漏”最快的方式是使用Marius Gedminas編寫的objgraph,這是一個極好的工具。該工具允許你查看內(nèi)存中對象的數(shù)量,定位含有該對象的引用的所有代碼的位置。
一開始,首先安裝objgraph:
一旦你已經(jīng)安裝了這個工具,在你的代碼中插入一行聲明調(diào)用調(diào)試器:
最普遍的對象是哪些?
在運行的時候,你可以通過執(zhí)行下述指令查看程序中前20個最普遍的對象:
哪些對象已經(jīng)被添加或刪除?
我們也可以查看兩個時間點之間那些對象已經(jīng)被添加或刪除:
誰引用著泄漏的對象?
繼續(xù),你還可以查看哪里包含給定對象的引用。讓我們以下述簡單的程序做為一個例子:
想要看看哪里包含變量x的引用,執(zhí)行objgraph.show_backref()函數(shù):
該命令的輸出應該是一副PNG圖像,保存在/tmp/backrefs.png,它看起來是像這樣:
在運行的時候,你可以通過執(zhí)行下述指令查看程序中前20個最普遍的對象:最下面有紅字的盒子是我們感興趣的對象。我們可以看到,它被符號x引用了一次,被列表y引用了三次。如果是x引起了一個內(nèi)存泄漏,我們可以使用這個方法,通過跟蹤它的所有引用,來檢查為什么它沒有自動的被釋放。
回顧一下,objgraph 使我們可以:
顯示占據(jù)python程序內(nèi)存的頭N個對象
顯示一段時間以后哪些對象被刪除活增加了
在我們的腳本中顯示某個給定對象的所有引用
努力與精度
在本帖中,我給你顯示了怎樣用幾個工具來分析python程序的性能。通過這些工具與技術(shù)的武裝,你可以獲得所有需要的信息,來跟蹤一個python程序中大多數(shù)的內(nèi)存泄漏,以及識別出其速度瓶頸。
對許多其他觀點來說,運行一次性能分析就意味著在努力目標與事實精度之間做出平衡。如果感到困惑,那么就實現(xiàn)能適應你目前需求的最簡單的解決方案。
參考
stack overflow – time explained(堆棧溢出 – 時間解釋)
line_profiler(線性分析器)
memory_profiler(內(nèi)存分析器)
objgraph(對象圖)
end
數(shù)據(jù)分析咨詢請掃描二維碼
若不方便掃碼,搜微信號:CDAshujufenxi
LSTM 模型輸入長度選擇技巧:提升序列建模效能的關(guān)鍵? 在循環(huán)神經(jīng)網(wǎng)絡(RNN)家族中,長短期記憶網(wǎng)絡(LSTM)憑借其解決長序列 ...
2025-07-11CDA 數(shù)據(jù)分析師報考條件詳解與準備指南? ? 在數(shù)據(jù)驅(qū)動決策的時代浪潮下,CDA 數(shù)據(jù)分析師認證愈發(fā)受到矚目,成為眾多有志投身數(shù) ...
2025-07-11數(shù)據(jù)透視表中兩列相乘合計的實用指南? 在數(shù)據(jù)分析的日常工作中,數(shù)據(jù)透視表憑借其強大的數(shù)據(jù)匯總和分析功能,成為了 Excel 用戶 ...
2025-07-11尊敬的考生: 您好! 我們誠摯通知您,CDA Level I和 Level II考試大綱將于 2025年7月25日 實施重大更新。 此次更新旨在確保認 ...
2025-07-10BI 大數(shù)據(jù)分析師:連接數(shù)據(jù)與業(yè)務的價值轉(zhuǎn)化者? ? 在大數(shù)據(jù)與商業(yè)智能(Business Intelligence,簡稱 BI)深度融合的時代,BI ...
2025-07-10SQL 在預測分析中的應用:從數(shù)據(jù)查詢到趨勢預判? ? 在數(shù)據(jù)驅(qū)動決策的時代,預測分析作為挖掘數(shù)據(jù)潛在價值的核心手段,正被廣泛 ...
2025-07-10數(shù)據(jù)查詢結(jié)束后:分析師的收尾工作與價值深化? ? 在數(shù)據(jù)分析的全流程中,“query end”(查詢結(jié)束)并非工作的終點,而是將數(shù) ...
2025-07-10CDA 數(shù)據(jù)分析師考試:從報考到取證的全攻略? 在數(shù)字經(jīng)濟蓬勃發(fā)展的今天,數(shù)據(jù)分析師已成為各行業(yè)爭搶的核心人才,而 CDA(Certi ...
2025-07-09【CDA干貨】單樣本趨勢性檢驗:捕捉數(shù)據(jù)背后的時間軌跡? 在數(shù)據(jù)分析的版圖中,單樣本趨勢性檢驗如同一位耐心的偵探,專注于從單 ...
2025-07-09year_month數(shù)據(jù)類型:時間維度的精準切片? ? 在數(shù)據(jù)的世界里,時間是最不可或缺的維度之一,而year_month數(shù)據(jù)類型就像一把精準 ...
2025-07-09CDA 備考干貨:Python 在數(shù)據(jù)分析中的核心應用與實戰(zhàn)技巧? ? 在 CDA 數(shù)據(jù)分析師認證考試中,Python 作為數(shù)據(jù)處理與分析的核心 ...
2025-07-08SPSS 中的 Mann-Kendall 檢驗:數(shù)據(jù)趨勢與突變分析的有力工具? ? ? 在數(shù)據(jù)分析的廣袤領域中,準確捕捉數(shù)據(jù)的趨勢變化以及識別 ...
2025-07-08備戰(zhàn) CDA 數(shù)據(jù)分析師考試:需要多久?如何規(guī)劃? CDA(Certified Data Analyst)數(shù)據(jù)分析師認證作為國內(nèi)權(quán)威的數(shù)據(jù)分析能力認證 ...
2025-07-08LSTM 輸出不確定的成因、影響與應對策略? 長短期記憶網(wǎng)絡(LSTM)作為循環(huán)神經(jīng)網(wǎng)絡(RNN)的一種變體,憑借獨特的門控機制,在 ...
2025-07-07統(tǒng)計學方法在市場調(diào)研數(shù)據(jù)中的深度應用? 市場調(diào)研是企業(yè)洞察市場動態(tài)、了解消費者需求的重要途徑,而統(tǒng)計學方法則是市場調(diào)研數(shù) ...
2025-07-07CDA數(shù)據(jù)分析師證書考試全攻略? 在數(shù)字化浪潮席卷全球的當下,數(shù)據(jù)已成為企業(yè)決策、行業(yè)發(fā)展的核心驅(qū)動力,數(shù)據(jù)分析師也因此成為 ...
2025-07-07剖析 CDA 數(shù)據(jù)分析師考試題型:解鎖高效備考與答題策略? CDA(Certified Data Analyst)數(shù)據(jù)分析師考試作為衡量數(shù)據(jù)專業(yè)能力的 ...
2025-07-04SQL Server 字符串截取轉(zhuǎn)日期:解鎖數(shù)據(jù)處理的關(guān)鍵技能? 在數(shù)據(jù)處理與分析工作中,數(shù)據(jù)格式的規(guī)范性是保證后續(xù)分析準確性的基礎 ...
2025-07-04CDA 數(shù)據(jù)分析師視角:從數(shù)據(jù)迷霧中探尋商業(yè)真相? 在數(shù)字化浪潮席卷全球的今天,數(shù)據(jù)已成為企業(yè)決策的核心驅(qū)動力,CDA(Certifie ...
2025-07-04CDA 數(shù)據(jù)分析師:開啟數(shù)據(jù)職業(yè)發(fā)展新征程? ? 在數(shù)據(jù)成為核心生產(chǎn)要素的今天,數(shù)據(jù)分析師的職業(yè)價值愈發(fā)凸顯。CDA(Certified D ...
2025-07-03