python: память разделяется между StringIO?

Разделяется ли память между StringIO, если я это сделаю? У меня такое ощущение, что память процесса python не увеличилась в строке 6.

In [1]: from StringIO import StringIO
In [2]: s = StringIO()
In [3]: s.write('abcd'*10000000) # memory increases
In [4]: s.tell()
Out[4]: 40000000
In [5]: s.seek(0)
In [6]: a = StringIO(s.read()) # memory DOES NOT increase
In [7]: a.tell()
Out[7]: 0
In [8]: a.read(10)
Out[8]: 'abcdabcdab'

Однако меня беспокоит то, что когда я удаляю эти 2 переменные, потребление памяти процессом python больше не уменьшается... почему? Создает ли этот код утечку памяти?

Когда я просто использовал одну переменную, память хорошо освобождается, когда я удаляю переменную.

Мне было бы любопытно лучше понять, что здесь происходит. Спасибо.


person Michael    schedule 06.07.2013    source источник


Ответы (1)


Объект StringIO() не создает копию переданной ему строки. В этом нет необходимости, так как строки не изменяемы.

При чтении данных из объекта StringIO() порциями создаются новые строковые объекты, являющиеся подстроками исходной входной строки.

Потребление памяти никогда не снижается сразу при освобождении объектов. Выделение памяти перераспределяется ОС только по мере необходимости, и многие типы (небольших) объектов могут быть интернированы Python для повышения эффективности и никогда не освобождаются, а используются только повторно.

person Martijn Pieters    schedule 06.07.2013
comment
Хорошо, да, я понимаю, почему чтение объекта по частям создаст новые строковые объекты. Это отлично. Я просто хочу убедиться, что исходная строка данных не дублируется каждый раз, когда я создаю новый StringIO, что, похоже, верно? Я пытаюсь иметь одного писателя и несколько читателей, не дублируя необработанные данные. - person Michael; 06.07.2013
comment
Так работает со StringIO, но с cStringIO все по-другому. Использование cStringIO, кажется, дублирует строку в памяти, потому что она увеличивается каждый раз, когда я это делаю: reader = StringIO() ; reader.write(source.getvalue()) Интересно. - person Michael; 06.07.2013
comment
Обратите внимание, что вы делаете. Вместо этого вы создаете объект записи. Вместо этого используйте StringIO(source.getvalue()). - person Martijn Pieters; 06.07.2013
comment
reader.write(source.getvalue())? Вы не должны писать читателю. - person martineau; 06.07.2013
comment
о да, это хороший момент, спасибо. Однако я пробовал reader = StringIO(source.getvalue()) и когда StringIO исходит из cStringIO, он все еще кажется дублированным, учитывая, что память увеличивается на тот же размер, что и при первом создании строки. Ну, я думаю, это просто потому, что реализация StringIO может немного отличаться в cStringIO. - person Michael; 08.07.2013