Использование памяти, сообщаемое гуппи, отличается от команды 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
виртуальный размер включает в себя память, которая была зарезервирована процессом и не используется, размер всех общих библиотек, которые были загружены, страницы, которые были выгружены, и блоки, которые уже были освобождены вашим процессом, поэтому он может быть намного больше, чем размер всех живых объектов в питоне.
некоторые дополнительные инструменты для исследования производительности памяти:
Heapy (часть Guppy, которую вы используете): http://guppy-pe.sourceforge.net/
Python Memory Validator http://www.softwareverify.com/python/memory/index.html
PySizer http://pysizer.8325.org/
хорошее руководство по отслеживанию утечек памяти в 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. Гуппи покажет выделенную кучу, но ничего не делает для упреждающего освобождения объектов, которые больше не выделяются.