2013-12-17 4 views
3

Я знаю, что у python есть своя собственная реализация управления памятью с использованием isans для объектов разного размера и многое другое, хотя я еще не нашел исчерпывающей документации. Еще я хотел бы понять, что происходит под капотом.Является ли python2 неохотой освобождать память?

Фон - это приложение для работы с базой данных python2, которое как-то кажется утечкой памяти, оно работает на 64-битном Linux. Каждый день это приложение считывает некоторые данные из БД, оно суммируется до ~ 3,5 ГБ использования ОЗУ только для чтения строк (с использованием MySQLdb). Есть около 3.5M строк, которые впоследствии уменьшаются до нескольких 100 строк, а остальная часть заканчивается («освобождена»).

Но python-2.7 освобождает только небольшую часть «неиспользуемой» памяти. Я уверен, что память будет повторно использована позже, но я заметил, что как-то эта память кажется «медленно течет». Указанное приложение БД читает этот огромный кусок данных каждый день. Чтение его дважды (или более раз) в строке выделяет только память для первого чтения, а затем, по-видимому, повторно использует эту память. Но позволяя ему работать в течение нескольких часов, а затем чтение данных БД снова создает следующий 3 + ГБ пик распределения памяти (который снова никогда не освобождается).

Чтобы добавить еще немного фона (и сделать что-то хуже для объяснения), я должен сказать, что это приложение БД не праздно, но постоянно выполняет задачи. Я уверен, что из-за мониторинга использования памяти (данных производительности nagios) использование памяти никогда не поднимается до 3,5 ГБ оперативной памяти (или даже близко) без этого конкретного запроса БД. Но с включением этого запроса каждый день добавляется 3 + ГБ оперативной памяти. Этот запрос возвращает в основном уникальные целые числа и поплавки.

Это основная причина, по которой я начал подозревать python в целом. Я чувствую, что прочитал тонны информации, посмотрел на _PyObject_DebugMallocStats(), но понятия не имею, что (или почему) python решает сохранить пару гигабайт.

Она сводится к очень простой пример (не представляя ситуацию в реальной жизни относительно данных, я знаю о xrange()):

def mem_usage(pid=None): 
    mem = 0 
    proc = str(pid or "self") 
    with open("/proc/%s/smaps" % proc) as fstat: 
     for l in fstat: 
      if not l.startswith("Private_"): 
       continue 
      mem += int(l.split(":", 1)[1].strip().split(" ", 1)[0]) 
    return mem 

mem_usage()     # reports a few MB 
x = list(range(100000000)) # use list() for py3k 
mem_usage()     # reports ~3GB 
del x 
mem_usage()     # reports ~2.5GB 

Что интересно, что py3k освобождает память, когда я удалить огромный список. Не только фракция, но и почти все, что позволяет использовать память только немного выше, чем в начале.

Я исследовал это с помощью memory_profiler (я думаю, это не делает намного больше, чем данная функция mem_usage()) без всякого понимания. Я читал о gdb-heap, но не смог заставить его работать до сих пор.

На самом деле я не считаю, что есть решение (кроме перезапуска приложения или уменьшения количества данных, считываемых из БД). Но я бы очень благодарен за понимание этой темы.

EDIT:

Резюмируя мой вопрос: Почему Питон-2,7 держать эту память, выделенную?

+1

Итак, я прочитал вашу стену здесь, и я изо всех сил стараюсь найти вопрос ... Что именно вы спрашиваете? Вы говорите, что python не освобождает память, но python3k делает ... что вы ищете? Можете ли вы резюмировать четкий ответный вопрос? – mgilson

+0

Я добавил вопрос как можно скорее :) – resi

+0

@resi Мы pythonista. Можете ли вы задать вопрос в одном лайнере? Я понял, почему python 2 не освобождает память. – thefourtheye

ответ

2

range пример держит тонну памяти вокруг, потому что Python 2.7 никогда не освобождает int S:

block_list is a singly-linked list of all PyIntBlocks ever allocated, linked via their next members. PyIntBlocks are never returned to the system before shutdown (PyInt_Fini).

Однако, это не должно быть проблемой, если в какой-то момент, несколько гигабайт ints живы одновременно. В противном случае Python будет использовать старые, отброшенные ints для представления любых новых, которые вы используете.Если у вас есть , то имеют стоимость в несколько гигабайт, я рекомендую найти способ сохранить меньше их одновременно.

+0

Я вижу проблему с PyIntBlocks, вызванную огромным количеством объектов int, существующих в одно и то же время (и то же самое с float). Я не уверен, что читаю intobject.c правильно, но псевдо-освобожденные блоки собираются в free_list и повторно используются позже, это правда? Означает ли это, что мое приложение БД использует все PyIntBlocks при повторном запуске на следующий день (когда он выполняет другой скачок в использовании памяти)? – resi

+0

Я не уверен, что обработка int и float в python 2.7 является единственной проблемой, которую я имею здесь, но не смог получить больше информации. Тем не менее вы указали это, поэтому я предполагаю, что справедливо принять ваш ответ. – resi

Смежные вопросы