我为什么会在这个python循环中泄漏内存?
我正在写一个自定义的文件系统爬虫,这个爬虫需要处理通过sys.stdin传入的数百万个文件路径模式(globs)。我发现当运行这个脚本时,它的内存使用量随着时间的推移大幅增加,整个程序几乎变得非常缓慢。我下面写了一个简单的例子来展示这个问题。我是在做错什么,还是发现了Python或glob模块的一个bug?(我使用的是Python 2.5.2)
#!/usr/bin/env python
import glob
import sys
import gc
previous_num_objects = 0
for count, line in enumerate(sys.stdin):
glob_result = glob.glob(line.rstrip('\n'))
current_num_objects = len(gc.get_objects())
new_objects = current_num_objects - previous_num_objects
print "(%d) This: %d, New: %d, Garbage: %d, Collection Counts: %s"\
% (count, current_num_objects, new_objects, len(gc.garbage), gc.get_count())
previous_num_objects = current_num_objects
输出结果看起来是这样的:
(0) This: 4042, New: 4042, Python Garbage: 0, Python Collection Counts: (660, 5, 0) (1) This: 4061, New: 19, Python Garbage: 0, Python Collection Counts: (90, 6, 0) (2) This: 4064, New: 3, Python Garbage: 0, Python Collection Counts: (127, 6, 0) (3) This: 4067, New: 3, Python Garbage: 0, Python Collection Counts: (130, 6, 0) (4) This: 4070, New: 3, Python Garbage: 0, Python Collection Counts: (133, 6, 0) (5) This: 4073, New: 3, Python Garbage: 0, Python Collection Counts: (136, 6, 0) (6) This: 4076, New: 3, Python Garbage: 0, Python Collection Counts: (139, 6, 0) (7) This: 4079, New: 3, Python Garbage: 0, Python Collection Counts: (142, 6, 0) (8) This: 4082, New: 3, Python Garbage: 0, Python Collection Counts: (145, 6, 0) (9) This: 4085, New: 3, Python Garbage: 0, Python Collection Counts: (148, 6, 0)
每进行100次迭代,就会释放100个对象,所以len(gc.get_objects()
每100次迭代就增加200。len(gc.garbage)
始终保持为0。第二代的垃圾回收次数缓慢增加,而第0代和第1代的次数则是上下波动。
2 个回答
2
我在我的系统上没有发现任何实际的内存泄漏,但我觉得你提到的“每100次迭代释放100个对象”可能是因为你在使用编译好的正则表达式缓存(通过glob模块)。如果你查看一下re.py文件,你会发现_MAXCACHE
的默认值是100,而一旦达到这个值,整个缓存就会被清空(在_compile
中)。如果你在调用gc
之前先调用re.purge()
,你可能会发现这个效果消失了。
(我在这里建议使用re.purge()
只是为了检查缓存是否影响了你的垃圾回收结果。实际上,你的代码中不需要包含这个。)
不过,我怀疑这能解决你内存激增的问题。
7
我发现这个问题是和fnmatch模块有关的。glob.glob这个函数会调用fnmatch来进行文件匹配,而fnmatch有一个缓存,用来存储正则表达式,这个缓存是不会被清空的。所以在这种情况下,缓存会不断增长,而且没有限制。我已经对fnmatch库提交了一个bug报告。
[1]: http://bugs.python.org/issue7846 Python Bug