Python在从字典中删除项目后重新获取内存

14

我在Python中有一个相对较大的字典,希望能够不仅删除其中的项,而且实际上从程序中回收这些删除的内存。我遇到了一个问题,即使我从字典中删除了项并手动运行了垃圾回收器,Python看起来也没有释放内存。

以下是一个简单的例子:

>>> tupdict = {}
# consumes around 2 GB of memory
>>> for i in xrange(12500000):
...   tupdict[i] = (i,i)
... 
# delete over half the entries, no drop in consumed memory
>>> for i in xrange(7500000):
...   del tupdict[i]
... 
>>> import gc
# manually garbage collect, still no drop in consumed memory after this
>>> gc.collect()
0
>>> 

我猜想的情况是,虽然条目被删除并进行垃圾回收,但Python不会继续调整字典的大小。我的问题是,是否有任何简单的方法来解决这个问题,还是我需要认真重新考虑如何编写我的程序?


你是如何测量内存消耗的? - stonemetal
Ubuntu系统监视器 - Bryce Thomas
在Windows XP SP3上运行Python 2.6.5时,执行gc.collect()似乎可以释放大约50%的内存。 - Nick T
3
Windows会释放进程所使用的内存给操作系统来使用,而Linux则不会这么做,因此这是预期的行为。无论哪种操作系统都会按照各自的目的做出"正确的事情"。 - Nick Bastin
2个回答

18
很多因素会影响Python是否将内存返回给底层操作系统,这可能是您试图确定内存是否已被释放的方式。CPython具有池化分配器系统,它往往会保留已释放的内存以便以高效的方式重新使用(但从操作系统的角度来看,这些后续分配不会增加您的内存占用量),这可能就是您所看到的情况。
此外,在某些unix平台上,进程直到应用程序关闭(或发生其他重大事件)才会将空闲内存释放回操作系统。即使您处于整个池已被释放的情况下(因此Python可能决定free()它而不是保持为未来对象打开),操作系统仍不会释放这些内存以供其他进程使用(但可以在原始进程内部进行进一步重新分配)。总的来说,这对于减少内存碎片非常有利,并且没有太多的缺点,因为未使用的进程内存将被分页到磁盘上。Windows会将进程内存释放回操作系统以供任何新分配使用(然后可以在任务管理器中看到),因此在Windows上尝试这样做可能看起来会给您带来不同的结果。
最终,如何管理已释放的进程内存是操作系统的职责,并且有各种方案(具有优缺点),因此仅查看您喜欢的系统信息工具可能无法告诉您全部真相。

9

你说得对,如果从字典中删除了项,Python不会将字典大小调整回来。这与操作系统内存管理和垃圾回收无关,而是Python字典数据结构的实现细节。

一种解决方法是通过复制旧字典来创建新字典。查看此视频以获取更多信息:http://pyvideo.org/video/276/the-mighty-dictionary-55(大约在26:30处有一个答案)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接