可以给Python字典设定初始容量吗(有用吗)
我正在填充一个包含大约1000万个项目的Python字典。我对字典(或者说哈希表)的理解是,当里面的元素太多时,它需要重新调整大小,而这个操作会耗费不少时间。
有没有办法告诉Python字典,我至少会存储n个项目,这样它可以从一开始就分配好内存?或者说,这样的优化对我的运行速度没有帮助吗?
(另外,我并没有检查我的小脚本运行慢是否是因为这个原因,其实我也不知道怎么检查。不过在Java中,我会这样做,直接设置HashSet的初始容量。)
2 个回答
是的,你可以这样做。这里有一个我在别人提问时找到的解决方案,这个问题和你的也有关系:
d = {}
for i in xrange(4000000):
d[i] = None
# 722ms
d = dict(itertools.izip(xrange(4000000), itertools.repeat(None)))
# 634ms
dict.fromkeys(xrange(4000000))
# 558ms
s = set(xrange(4000000))
dict.fromkeys(s)
# Not including set construction 353ms
这些是初始化一个特定大小的字典的不同方法。
首先,我听说可以在初始化字典的时候设置它的大小,但我从来没有看到过相关的文档或PEP来说明这是怎么做的。
考虑到这一点,我对你提到的项目数量进行了分析,下面是一些描述。虽然每次调整字典大小可能需要一些时间,但我建议你可以先不担心这个问题,至少在你能测试它的性能之前。
在判断字典何时需要调整大小时,我们关注两个规则:元素的数量和调整的比例。当字典填满到2/3时,如果再添加一个元素就会超过这个比例,它就会自动调整大小。元素数量在50,000以下时,字典的大小会增加4倍,超过这个数量时则会增加2倍。根据你估计的10,000,000个元素(介于2^23和2^24之间),你的字典会调整大小15次(在50,000以下调整7次,在50,000以上调整8次)。在11,100,000个元素时还会再调整一次。
调整大小和替换哈希表中的当前元素确实需要一些时间,但我在想,你是否会注意到这点,尤其是你代码中其他部分的运行情况。我做了一个时间测试,比较了在字典大小从2^3到2^24的五个不同边界位置插入元素的时间,结果显示“边界”位置的插入平均比“非边界”位置多0.4纳秒。这大约是0.17%更长……可能是可以接受的。所有操作的最小时间是0.2085微秒,最大时间是0.2412微秒。
希望这些信息对你有帮助,如果你检查了代码的性能,请记得回来更新一下!我主要参考的资源是Brandon Rhodes在2010年PyCon上做的精彩演讲:强大的字典