用pympler.tracker.summarytracker()做实时内存快照最轻量,需在业务前后各调用take_snapshot()比对,避免循环新建、禁用gc以保增量准确,重点关注dict/list/str类型。

怎么用 pympler 做实时内存快照
直接调用 tracker.SummaryTracker() 是最轻量的起点,它不侵入业务逻辑,适合在关键路径前后各拍一次快照比对。注意别在循环里反复初始化 tracker——每次新建都会重置统计基准,导致增量归零。
常见错误是以为 tracker.print_diff() 能自动识别“新增对象”,其实它只对比两次 tracker.take_snapshot() 的结果,中间若有 GC 发生,存活对象数可能反降。建议配合 gc.disable() 短暂禁用垃圾回收(仅调试期)。
- 用法示例:
from pympler import tracker<br>tr = tracker.SummaryTracker()<br># ... 业务代码前<br>s1 = tr.take_snapshot()<br># ... 业务代码后<br>s2 = tr.take_snapshot()<br>tr.print_diff(s1, s2)
- 重点关注
types列里的dict、list、str—— 它们占内存大且容易意外累积 - 避免在多线程环境共享同一个
SummaryTracker实例,线程不安全
objgraph 查不到对象?先确认引用链是否被截断
objgraph 找不到目标对象,大概率不是工具失效,而是你传进去的变量名本身已不持有引用。比如函数返回一个大列表,你在函数外只做了 res = func(),但紧接着又执行了 res = None,那原始列表可能已被 GC 标记为待回收,objgraph.by_type("list") 就查不到它。
更隐蔽的情况是:对象被闭包、__dict__ 或弱引用容器(如 weakref.WeakKeyDictionary)持有,objgraph.show_backrefs() 默认不穿透这些结构。必须显式加参数:max_depth=5, too_many=10, extra_ignore=[id(locals())]。
立即学习“Python免费学习笔记(深入)”;
系统优势: 1、 使用全新ASP.Net+c#和三层结构开发. 2、 可生成各类静态页面(html,htm,shtm,shtml和.aspx) 3、 管理后台风格模板自由选择,界面精美 4、 风格模板每月更新多套,还可按需定制 5、 独具的缓存技术加快网页浏览速度 6、 智能销售统计,图表分析 7、 集成国内各大统计系统 8、 多国语言支持,内置简体繁体和英语 9、 UTF-8编码,可使用于全球
- 典型误判场景:Django 视图里临时构造的 QuerySet 对象,因缓存机制被 Model 类的
_meta引用链间接持有着,不设max_depth就看不到根因 -
objgraph.show_growth()比by_type()更可靠——它基于全局对象计数器,不依赖当前变量作用域 - Windows 下若报
Graphviz not found,不是必须装 Graphviz;改用objgraph.show_most_common_types(limit=20)同样能定位热点类型
用 tracemalloc 定位内存分配源头时,为什么行号总是 <frozen importlib._bootstrap></frozen>
这是 Python 3.6+ 默认行为:tracemalloc 只记录“分配发生时”的栈帧,而很多第三方库(尤其是 C 扩展或用 __import__ 动态加载的模块)的内存申请发生在 import 过程中,真实业务代码行号被压在底层帧之下。
解决办法是启动时就启用,并过滤掉无关路径:tracemalloc.start(25) # depth=25 足够展开嵌套 import,再用 filter_traces() 排除标准库路径:
import tracemalloc<br>tracemalloc.start(25)<br># ... 运行后<br>snapshot = tracemalloc.take_snapshot()<br>top_stats = snapshot.filter_traces((<br> tracemalloc.Filter(False, "<frozen importlib._bootstrap>"),<br> tracemalloc.Filter(False, "lib/python3.*"),<br>)).statistics('lineno')- 注意
tracemalloc无法跟踪 C 扩展分配的内存(如 NumPy 数组底层 malloc),这类得靠psutil.Process().memory_info().rss结合时间戳粗略估算 - 生产环境慎用:开启后每个
malloc调用会增加约 10% CPU 开销,且 snapshot 本身也吃内存
生成的 .heapsnapshot 文件怎么导入 Chrome DevTools
Python 没有原生导出 Chrome 兼容格式的能力,必须用 memray 或手动转换。推荐用 memray:它生成的 .bin 文件可直接转成 Chrome 能读的 .heapsnapshot。
关键步骤是加 --native 参数启动采集,否则看不到 C 扩展分配点;导出时指定 --format chrome:
pip install memray<br>memray run --native --output profile.bin python my_script.py<br>memray tree profile.bin # 快速看热点<br>memray convert --format chrome profile.bin # 输出 profile.heapsnapshot
- Chrome 中打开 DevTools → Memory → Load → 选中文件,注意顶部切换到 “Allocation instrumentation on timeline” 才能看到按时间轴分布的分配事件
- 如果转换失败,大概率是
profile.bin里含多进程数据(如用了multiprocessing),需加--pid指定目标进程 ID 重采
实际分析时,真正卡住人的往往不是工具不会用,而是没意识到「Python 对象引用关系」和「C 层内存分配」是两套体系——前者用 objgraph 和 pympler,后者得靠 memray 或 valgrind。混着查,才不容易漏掉释放失败的 ctypes 指针或未 close 的 mmap 区域。









