目錄
- cProfile
- line_profiler
- 總結(jié)
上一篇文章我們介紹了基準(zhǔn)測(cè)試,通過基準(zhǔn)測(cè)試可以發(fā)現(xiàn)程序變慢了,那么是因?yàn)槭裁丛驅(qū)е滦阅茏兟?,需要進(jìn)一步做代碼性能分析。python同樣提供了性能分析工具。
cProfile
cProfile是python默認(rèn)的性能分析器,他只測(cè)量CPU時(shí)間,并不關(guān)心內(nèi)存消耗和其他與內(nèi)存相關(guān)聯(lián)的信息。
from time import sleep
import random
def random_list(start, end, length):
"""
生成隨機(jī)列表
:param start: 隨機(jī)開始數(shù)
:param end: 隨機(jī)結(jié)束數(shù)
:param length: 列表長(zhǎng)度
"""
data_list = []
for i in range(length):
data_list.append(random.randint(start, end))
return data_list
def bubble_sort(arr):
"""
冒泡排序: 對(duì)列表進(jìn)行排序
:param arr 列表
"""
n = len(arr)
sleep(1)
for i in range(n):
for j in range(0, n - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
return arr
if __name__ == '__main__':
get_data_list = random_list(1, 99, 10)
import cProfile
cProfile.run('bubble_sort({})'.format(get_data_list))
繼續(xù)使用上一篇文章中的例子,引用cProfile模塊,run()方法參數(shù)說明。
run(statement, filename=None, sort=-1)
- statement: 需要測(cè)試的代碼或者函數(shù)(函數(shù)名)
- fielname: 結(jié)果保存的位置, 默認(rèn)為stdout
- sort: 結(jié)果排序方法,常用的有cumtime: 累積時(shí)間, name: 函數(shù)名, line: 行號(hào)
為了使結(jié)果統(tǒng)計(jì)出耗時(shí)部分,我們加了sleep,結(jié)果如下:
❯ python demo.py
6 function calls in 1.004 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 1.004 1.004 string>:1(module>)
1 0.000 0.000 1.004 1.004 demo.py:19(bubble_sort)
1 0.000 0.000 1.004 1.004 {built-in method builtins.exec}
1 0.000 0.000 0.000 0.000 {built-in method builtins.len}
1 1.004 1.004 1.004 1.004 {built-in method time.sleep}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
- 6 function calls in 1.004 seconds 6個(gè)函數(shù)調(diào)用被監(jiān)控,耗時(shí)1.004秒。
- ncalls 函數(shù)被調(diào)用的次數(shù)。如果這一列有兩個(gè)值,就表示有遞歸調(diào)用,第二個(gè)值是原生調(diào)用次數(shù),第一個(gè)值是總調(diào)用次數(shù)。
- tottime 函數(shù)內(nèi)部消耗的總時(shí)間。(可以幫助優(yōu)化)
- percall 是tottime除以ncalls,一個(gè)函數(shù)每次調(diào)用平均消耗時(shí)間。
- cumtime 之前所有子函數(shù)消費(fèi)時(shí)間的累計(jì)和。
- filename:lineno(function) 被分析函數(shù)所在文件名、行號(hào)、函數(shù)名。
line_profiler
line_profiler 可以提供有關(guān)時(shí)間是如何在各行之間分配的信息,直白一點(diǎn)就是給出程序每行的耗時(shí),在無法確定哪行語句最浪費(fèi)時(shí)間,這很有用。
line_profiler是一個(gè)第三方模塊,需要安裝。
https://github.com/pyutils/line_profiler
from time import sleep
import random
def random_list(start, end, length):
"""
生成隨機(jī)列表
:param start: 隨機(jī)開始數(shù)
:param end: 隨機(jī)結(jié)束數(shù)
:param length: 列表長(zhǎng)度
"""
data_list = []
for i in range(length):
data_list.append(random.randint(start, end))
return data_list
@profile
def bubble_sort(arr):
"""
冒泡排序: 對(duì)列表進(jìn)行排序
:param arr 列表
"""
n = len(arr)
sleep(1)
for i in range(n):
for j in range(0, n - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
return arr
if __name__ == '__main__':
get_data_list = random_list(1, 99, 10)
bubble_sort(get_data_list)
給需要監(jiān)控的函數(shù)加上@profile
裝飾器。通過kernprof
命令運(yùn)行文件(安裝完line_profiler生成的命令)。
參數(shù)說明:
- -l:以使用函數(shù)line_profiler
- -v:以立即將結(jié)果打印到屏幕
運(yùn)行結(jié)果:
kernprof -l -v demo.py
Wrote profile results to demo.py.lprof
Timer unit: 1e-06 s
Total time: 1.00416 s
File: demo.py
Function: bubble_sort at line 18
Line # Hits Time Per Hit % Time Line Contents
==============================================================
18 @profile
19 def bubble_sort(arr):
20 """
21 冒泡排序: 對(duì)列表進(jìn)行排序
22 :param arr 列表
23 """
24 1 8.0 8.0 0.0 n = len(arr)
25 1 1004030.0 1004030.0 100.0 sleep(1)
26 11 15.0 1.4 0.0 for i in range(n):
27 55 44.0 0.8 0.0 for j in range(0, n - i - 1):
28 45 41.0 0.9 0.0 if arr[j] > arr[j + 1]:
29 20 21.0 1.1 0.0 arr[j], arr[j + 1] = arr[j + 1], arr[j]
30 1 1.0 1.0 0.0 return arr
輸出非常直觀,分成了6列。
- Line #:運(yùn)行的代碼行號(hào)。
- Hits:代碼行運(yùn)行的次數(shù)。
- Time:代碼行的執(zhí)行時(shí)間,單位為微秒。
- Per Hit:Time/Hits。
- % Time:代碼行總執(zhí)行時(shí)間所占的百分比。
- Line Contents:代碼行的內(nèi)容。
只需查看% Time列,就可清楚地知道時(shí)間都花在了什么地方。
總結(jié)
性能測(cè)試分析站在項(xiàng)目層面是一個(gè)很龐大的話題,以前為測(cè)試工程師,關(guān)注的是性能工具的使用,以及用戶維度的性能[1];作為開發(fā)工程師,每個(gè)功能都是由一個(gè)個(gè)函數(shù)/方法組成,我們?nèi)シ治雒總€(gè)函數(shù)/方法,甚至是每行代碼的耗時(shí),才能更好的進(jìn)行代碼層面的性能優(yōu)化。
以上就是python如何做代碼性能分析的詳細(xì)內(nèi)容,更多關(guān)于python 代碼性能分析的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
您可能感興趣的文章:- python一些性能分析的技巧
- Python性能分析工具py-spy原理用法解析
- Python內(nèi)置類型性能分析過程實(shí)例
- Python性能分析工具Profile使用實(shí)例
- cProfile Python性能分析工具使用詳解
- Python中判斷子串存在的性能比較及分析總結(jié)
- 使用pycallgraph分析python代碼函數(shù)調(diào)用流程以及框架解析
- Python爬蟲分析微博熱搜關(guān)鍵詞的實(shí)現(xiàn)代碼
- 使用bandit對(duì)目標(biāo)python代碼進(jìn)行安全函數(shù)掃描的案例分析
- python中delattr刪除對(duì)象方法的代碼分析
- python3中確保枚舉值代碼分析