Python 中如何做性能分析(Profile)?
Python 性能分析用内置 cProfile 模块:python -m cProfile script.py 查看各函数耗时和调用次数。line_profiler 逐行分析。本文介绍各种工具。
用内置的 cProfile 模块:python -m cProfile myscript.py 就能输出每个函数的调用次数和耗时,找出性能瓶颈。需要逐行分析用第三方库 line_profiler。
方法一:命令行运行
python -m cProfile myscript.py
输出包含以下列(具体数值来自实际运行,不把示意数字视为实测):
ncalls tottime percall cumtime percall filename:lineno(function)
两个 percall 分别是 tottime/调用次数与 cumtime/原始调用次数;递归场景需结合 ncalls 解释。
ncalls:调用次数tottime:该函数自身耗时(不含子调用)cumtime:累计耗时(含子调用)
方法二:代码中调用
import cProfile
def my_function():
return sum(range(100000))
cProfile.run('my_function()')
方法三:保存结果后用 pstats 排序
import cProfile
import pstats
def my_function():
return sum(range(100000))
cProfile.run('my_function()', 'profile_stats')
p = pstats.Stats('profile_stats')
p.sort_stats('cumulative').print_stats(20) # 按累计耗时排前 20
p.sort_stats('time').print_stats(20) # 按自身耗时排前 20
逐行分析:line_profiler
pip install line_profiler
在要分析的函数上加 @profile 装饰器,然后:
kernprof -l -v myscript.py
常见问题(FAQ)
Q:cProfile 会影响程序性能吗?
A:会。cProfile 会在函数调用等事件上记录统计信息,开销随函数调用模式和负载变化,不能用固定 10%-30% 概括。通常先在开发和测试环境使用;若用于生产诊断,应限定采集范围并评估开销。
Q:cProfile 和 timeit 有什么区别?
A:cProfile 用于定位哪里慢(哪些函数耗时多),timeit 用重复运行比较小段代码的耗时。先用 cProfile 找瓶颈,再在可比环境和代表性输入下用 timeit 对比;结果仍会受系统负载和测量方式影响。
Q:如何可视化 cProfile 结果?
A:用 snakeviz 或 gprof2dot 将结果转为交互式图表,更直观。