![](/img/trans.png)
[英]process in python for loop slows down, even when resetting the list
[英]Python function slows down with presence of large list
我正在测试几种不同方法对我的一些数据进行复杂迭代的速度,我发现了一些奇怪的东西。 似乎在某些 function 本地有一个大列表会大大减慢 function 的速度,即使它没有触及该列表。 例如,通过同一个生成器 function 的 2 个实例创建 2 个独立列表,第二次的速度大约慢 2.5 倍。 如果在创建第二个列表之前删除了第一个列表,则两个迭代器 go 的速度相同。
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 秒。 如果我在评论 position 中插入l1= []
或l1= len(l1)
,则两个for
循环都需要 4.5 秒。
为什么 function 中本地 memory 分配的速度与该函数变量的当前大小有关?
编辑:禁用垃圾收集器可以修复所有问题,因此必须是由于它不断运行。 结案!
当您创建那么多新对象(300 万个元组)时,垃圾收集器就会陷入困境。 如果您使用 gc.disable() 关闭垃圾收集,问题就会消失(并且程序运行速度快 4 倍以启动)。
没有更详细的仪器是不可能的。
作为一个非常非常初步的步骤,检查您的主要 memory 使用情况。 如果您的 RAM 已全部填满并且您的操作系统正在分页到磁盘,那么您的性能将非常糟糕。 在这种情况下,您最好将中间产品放在 memory 以外的其他地方。 如果您只需要顺序读取数据,请考虑写入普通文件; 如果您的数据遵循严格的结构,请考虑持久化到关系数据库中。
我的猜测是,当创建第一个列表时,有更多的 memory 可用,这意味着随着列表的增长,需要重新分配的机会更少。
在您使用第一个列表占用相当大的 memory 块后,您的第二个列表随着 python 列表的大小是动态大小的而增长,因此需要重新分配的可能性更高。
在 function 返回之前,function 本地数据使用的 memory 不会被垃圾收集。 除非您需要进行切片,否则对大型 collections 数据使用列表并不是一个好主意。
从您的示例来看,创建这些列表的目的并不完全清楚。 您可能需要考虑使用生成器而不是列表,尤其是在列表将被迭代的情况下。 如果您需要对返回数据进行切片,请在那时将生成器转换为列表。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.