如何分析python代码性能
以下方法分别针对代码块、代码程序文件、 函数进行性能计时统计:
- time.time()或者datetime.datetime.now()
# 结束时间-开始时间
import time
import datetime
start = time.time() # 或者datetime.datetime.now()
func() # 需要统计运行时长的函数
end = time.time()
print(end - start)
- time.clock()
"""
clock() 函数以浮点数计算的秒数返回当前的CPU时间,用来衡量不用程序的耗时,比time.time更有用。在win系统下,这个函数返回的是真实时间(wall time),而在Unix/Linux下返回的是CPU 时间。
"""
# test.py
import time
start = time.clock()
func() # 需要统计运行时长的函数
end = time.time()
print(end - start)
- time
# 在linux下对整个程序做计时统计
/usr/bin/time -p python test.py
# 输入内容
# real 0m2.057s 记录了整体的耗时
# user 0m0.033s 记录了CPU花在任务上的时间,但不保罗内核函数花费的时间
# sys 0m0.011s 记录了内核函数花费的时间
# user + sys 即是cpu总共花费的时间
# real - (user + sys) 得到可能是花费在等待IO的时间
# 打开–verbose开关来获得更多输出信息
/usr/bin/time --verbose python test.py
- cProfile:分析分析cpu使用情况
cProfile:基于lsprof的用C语言实现的扩展应用,运行开销比较合理,适合分析运行时间较长的程序,推荐使用这个模块。
# 命令生成统计文件
python -m cProfile test.py # 直接输出统计结果
# 上面这条命令等价于
import cProfile
import re
cProfile.run('re.compile("test")')
# 命令生成统计文件(二进制数据文件)
python -m cProfile -o stats test.py
# 上面这条命令等价于
import cProfile
import re
cProfile.run('re.compile("test")', 'stats', 'cumtime')
# 然后,通过python分析生成的统计文件
import pstats
p = pstats.Stats("stats")
p.print_stats()
# 结果
'''
Hello World
5 function calls in 2.001 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 2.001 2.001 test.py:10(<module>)
1 0.000 0.000 2.001 2.001 {built-in method builtins.exec}
1 0.000 0.000 0.000 0.000 {built-in method builtins.print}
1 2.001 2.001 2.001 2.001 {built-in method time.sleep}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
'''
统计表中各参数含义:
参数 | 描述 |
---|---|
ncalls | 表示函数调用的次数 |
tottime | 表示指定函数的总的运行时间,除掉函数中调用子函数的运行时间 |
percall | 第一个percall)等于 tottime/ncalls |
cumtime | 表示该函数及其所有子函数的调用运行的时间,即函数开始调用到返回的时间 |
percall | (第二个percall)即函数运行一次的平均时间,等于 cumtime/ncalls |
filename:lineno(function) | 表示每个函数调用的具体信息 |
- timeit
# 计算小段代码的执行时间的模块
from timeit import timeit
print(timeit('math.sqrt(2)', 'import math', number=100000)) # 执行10万次2的开方
# 结果
'''
0.023690600000000006
'''
- 装饰器
# 将给需要计时的函数加上装饰器@time_count
from functools import wraps
import time
def time_count(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter() # 使用time.perf_counter() 能够提供给定平台上精度最高的计时器
res = func(*args, **kwargs)
end = time.perf_counter()
print('{}.{} : {}'.format(func.__module__, func.__name__, end - start))
return res
return wrapper
@time_count
def time_sleep():
time.sleep(2)
print("休眠两秒")
if __name__ == '__main__':
time_sleep()
# 结果
'''
休眠两秒
__main__.time_sleep : 1.9995934
'''
- line_profile
用cProfile找到需要分析的函数,然后用line_profiler对函数逐行进行性能分析。
# 安装 line_profile
pip install line_profiler
# 运行kernprof 逐行分析被修饰函数的CPU开销
kernprof.py -l -v test.py # -v 显示输出;-l 代表逐行分析而不是逐函数分析
# 结果中各参数的含义
'''
Total Time:测试代码的总运行时间
Hits:表示每行代码运行的次数
Time:每行代码运行的总时间
Per Hits:每行代码运行一次的时间
% Time:每行代码运行时间的百分比
'''
- memory_profiler:分析内存使用情况
# 安装memory_profiler和依赖
pip install psutil
pip install memory_profiler
# 命令分析内存使用情况
python -m memory_profiler test.py