标准答案

  1. 引用计数归零通常立即释放,但循环引用需要 cyclic GC 检测。
  2. 全局缓存、闭包、事件回调、任务和生成器都可能长期持有对象。
  3. Python allocator 可能保留内存给进程,即使对象释放后 RSS 仍不立即下降。
  4. 用 tracemalloc、对象统计、堆快照和业务流量趋势区分真实泄漏和分配器行为。

题目解析

CPython 引用计数通常立即释放无环对象,循环引用交给 cyclic GC;但释放对象后分配器可能保留内存,RSS 不一定立即下降。C 扩展、Buffer 和 native 资源还可能绕开普通对象统计。

排查要比较 heap/tracemalloc、对象引用、GC 后基线、RSS、流量和缓存/队列。全局字典、闭包、监听器、Task 和生成器都可能延长对象生命周期。

gc.collect 可以帮助验证但不是容量方案。缓存和队列要有上限、TTL、淘汰和清理,修复后要用重复流量确认基线稳定。

常见误区

  • 误区:只看 RSS 就判定泄漏。改正:区分 Python 对象、C 扩展、Buffer、分配器保留和真实引用链。
  • 误区:频繁 gc.collect 作为根因修复。改正:定位长期引用和无界数据,GC 只用于验证或辅助回收。
  • 误区:全局字典缓存没有上限和 TTL。改正:设置容量、过期、淘汰和监控。

作者信息