别猜,量它:cProfile 与逐行计时的正确姿势
优化的第一原则是测量。没有 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 能直接指到分配行。
小结
- 先 cProfile 定位热点,再 timeit 验证
- 内存问题看 tracemalloc,不要凭感觉加 gc
- 优化后用同一套基准复测,避免“看起来快了”