别猜,量它:cProfile 与逐行计时的正确姿势

性能 · 约 6 分钟

优化的第一原则是测量。没有 profiling 数据的“优化”多数只是换了一种写法。

一、先找热点:cProfile

python -m cProfile -s cumtime app.py | head -30

# 或在代码里
import cProfile, pstats
pr = cProfile.Profile(); pr.enable()
main(); pr.disable()
pstats.Stats(pr).sort_stats("cumtime").print_stats(15)

看 cumtime 找整体耗时、看 tottime 找自身耗时;两者差距大说明时间在子调用里。

二、验证微优化:timeit

python -m timeit -s "d={'a':1}" "d.get('a')"
python -m timeit -s "d={'a':1}" "d['a'] if 'a' in d else None"

微基准要固定输入规模、重复足够次数;单次差异小于 10% 的通常不值得改,可读性更重要。

三、内存:tracemalloc

import tracemalloc
tracemalloc.start()
run_batch()
snap = tracemalloc.take_snapshot()
for st in snap.statistics("lineno")[:8]:
    print(st)

内存持续增长先确认是缓存、连接池还是真泄漏;tracemalloc 能直接指到分配行。

小结