python列表append内存不足_有没有办法避免Python list.append()在循环中随着列表的增长而逐渐变慢?...

您观察到的性能差是由您所使用的版本中的Python垃圾收集器中的错误引起的。升级到Python 2.7或3.1或更高版本,以重新获得Python中列表追加所期望的摊销0(1)行为。

如果无法升级,请在生成列表时禁用垃圾收集,并在完成后将其打开。

(您还可以调整垃圾回收器的触发器,或者在进行过程中有选择地调用collect,但我不会在这个答案中探索这些选项,因为它们更复杂,我怀疑您的用例可以接受上述解决方案。)

背景:

报告者观察到,随着列表长度的增长,将复杂对象(不是数字或字符串的对象)附加到列表的速度会线性减慢。

此行为的原因是垃圾收集器正在检查并重新检查列表中的每个对象,以查看它们是否符合垃圾收集的条件。此行为导致向列表中添加对象的时间线性增加。修复程序预计会在py3k中落地,因此它不应该应用于您正在使用的解释器。

测试:

我做了个测试来证明这一点。对于1k迭代,我将10k对象追加到列表中,并记录每次迭代的运行时。整体运行时差异是显而易见的。在测试的内部循环中禁用了垃圾收集,我的系统运行时为18.6秒。在整个测试中启用了垃圾收集,运行时为899.4秒

这是测试:import time

import gc

class A:

def __init__(self):

self.x = 1

self.y = 2

self.why = 'no reason'

def time_to_append(size, append_list, item_gen):

t0 = time.time()

for i in xrange(0, size):

append_list.append(item_gen())

return time.time() - t0

def test():

x = []

count = 10000

for i in xrange(0,1000):

print len(x), time_to_append(count, x, lambda: A())

def test_nogc():

x = []

count = 10000

for i in xrange(0,1000):

gc.disable()

print len(x), time_to_append(count, x, lambda: A())

gc.enable()

图形结果:红色表示gc打开,蓝色表示gc关闭。y轴按秒对数缩放。

由于这两个图在y分量上相差几个数量级,因此它们在y轴线性缩放的情况下是独立的。

有趣的是,在垃圾收集关闭的情况下,我们看到每10k个appends的运行时只有小的峰值,这表明Python的列表重新分配成本相对较低。无论如何,它们比垃圾收集成本低很多数量级。

上面这些图的密度使我们很难看出,在启用垃圾收集器的情况下,大多数间隔实际上都有很好的性能;只有当垃圾收集器循环时,我们才会遇到这种病态行为。你可以在10公里附加时间的直方图中观察到这一点。大多数数据点在每10公里附件中下降0.02秒左右。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值