Python2.7 range函数在Ubuntu16.04下内存无法释放是什么原因?
Python2.7 range内存未释放问题原因解答
核心原因
这个现象不是内存泄漏,是不同系统底层C库的内存分配策略差异导致的,具体逻辑如下:
- Python2.7中
range会直接生成包含所有元素的完整列表,你运行的代码中range(int(1e8))会生成1亿个整数的列表,占用约2~3GB内存。执行del a和gc.collect()后,这部分内存已经被Python解释器标记为空闲,可以被后续Python代码的内存申请复用,只是没有返还给操作系统而已。 - Ubuntu16.04使用glibc的
ptmalloc作为默认内存分配器,为了降低频繁申请/释放内存的系统调用开销,ptmalloc会将释放的大内存块缓存在进程的内存池中,除非达到特定的修剪阈值,否则不会主动调用系统调用把内存还给操作系统,所以你用htop会看到内存一直被占用。 - macOS使用的BSD libc内置的malloc实现,对大内存块的释放策略更激进,大内存释放后会立即返还给操作系统,所以你在macOS上不会复现这个问题。
验证方式
你可以在gc.collect()之后追加一行新的内存申请代码:b = range(int(1e8)),再通过htop观察会发现内存占用不会再次上涨,说明之前的空闲内存已经被Python直接复用了,不存在泄漏。
优化方案
- 日常使用优先用Python2.7内置的
xrange代替range,xrange是惰性迭代器,不会一次性生成所有元素,内存占用仅几十字节。 - 如果业务场景必须使用大内存列表,可以将大内存计算逻辑放到独立子进程中运行,子进程退出后所有关联内存都会被操作系统直接回收,不需要依赖Python解释器的内存释放策略。
内容的提问来源于stack exchange,提问作者Che Huu
相关产品推荐
相关产品推荐

