雖然并非你編寫的每個 Python 程序都要求一個嚴格的性能分析,但是讓人放心的是,當問題發生的時候,Python 生態圈有各種各樣的工具可以處理這類問題。
分析程序的性能可以歸結為回答四個基本問題:
下面,我們將用一些神奇的工具深入到這些問題的答案中去。
用 time 粗粒度的計算時間
讓我們開始通過使用一個快速和粗暴的方法計算我們的代碼:傳統的 unix time 工具。
$ time python yourprogram.pyreal 0m1.028suser 0m0.001ssys 0m0.003s
三個輸出測量值之間的詳細意義在這里 stackoverflow article,但簡介在這:
real — 指的是實際耗時 user — 指的是內核之外的 CPU 耗時 sys — 指的是花費在內核特定函數的 CPU 耗時你會有你的應用程序用完了多少 CPU 周期的即視感,不管系統上其他運行的程序添加的系統和用戶時間。
如果 sys 和 user 時間之和小于 real 時間,然后你可以猜測到大多數程序的性能問題最有可能與 IO wait 相關。
用 timing context 管理器細粒度的計算時間
我們下一步的技術包括直接嵌入代碼來獲取細粒度的計時信息。下面是我進行時間測量的代碼的一個小片段
timer.py
import time class Timer(object): def __init__(self, verbose=False): self.verbose = verbose def __enter__(self): self.start = time.time() return self def __exit__(self, *args): self.end = time.time() self.secs = self.end - self.start self.msecs = self.secs * 1000 # millisecs if self.verbose: print 'elapsed time: %f ms' % self.msecs
為了使用它,使用 Python 的 with 關鍵字和 Timer 上下文管理器來包裝你想計算的代碼。當您的代碼塊開始執行,它將照顧啟動計時器,當你的代碼塊結束的時候,它將停止計時器。
這個代碼片段示例:
from timer import Timerfrom redis import Redisrdb = Redis() with Timer() as t: rdb.lpush("foo", "bar")print "=> elasped lpush: %s s" % t.secs with Timer() as t: rdb.lpop("foo")print "=> elasped lpop: %s s" % t.secs為了看看我的程序的性能隨著時間的演化的趨勢,我常常記錄這些定時器的輸出到一個文件中。
使用 profiler 逐行計時和分析執行的頻率
羅伯特·克恩有一個不錯的項目稱為 line_profiler , 我經常使用它來分析我的腳本有多快,以及每行代碼執行的頻率:
為了使用它,你可以通過使用 pip 來安裝它:
pip install line_profiler
新聞熱點
疑難解答