Использование памяти, сообщаемое гуппи, отличается от команды ps

Я профилирую свой витой сервер. Он использует гораздо больше памяти, чем я ожидал. Его использование памяти растет со временем.

 ps -o pid,rss,vsz,sz,size,command
  PID   RSS    VSZ    SZ    SZ COMMAND
 7697 70856 102176 25544 88320 twistd -y broadcast.tac

Как видите, он стоит 102176 КБ, а именно 99,78125 МБ. И я использую гуппи из витого люка, чтобы посмотреть профиль использования памяти.

>>> hp.heap()
Partition of a set of 120537 objects. Total size = 10096636 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0  61145  51  5309736  53   5309736  53 str
     1  27139  23  1031596  10   6341332  63 tuple
     2   2138   2   541328   5   6882660  68 dict (no owner)
     3   7190   6   488920   5   7371580  73 types.CodeType
     4    325   0   436264   4   7807844  77 dict of module
     5   7272   6   407232   4   8215076  81 function
     6    574   0   305776   3   8520852  84 dict of class
     7    605   1   263432   3   8784284  87 type
     8    602   0   237200   2   9021484  89 dict of type
     9    303   0   157560   2   9179044  91 dict of zope.interface.interface.Method
<384 more rows. Type e.g. '_.more' to view.>

Гул... Кажется, что-то не так. Гуппи показывает, что общее использование памяти составляет 10096636 байт, а именно 9859,996 КБ или 9,628 МБ.

Это огромная разница. Что плохого в этом странном результате? Что я делаю неправильно?

Обновление: вчера вечером я написал скрипт монитора. Он записывает использование памяти и количество онлайн-пользователей. Это радиосервер, так что вы можете видеть, что есть радио и общее количество слушателей. Вот рисунок, который я сгенерировал с помощью matplotlib. http://static.ez2learn.com/temp/mem_figure.svg

Что-то странное Иногда использование памяти, напечатанное ps, очень мало, как это

2010-01-15 00:46:05,139 INFO 4 4 17904 36732 9183 25944
2010-01-15 00:47:03,967 INFO 4 4 17916 36732 9183 25944
2010-01-15 00:48:04,373 INFO 4 4 17916 36732 9183 25944
2010-01-15 00:49:04,379 INFO 4 4 17916 36732 9183 25944
2010-01-15 00:50:02,989 INFO 4 4 3700 5256 1314 2260

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

3 ответа

Решение

Возможно из-за подкачки / резервирования памяти, основываясь на определении ps:

RSS: resident set size, the non-swapped physical memory
     that a task has used (in kiloBytes).

VSZ: virtual memory usage of entire process.
     vm_lib + vm_exe + vm_data + vm_stack

это может немного сбивать с толку, 4 метрики разных размеров можно увидеть с:

# ps -eo pid,vsz,rss,sz,size,cmd|egrep python

PID    VSZ   RSS   SZ    SZ    CMD
23801  4920  2896  1230  1100  python

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

некоторые дополнительные инструменты для исследования производительности памяти:

хорошее руководство по отслеживанию утечек памяти в python с использованием pdb и objgraph:

http://www.lshift.net/blog/2008/11/14/tracing-python-memory-leaks

Как указано выше, размер RSS - это то, что вас больше всего интересует здесь. "Виртуальный" размер включает в себя отображаемые библиотеки, которые вы, вероятно, не хотите считать.

Прошло много времени с тех пор, как я использовал heapy, но я почти уверен, что статистика, которую он печатает, не включает служебные данные, добавленные самой heapy. Эти издержки могут быть довольно значительными (я видел, как процесс RSS на 100 МБ увеличивался еще на дюжину или около того МБ, см. http://www.pkgcore.org/trac/pkgcore/doc/dev-notes/heapy.rst).

Но в вашем случае я подозреваю, что проблема в том, что вы используете какую-то библиотеку C, которая либо пропускает, либо использует память таким образом, что heapy не отслеживает. Heapy знает о памяти, используемой непосредственно объектами python, но если эти объекты обертывают объекты C, которые выделены отдельно, heapy обычно вообще не знает об этой памяти. Возможно, вам удастся добавить поддержку heapy к вашим привязкам (но если вы не контролируете используемые привязки, это, очевидно, хлопотно, и даже если вы контролируете привязки, вы не сможете сделать это в зависимости от того, что вы упаковываете).

Если на уровне C есть утечки, heapy также потеряет память (размер RSS будет увеличиваться, но сообщаемый размер heapy останется прежним). Valgrind - это, вероятно, ваш лучший выбор, чтобы отследить их, как и в других приложениях на Си.

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

Это не полный ответ, но из вашего колодца я бы также предложил запустить gc.collect() вручную перед просмотром с помощью ps или top. Гуппи покажет выделенную кучу, но ничего не делает для упреждающего освобождения объектов, которые больше не выделяются.

Другие вопросы по тегам