人人都会AI编程

memory_profiler /tracemalloc:内存占用分析

更新时间:2026-07-12

内存问题通常比 CPU 瓶颈更难排查——程序不报错,但内存持续增长,最终被系统 OOM Killer 杀掉。Python 给开发者提供了从“逐行分析”到“底层追踪”的完整内存分析工具链,其中memory_profilertracemalloc是最常用的两个。

memory_profiler:逐行看内存,粗暴直接

memory_profiler 是第三方库,它最核心的能力是:告诉你每一行代码执行后,内存占用量增加了多少

安装

pip install memory-profiler

基本使用
在需要分析的函数上添加 @profile 装饰器,然后用 Python 执行脚本(注意:不能直接在 Jupyter 中用,需要将脚本保存为 .py 文件在终端运行):

# example.py
from memory_profiler import profile

@profile
def process_data():
    data = [i for i in range(100000)]       # 创建一个列表
    squared = [x**2 for x in data]         # 生成平方值
    del data                                # 释放原列表
    return squared

if __name__ == '__main__':
    process_data()

终端运行:

python -m memory_profiler example.py

你会看到类似这样的输出:

Line #    Mem usage    Increment   Line Contents
================================================
     4     35.4 MiB     35.4 MiB   @profile
     5                             def process_data():
     6     38.4 MiB      3.0 MiB       data = [i for i in range(100000)]
     7     42.1 MiB      3.7 MiB       squared = [x**2 for x in data]
     8     38.3 MiB     -3.8 MiB       del data
     9     38.3 MiB      0.0 MiB       return squared

每一行的内存增/减一目了然,你马上就知道哪一步造成了内存飙升。

更强大的功能:mprof
memory_profiler 还附带命令行工具 mprof,可以按时间采样整个进程的内存使用并绘制图表,适合长时间运行的脚本:

mprof run python my_script.py
mprof plot
tracemalloc:追踪内存分配痕迹,适合排查泄漏

tracemalloc 是 Python 3.4 起内置的标准库模块,它不关心“每行涨了多少内存”,而是记录每一次内存分配发生在哪个文件、哪一行,帮你找到“谁分配了内存却迟迟不释放”。

基本用法:捕获快照,对比差异

import tracemalloc

tracemalloc.start()              # 开始追踪

# ---- 模拟一段可能泄漏的操作 ----
data1 = [i for i in range(100000)]
snapshot1 = tracemalloc.take_snapshot()   # 拍快照

del data1                                 # 释放
# ---- 再跑一段 ----
data2 = [i for i in range(200000)]
snapshot2 = tracemalloc.take_snapshot()

# 比较两个快照,找出多出来的内存分配
stats = snapshot2.compare_to(snapshot1, 'lineno')
for stat in stats[:5]:
    print(stat)

输出示例:

<...>/example.py:6: size=800 KiB (+800 KiB), count=1 (+1), average=800 KiB
<...>/example.py:9: size=1.6 MiB (+1.6 MiB), count=1 (+1), average=1.6 MiB

这里清楚显示第 9 行分配了 1.6 MiB 内存,且是净增长(未被释放)。多次拍快照对比,就能精确定位长期不释放的内存分配点,也就是泄漏源。

显示前 N 个内存消耗大户

# 取当前快照按文件统计
snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('filename')
for stat in top_stats[:5]:
    print(stat)
实用分工建议
  • 快速定位“胖函数”:用 memory_profiler 直接看到函数内哪几行最耗内存,适合代码重构优化。
  • 追查隐藏泄漏:遇到“程序跑着跑着内存就满了”的情况,在上线前或测试环境中启用 tracemalloc,对比多个时间点的快照,找出那些只增不减的分配点。
  • 注意性能影响:tracemalloc 启动后会额外记录每次分配,对性能有一定影响(但通常可接受),生产环境慎开;memory_profiler 的逐行装饰器也会拖慢执行,仅用于调试分析。

两者结合,基本覆盖了从“内存用多了”到“内存收不回来”的所有常见场景。