Python函数在有大列表时变慢
我在测试几种不同的方法来处理我的数据时,发现了一些奇怪的现象。似乎在某个函数里,如果有一个很大的列表,即使这个函数没有用到这个列表,函数的运行速度也会明显变慢。举个例子,通过同一个生成器函数创建两个独立的列表,第二次的速度大约慢了2.5倍。如果在创建第二个列表之前先把第一个列表删除,那么两个迭代器的速度就会一样快。
def f():
l1, l2 = [], []
for c1, c2 in generatorFxn():
l1.append((c1, c2))
# destroying l1 here fixes the problem
for c3, c4 in generatorFxn():
l2.append((c3, c4))
这些列表最后大约有310万个项目,但我也在较小的列表上看到了同样的效果。第一个for
循环大约需要4.5秒来运行,而第二个则需要10.5秒。如果我在注释的位置插入l1= []
或者l1= len(l1)
,那么两个for
循环都会只需要4.5秒。
为什么函数里本地内存的分配速度和这个函数的变量当前大小有关系呢?
编辑:禁用垃圾回收器后,一切都正常了,所以这一定是因为它一直在运行。问题解决了!
4 个回答
2
我猜想,当你第一次创建列表的时候,系统有更多的内存可用,这样列表在变大的时候就不太可能需要重新分配内存。
但是,当你用第一个列表占用了相当一部分内存后,第二个列表在变大的时候就更有可能需要重新分配内存,因为Python的列表是动态大小的。
2
没有更多详细的信息,很难给出确切的答案。
作为一个非常初步的步骤,先检查一下你的主内存使用情况。如果你的内存(RAM)已经满了,操作系统就会把数据存到硬盘上,这样你的性能会非常糟糕。在这种情况下,最好的办法是把中间结果放到内存以外的地方。如果你只需要顺序读取数据,可以考虑写入一个普通文件;如果你的数据有严格的结构,可以考虑存入关系型数据库。
12
当你创建这么多新对象(300万个元组)时,垃圾回收器就会变得很慢。如果你关闭垃圾回收功能,也就是用gc.disable()这个命令,那么这个问题就解决了(而且程序运行速度会快4倍)。