Python垃圾回收后为何存在未释放的剩余内存
问题现象
测试过程中创建包含1000万元素的大型列表,尝试将变量赋值为None解除引用,等待垃圾回收器释放内存:
l = list(range(0, 10000000)) l = None
使用memory_profiler检测内存变化,发现内存没有完全释放,检测输出如下:
Line # Mem usage Increment Occurrences Line Contents ============================================================= 8 427.3 MiB 382.7 MiB 1 l = list(range(0, 10000000)) 9 122.3 MiB -305.0 MiB 1 l = None
剩余内存未释放的原因
这属于Python内存管理机制下的正常现象,不是内存泄漏,具体原因如下:
- 内存池留存策略:Python默认使用自带的pymalloc分配器管理小对象内存,不会在对象被垃圾回收后立刻把内存交还给操作系统。pymalloc以256KB大小的arena为单位向操作系统申请内存,只有当单个arena内的所有内存块都完全空闲时,才会把这部分内存归还给系统;其余释放的内存块会被留在内部内存池中,留给后续新建的Python对象直接复用,减少频繁向操作系统申请/释放内存的性能开销。
- 内存碎片与arena占用规则:大列表申请的是连续内存空间,释放时如果某个arena内存块里还存在哪怕一个存活的Python对象,整个arena的内存都不会被交还给操作系统。被存活对象分割出的零散空闲内存块无法满足操作系统连续内存回收的要求,就会滞留在进程内存空间中。
- 统计口径差异:
memory_profiler统计的是Python进程向操作系统申请的常驻内存总大小,不是Python解释器当前实际被存活对象占用的内存大小。执行l = None后,原列表对象已经被垃圾回收器标记为可回收,这部分内存对Python来说已经是可复用的空闲状态,只是没有交回给操作系统,因此会被统计为进程仍在占用的内存。
这部分留存的内存不会造成内存泄漏,后续代码创建新对象时,Python会优先使用内存池中的空闲块,不会无限制向操作系统申请新内存。
内容的提问来源于stack exchange,提问作者Michael Dorner
相关产品推荐
相关产品推荐

