我在其他语言中经历过这种情况。现在我在Python中遇到了同样的问题。我有一个有很多CRUD动作的字典。可以假设从字典中删除元素应该减少它的内存占用。事实并非如此。一旦字典大小增加(通常加倍),它就永远不会(?)释放分配的内存。我已经进行了这个实验:
import random
import sys
import uuid
a= {}
for i in range(0, 100000):
a[uuid.uuid4()] = uuid.uuid4()
if i % 1000 == 0:
print sys.getsizeof(a)
for i in range(0, 100000):
e = random.choice(a.keys())
del a[e]
if i % 1000 == 0:
print sys.getsizeof(a)
print len(a)
第一个循环的最后一行是6291736
。第二个循环的最后一行也是6291736
。字典的大小为0
。
那么如何解决这个问题呢?有没有办法强制释放内存?
PS:不需要随机做 - 我玩了第二个循环的范围。
答案 0 :(得分:2)
执行此操作“重新散列”以便使用更少内存的方法是创建新字典并复制内容。
本视频中解释了Python字典的实现:
有一位与会者提出同样的问题(https://youtu.be/C4Kc8xzcA68?t=1593),发言者给出的答案是:
调整大小仅在插入时计算;当字典缩小它只是获得了很多虚拟条目,当你重新填充它时,它将开始重用它们来存储密钥。 [...]您必须将键和值复制到新词典
答案 1 :(得分:1)
实际上字典可以在调整大小时缩小,但调整大小只发生在不删除键插入时。以下是来自dictresize
的{{3}}的评论:
通过分配新表并重新插入所有表来重组表 物品又来了。删除条目后,新表可能会删除 实际上比旧的小。
顺便说一下,由于另一个答案引用了PyCon 2010字典上的CPython source,并且引用似乎与上述(已存在多年)不一致,我想我会包括完整的引用,缺少部分用粗体。
调整大小仅在插入时计算。随着字典的缩小, 它只是获得了很多虚拟条目,当你重新填充它时,它会 只需重新开始使用它们来存储密钥。 直到你才会调整大小 设法以更大的尺寸再次使其三分之二满。所以 删除键时不会调整大小。你必须做一个插入来获得 它要弄清楚它需要缩小。
所以他确实说调整大小操作可以“弄清楚[字典]需要缩小”。但这只发生在插入上。显然,在调整大小期间复制所有键时,可以删除虚拟键,从而减小后备阵列的大小。
然而,目前尚不清楚如何实现这一目标,这就是为什么Rhodes说要将所有内容复制到新词典中。