前言
??在進行模型測試過程中,我們通常需要知道整個預測過程所消耗的時間與空間,以及哪個部分存在瓶頸,才能進行后續的優化。因此,本文介紹我常用的性能分析工具--line_profiler
與memory_profiler
。
一、時間分析--line_profiler模塊
1.1 安裝
$ pip3 install line_profiler
1.2 用法
??line_profiler使用裝飾器(@profile)標記需要調試的函數。用kernprof運行代碼,被選函數每一行花費的cpu時間以及其他信息就會被記錄下來。
# demo.py
@profile
def foo():
task = []
for a in range(0, 101):
for b in range(0, 101):
if a + b == 100:
task.append((a, b))
return task
@profile
def run():
for item in foo():
pass
if __name__ == '__main__':
run()
運行下面的命令
kernprof -l -v demo.py
-l表示逐行分析,-v用于輸出。
同時會輸出一個文件:demo.py.lprof,后期可以對.lprof文件進行分析輸出結果。
python -m line_profiler demo.py.lprof
1.3 結果分析
Wrote profile results to demo.py.lprof
Timer unit: 1e-06 s
Total time: 0.004891 s
File: demo.py
Function: foo at line 1
Line # Hits Time Per Hit % Time Line Contents
==============================================================
1 @profile
2 def foo():
3 1 0.0 0.0 0.0 task = []
4 102 23.0 0.2 0.5 for a in range(0, 101):
5 10302 2260.0 0.2 46.2 for b in range(0, 101):
6 10201 2578.0 0.3 52.7 if a + b == 100:
7 101 30.0 0.3 0.6 task.append((a, b))
8 1 0.0 0.0 0.0 return task
Total time: 0.008603 s
File: demo.py
Function: run at line 11
Line # Hits Time Per Hit % Time Line Contents
==============================================================
11 @profile
12 def run():
13 102 8584.0 84.2 99.8 for item in foo():
14 101 19.0 0.2 0.2 pass
Timer unit: 1e-06 s
:時間單位;
Total time: 0.004891 s
:總時間;
Hit
:代碼運行次數;
%Time
:代碼占了它所在函數的消耗的時間百分比,通常直接看這一列。
二、內存分析--memory_profiler模塊
2.1 安裝
??首先安裝memory_profiler和psutil(psutil主要用于提高memory_profile的性能,建議安裝)(可使用pip直接安裝)
$ pip install memory_profiler
$ pip install psutil
2.2 用法
(1) ?1.在函數前添加 @profile
? ? 2.運行方式: python -m memory_profiler test.py
? ? 此方法缺點:在調試和實際項目運行時 要增刪 @profile 此裝飾器
(2) ?1.先導入:from memory_profiler import profile
? ? 2.函數前加裝飾器: @profile(precision=4, stream=open('memory_profiler.log','w+'))
? ?? ?? ?? ?? ? 參數含義:precision:精確到小數點后幾位 ;
? ?? ?? ?? ?? ? stream:此模塊分析結果保存到 'memory_profiler.log' 日志文件。如果沒有此參 數,分析結果會在控制臺輸出;
? ?運行方式:直接跑此腳本 python memory_profiler_test.py ;
? ?此方法優點:解決第一種方法的缺點,在不需要分析時,直接注釋掉此行。
(3)
腳本代碼和方法二一樣,但是運行方式不同:
mprof run memory_profiler_test.py : 分析結果會保存到一個 .dat格式文件中
mprof plot : 把結果以圖片到方式顯示出來(直接在本目錄下運行此命令即可,程序會自動找出.dat文件) (要安裝 pip install matplotlib)
mprof clean : 清空所有 .dat文件
2.3 結果分析
Filename: demo.py
Line # Mem usage Increment Line Contents
================================================
1 49.160 MiB 49.160 MiB @profile
2 def foo():
3 49.160 MiB 0.000 MiB task = []
4 49.160 MiB 0.000 MiB for a in range(0, 101):
5 49.160 MiB 0.000 MiB for b in range(0, 101):
6 49.160 MiB 0.000 MiB if a + b == 100:
7 49.160 MiB 0.000 MiB task.append((a, b))
8 49.160 MiB 0.000 MiB return task
Filename: demo.py
Line # Mem usage Increment Line Contents
================================================
11 49.160 MiB 49.160 MiB @profile
12 def run():
13 49.160 MiB 49.160 MiB for item in foo():
14 49.160 MiB 0.000 MiB pass
Mem usage
: 運行內存大小;
Increment
: 運行當前代碼后,增加的內存。