Восстановление памяти Python после удаления элементов в словаре

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

Простой пример:

>>> tupdict = {}
# consumes around 2 GB of memory
>>> for i in xrange(12500000):
...   tupdict[i] = (i,i)
... 
# delete over half the entries, no drop in consumed memory
>>> for i in xrange(7500000):
...   del tupdict[i]
... 
>>> import gc
# manually garbage collect, still no drop in consumed memory after this
>>> gc.collect()
0
>>> 

Я предполагаю, что происходит то, что, хотя записи удаляются и сборщик мусора запускается, Python не идет вперед и не изменяет размер словаря. Мой вопрос в том, есть ли какой-нибудь простой способ обойти это, или мне, вероятно, потребуется более серьезное переосмысление того, как я пишу свою программу?

Ответ 1

Множество факторов зависит от того, возвращает ли Python эту память в базовую ОС или нет, что, вероятно, связано с тем, как вы пытаетесь определить, освобождается ли память. CPython имеет объединенную систему распределения, которая имеет тенденцию удерживаться в освобожденной памяти, чтобы ее можно было повторно использовать эффективным образом (но эти последующие распределения не увеличивают объем вашей памяти с точки зрения ОС), что может быть тем, re вид.

Кроме того, на некоторых платформах unix процессы не освобождают освобожденную память до ОС до тех пор, пока приложение не закроется (или произойдет какое-то другое значительное событие). Даже если вы находитесь в ситуации, когда весь пул освобожден (и, следовательно, Python может решить освободить(), а не держать его открытым для будущих объектов), ОС все равно не освободит эту память для использования другими процессами (но может использоваться для дальнейшего перераспределения в исходном процессе). В общем, это хорошо для сокращения фрагментации памяти и не имеет слишком большого количества недостатков, поскольку неиспользуемая память процесса будет выгружаться на диск. Windows выпускает память процесса обратно в ОС для использования любым новым распределением (которое вы можете увидеть в диспетчере задач), поэтому попытка этого в Windows, скорее всего, даст вам другой результат.

В конце концов, как управлять освобожденной памятью процесса является областью действия операционной системы, и существуют различные схемы (с переменами и минусами), используемые таким образом, что просто поиск в вашем системном информационном инструменте по выбору не обязательно скажет вам вся правда.

Ответ 2

Вы правы, что Python не изменяет размер словаря назад, если элементы удалены из словаря. Это не имеет никакого отношения к управлению памятью ОС и сбору мусора, это деталь реализации структуры данных Python dict.

Обходной путь - создать новый словарь, скопировав старый словарь. Проверьте это отличное видео для получения дополнительной информации: http://pyvideo.org/video/276/the-mighty-dictionary-55 (около 26:30 есть ответ).