为什么python字符串串联被证明是最容易记忆的?

时间:2019-05-13 14:01:26

标签: python-3.x memory-management centos ram

我正在研究python内存管理算法和底层C代码,并测试了它的工作方式,获得了意外的结果。

基础

使用多种方法在6 Gb RAM CentOS虚拟机上生成5.5 Gb字符串。生成是通过dict来完成的,在dict中,应该显示多少符号应进行多少次排序(例如{3: 5, 1: 3}应该给出'11133333')。

期望

  • ''.join()应该起作用,因为它使用memcpy(),并且它将使用的最大值是字符串的一部分,再加上iterable的下一部分。尽管dict对象创建了缓冲区,但似乎可以很好地与swap配合使用。自定义可迭代对象的粒度将在速度和内存使用之间进行权衡。
  • ''.format()实际上会释放内存,因此它应该工作得更快更好。
  • s1+=s2应该是最重的内存,因为它将两个字符串都保存在内存中并为新字符串创建一个缓冲区。

结果

一切均因MemoryError失败,除了: -''.join(),造粒最少 -...串联。

python -m dis pymemory.py向我显示了“ INPLACE_ADD”以进行串联操作,该操作与我看过的C代码不兼容。

代码

代码已被剥离,显然所有方法都应单独运行。

b = {
    0: 590615000,
    1: 591234001,
    2: 590895000,
    3: 590010000,
    4: 591552000,
    5: 590375000,
    6: 589251000,
    7: 589903000,
    8: 590806000,
    9: 590939000
}

# literal format
a = '{}{}{}{}{}{}{}{}{}{}'.format(str(0)*b[0], str(1)*b[1], str(2)*b[2], str(3)*b[3], str(4)*b[4], str(5)*b[5], str(6)*b[6], str(7)*b[7], str(8)*b[8], str(9)*b[9])
del a


# format
# MEMORY ERROR
d = {}
for k in b:
    d['k'+str(k)] = str(k)*b[k]
a = ('{}'*d.keys().__len__()).format(*['{'+str(k)+'}' for k in sorted(d.keys())]).format(**d)
del a
del d

# join
# MEM ERROR
def i_am_iter(d):
    for k in d:
        yield str(k)*d[k]
    raise StopIteration
a = ''.join(i_am_iter(b))

# concat
# WORKS!
a = ''
for k in b:
    a += str(k)*b[k]

问题

对此有解释吗?为什么串联有效?为什么不加入或格式化?我在某处缺少优化吗?

1 个答案:

答案 0 :(得分:0)

好吧,所以事实证明,如果只有一个对对象的引用,就对concat进行了优化,这使它就位并且比大多数其他东西(联接和格式除外)和大多数内存消耗(包括联接和格式)快得多)。 http://blog.mclemon.io/python-efficient-string-concatenation-in-python-2016-edition https://docs.python.org/release/2.4.2/whatsnew/node12.html#SECTION0001210000000000000000