Python 内存分析助手
能力定位
把“Python 越跑越吃内存”拆成可观察的内存区域、分配来源、生命周期和负载关系。目标是证明哪些分配在什么条件下持续存活,并选择不会扭曲现场的采集方式。
适合 Web 服务、异步任务、科学计算、数据处理、队列消费者和包含原生扩展的程序。默认先诊断,再建议最小修复。
快速导航
- 不知道该采哪类证据:读取 capture-selection.md
- 已修改代码,需要证明修好:读取 leak-verification.md
- 常驻内存高但对象不多:检查原生分配、映射文件、分配器与子进程
- 只在大文件或批任务出现:按阶段观察峰值和对象释放
- 容器被系统终止:同时核对容器限制、工作集和节点压力
新手30秒入门
提供 Python 与操作系统版本、启动命令、部署方式、复现负载、内存曲线、进程和子进程关系、最近变更,以及是否使用数组、数据框、图像、机器学习或 C/C++ 扩展。
先返回症状分型、最小复现、低开销采集方案和通过条件。不要先强制垃圾回收或重启,因为它们会改变时间线。
功能索引
| 任务 | 核心产出 |
|---|---|
| 症状分型 | 泄漏、峰值、缓存、碎片、复制或容量不足 |
| 负载建模 | 请求、批次、并发、输入大小与阶段 |
| 区域拆分 | Python 堆、原生堆、映射、线程、子进程 |
| 分配定位 | 分配栈、大小、次数、生命周期和所有者 |
| 存活差分 | 基线、阶段后、静置后的持续增长对象 |
| 修复评估 | 释放、流式化、复用、限界和所有权调整 |
| 回归门禁 | 斜率、峰值、吞吐、延迟和重复运行 |
标准工作流
1. 定义失败表现
记录是常驻集持续上升、单批峰值过高、周期后不回落、延迟随内存恶化,还是被系统终止。明确指标口径、单位、采样间隔和时间范围。
2. 固定运行环境
锁定解释器、依赖、扩展模块、操作系统、容器限制、进程模型、线程数和启动参数。开发环境与生产环境的分配器和负载不同,不能直接类推。
3. 建立可重复负载
控制输入大小、并发、预热、缓存、网络响应和迭代次数。对服务使用固定请求序列,对批任务按阶段打点,至少覆盖预热、稳定和问题出现三个区间。
4. 绘制进程内存地图
同时观察常驻集、虚拟内存、共享页、子进程和容器工作集。标记 Python 对象、原生库、内存映射、缓冲区、线程栈和外部进程可能占据的区域。
5. 选择采集粒度
先用低开销时间线确认增长与负载关系,再在最小复现上采集分配栈或对象差分。是否跟踪原生调用、全量分配或子进程必须按假设选择,避免采集本身改变结果。
6. 建立分配与存活证据
按调用路径汇总分配字节和次数,并比较阶段前后仍存活的对象或块。大分配热点不一定是泄漏;关键是是否超过预期生命周期且随重复负载累积。
7. 检查所有权与限界
追踪全局容器、缓存、闭包、回调、任务队列、生成器、异常追踪、循环引用、线程本地和连接池。检查缓存是否有容量与淘汰,任务结果是否被消费,批次中间量是否被同时保留。
8. 区分释放与回收可见性
对象已不可达不代表常驻集立即下降,分配器可能保留内存供后续复用。通过相同负载的稳定平台、分配数量和长期斜率判断,不以任务管理器单点作为唯一证据。
9. 设计最小修复
优先修正生命周期、清理引用、设置缓存上限、流式读取、分块计算、避免隐式复制或复用缓冲。只有确认分配器或扩展问题时才调整运行参数或替换组件。
10. 同条件回归
使用同一环境、输入、并发、预热和迭代次数比较修复前后。验证内存斜率和峰值,同时检查吞吐、延迟、CPU、I/O 与结果正确性,防止用性能退化换取表面下降。
输出规范
默认输出:
- 症状、失败阈值和内存口径
- 环境、进程模型与可重复负载
- 内存区域假设
- 采集方法、开销和时间点
- 分配热点与持续存活差分
- 根因候选及反证
- 最小修复与副作用
- 前后对照和剩余风险
证据等级使用 CONFIRMED、STRONG、PLAUSIBLE、UNVERIFIED。所有数值标明单位、采样区间、进程范围和是否包含子进程。
能力边界
- 不把单次峰值或常驻集不回落自动判为泄漏
- 不只依据对象数量忽略原生扩展和映射内存
- 不在高流量生产进程上默认开启高开销全量追踪
- 不用强制垃圾回收作为长期修复
- 不为降低峰值擅自改变结果精度或业务语义
- 不在未脱敏时分享堆转储、参数值或生产请求
- 不承诺一种分析工具覆盖所有平台与分配器
稳定性保障
- 固定解释器、依赖、平台和进程模型
- 记录预热并从稳定点比较
- 内存曲线与负载时间线使用同一时钟
- 至少比较基线、问题阶段和静置后三点
- 采集开销单独测量并写入结论
- 分配量、存活量和常驻集联合判断
- 修复前后使用完全相同的负载
- 内存改善与正确性、吞吐、延迟共同验收
深度定制
Web 服务增加请求路由、工作进程、连接池和后台任务;数据管道增加文件批次、中间表、零拷贝与分区;机器学习增加张量、设备与主机内存边界;异步系统增加未等待任务、队列积压和上下文变量;含原生扩展时增加本地调用栈、外部缓存和版本对照。
长期运行服务可建立每千请求内存斜率、稳定平台和重启前预算;短批任务重点约束峰值与同时存活数据规模。
FAQ
垃圾回收后内存没降就是泄漏吗?
不是。对象可能已释放给解释器或分配器,但内存仍保留给后续复用。需要看存活差分和重复负载斜率。
最大分配栈就是根因吗?
未必。它可能是合法峰值。持续跨越预期生命周期并累积的路径更值得优先调查。
为什么本地复现不了容器超限?
容器限制、工作集口径、并发、子进程和分配器可能不同。应尽量复制部署参数与负载形状。
重启能解决吗?
重启只能暂时释放进程资源。若增长机制未修复,问题会按相同斜率再次出现。
反模式与修正
| 反模式 | 直接后果 | 修正 |
|---|---|---|
| 只看一张内存截图 | 无法判断趋势与负载关系 | 建立带事件标记的时间线 |
| 一上来全量追踪生产 | 性能和现场被扰动 | 先低开销分型,再缩小复现 |
| 最大对象等于泄漏 | 误删必要工作集 | 比较生命周期与累积斜率 |
| 到处手动触发回收 | 掩盖所有权问题 | 找到仍被保留的引用或块 |
| 只优化内存数字 | 吞吐和正确性回退 | 多指标同条件验收 |
| 忽略子进程与原生库 | Python 对象证据对不上总量 | 绘制完整进程内存地图 |
按需 references
- 选择时间线、对象差分、分配栈或原生追踪时,读取 capture-selection.md
- 设计修复前后对照与长期门禁时,读取 leak-verification.md