檢測Python程式執行效率及記憶體和CPU使用的7種方法

Daetalus發表於2014-12-18

在執行復雜的Python程式時,執行時間會很長,這時也許想提高程式的執行效率。但該怎麼做呢?

首先,要有個工具能夠檢測程式碼中的瓶頸,例如,找到哪一部分執行時間比較長。接著,就針對這一部分進行優化。

同時,還需要控制記憶體和CPU的使用,這樣可以在另一方面優化程式碼。

因此,在這篇文章中我將介紹7個不同的Python工具,來檢查程式碼中函式的執行時間以及記憶體和CPU的使用。

1. 使用裝飾器來衡量函式執行時間

有一個簡單方法,那就是定義一個裝飾器來測量函式的執行時間,並輸出結果:

接著,將這個裝飾器新增到需要測量的函式之前,如下所示:

例如,這裡檢測一個函式排序含有200萬個隨機數字的陣列所需的時間:

執行指令碼時,會看到下面的結果:

2. 使用timeit模組

另一種方法是使用timeit模組,用來計算平均時間消耗。

執行下面的指令碼可以執行該模組。

這裡的timing_functions是Python指令碼檔名稱。

在輸出的末尾,可以看到以下結果:

這表示測試了4次,平均每次測試重複5次,最好的測試結果是2.08秒。

如果不指定測試或重複次數,預設值為10次測試,每次重複5次。

3. 使用Unix系統中的time命令

然而,裝飾器和timeit都是基於Python的。在外部環境測試Python時,unix time實用工具就非常有用。

執行time實用工具:

輸出結果為:

第一行來自預定義的裝飾器,其他三行為:

  • real表示的是執行指令碼的總時間
  • user表示的是執行指令碼消耗的CPU時間。
  • sys表示的是執行核心函式消耗的時間。

注意:根據維基百科的定義,核心是一個計算機程式,用來管理軟體的輸入輸出,並將其翻譯成CPU和其他計算機中的電子裝置能夠執行的資料處理指令。

因此,Real執行時間和User+Sys執行時間的差就是消耗在輸入/輸出和系統執行其他任務時消耗的時間。

4. 使用cProfile模組

如果想知道每個函式和方法消耗了多少時間,以及這些函式被呼叫了多少次,可以使用cProfile模組。

現在可以看到程式碼中函式的詳細描述,其中含有每個函式呼叫的次數,由於使用了-s選項(累加),最終結果會根據每個函式的累計執行時間排序。

讀者會發現執行指令碼所需的總時間比以前要多。這是由於測量每個函式的執行時間這個操作本身也是需要時間。

5. 使用line_profiler模組

line_profiler模組可以給出執行每行程式碼所需佔用的CPU時間。

首先,安裝該模組:

接著,需要指定用@profile檢測哪個函式(不需要在程式碼中用import匯入模組):

最好,可以通過下面的命令獲得關於random_sort2函式的逐行描述。

其中-l表示逐行解釋,-v表示表示輸出詳細結果。通過這種方法,我們看到構建陣列消耗了44%的計算時間,而sort()方法消耗了剩餘的56%的時間。

同樣,由於需要檢測執行時間,指令碼的執行時間更長了。

6. 使用memory_profiler模組

memory_profiler模組用來基於逐行測量程式碼的記憶體使用。使用這個模組會讓程式碼執行的更慢。

安裝方法如下:

另外,建議安裝psutil包,這樣memory_profile會執行的快一點:

與line_profiler相似,使用@profile裝飾器來標識需要追蹤的函式。接著,輸入:

指令碼的執行時間比以前長1或2秒。如果沒有安裝psutil包,也許會更長。

從結果可以看出,記憶體使用是以MiB為單位衡量的,表示的mebibyte(1MiB = 1.05MB)。

7. 使用guppy包

最後,通過這個包可以知道在程式碼執行的每個階段中,每種型別(str、tuple、dict等)分別建立了多少物件。

安裝方法如下:

接著,將其新增到程式碼中:

執行程式碼:

可以看到輸出結果為:

通過在程式碼中將heap()放置在不同的位置,可以瞭解到指令碼中的物件建立和刪除操作的流程。

如果想學習更多關於Python程式碼速度優化方面的知識,我建議你去讀這本書《High Performance Python: Practical Performant Programming for Humans, september 2014.

希望這篇文章能偶幫到你!^_^

打賞支援我翻譯更多好文章,謝謝!

打賞譯者

打賞支援我翻譯更多好文章,謝謝!

任選一種支付方式

檢測Python程式執行效率及記憶體和CPU使用的7種方法 檢測Python程式執行效率及記憶體和CPU使用的7種方法

相關文章