Почему конкатенация строк Python оказывается самой легкой в ​​памяти? - PullRequest
1 голос
/ 13 мая 2019

Я копался в алгоритмах управления памятью Python и лежал в основе кода C и проверял, как он работает, получая неожиданный результат.

База

Создайте строку 5,5 ГБ на виртуальной машине CentOS с ОЗУ 6 ГБ, используя несколько методов. Генерация осуществляется через диктовку, в которой говорится, сколько раз должны появиться символы, отсортированные (например, {3: 5, 1: 3} должно давать «11133333»).

Expectation :

  • ''.join() должно работать, потому что он использует memcpy (), и максимум, который он будет использовать, является частью строки плюс следующая часть итерируемой. Хотя он создает буфер, объекты 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 голосов
/ 14 мая 2019

Хорошо, получается, что если есть только одна ссылка на объект, есть оптимизация 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

...