Как найти источник увеличения использования памяти скрученным сервером?

У меня есть сервер аудиовещания, написанный на Python и основанный на Twisted. Он работает нормально, но использование памяти увеличивается, когда на сервере больше пользователей, но использование памяти никогда не снижается, когда эти пользователи отключаются от сети. Как видно на следующем рисунке: < img src="https://web.archive.org/web/20131225020657/https://static.ez2learn.com/temp/mem_figure3.svg" alt="alt text">

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

Я пробовал следующий метод для решения этой проблемы:

  1. Обновление Twisted с 8.2 до 9.0
  2. Используйте гуппи для сброса кучи, но совсем не помогает
  3. Переключите селекторный реактор на реактор epoll, та же проблема.
  4. Используйте objgraph, чтобы нарисовать диаграмму отношения объектов, но я не вижу точек от этого.

Вот среда, которую я использовал для запуска моего скрученного сервера:

  • Питон: 2.5.4 r254:67916
  • ОС: Linux версии 2.6.18-164.9.1.el5PAE ([email protected]) (версия gcc 4.1.2 20080704 (Red Hat 4.1.2-46))
  • Витая: 9.0 (под виртуалкой)

Свалка гуппи:

Partition of a set of 116280 objects. Total size = 9552004 bytes.
 Index  Count   %     Size   % Cumulative  % Type
  0  52874  45  4505404  47   4505404  47 str
  1   5927   5  2231096  23   6736500  71 dict
  2  29215  25  1099676  12   7836176  82 tuple
  3   7503   6   510204   5   8346380  87 types.CodeType
  4   7625   7   427000   4   8773380  92 function
  5    672   1   292968   3   9066348  95 type
  6    866   1    82176   1   9148524  96 list
  7   1796   2    71840   1   9220364  97 __builtin__.weakref
  8   1140   1    41040   0   9261404  97 __builtin__.wrapper_descriptor
  9   2603   2    31236   0   9292640  97 int

Как видите, общий размер 9552004 байта составляет 9,1 МБ, и вы можете увидеть rss, сообщаемый командой ps:

[xxxx@webxx ~]$ ps -u xxxx-o pid,rss,cmd
  PID   RSS CMD
22123 67492 twistd -y broadcast.tac -r epoll

RSS моего сервера составляет 65,9 МБ, это означает, что на моем сервере 56,8 МБ используется невидимая память, что это такое?

Мои вопросы:

  1. Как найти источник увеличения использования памяти?
  2. Что такое видимое использование памяти для гуппи?
  3. Что это за невидимое использование памяти?
  4. Это вызвано утечкой памяти некоторых модулей, написанных на C? Если это так, как я могу отследить и исправить это?
  5. Как Python управляет памятью? Пул памяти? Я думаю, что это может быть вызвано фрагментами аудиоданных. Так что есть небольшие утечки в куске памяти, принадлежащем интерпретатору Python.

Обновление от 20 января 2010 г.: интересно, я загружаю последний файл журнала, и он показывает, что память никогда не увеличивается с момента. Я думаю, что может быть выделенное пространство памяти достаточно велико. Вот последняя цифра. alt text

Обновление от 21 января 2010 г.. Еще одна цифра. гм.... поднимите немного альтернативный текст

Упс... Все еще растет < img src="https://web.archive.org/web/20131224033058/https://static.ez2learn.com/temp/mem_figure7.svg" alt="alt text">


person Fang-Pen Lin    schedule 20.01.2010    source источник
comment
Re update: он все еще растет, даже когда количество ваших пользователей снижается, поэтому я бы не назвал это хорошим поведением. Приятно осознавать, что это не продолжится, пока не произойдет смерть от замены...   -  person Wim    schedule 21.01.2010
comment
Сервер работает в реальной среде, в таких условиях очень сложно найти причину. Мне нужно некоторое время, чтобы упростить мою программу и создать симулятор и инструменты тестирования, чтобы я мог запускать сервер в тестируемой среде. Я сообщу о том, что я вижу, как только я закончу работу.   -  person Fang-Pen Lin    schedule 21.01.2010


Ответы (3)


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

  1. размер куска 511
  2. размер куска 1040
  3. размер куска 386
  4. размер куска 1350
  5. ...

Большинство из них больше 256 байт, Python использует malloc для кусков больше 256 байт, а не использует пул памяти. И вы можете себе представить, что эти куски выделяются и освобождаются, что происходит? Например, когда блок размером 1350 освобождается, в куче может быть свободное место размером 1350 байт. После этого приходит еще один запрос 988, один раз malloc подхватывает дырку, а потом появляется еще одна новая маленькая свободная дырочка размера 362. После долгого бега дырочек в кучах становится все больше и больше, другими словами есть так много фрагментов в кучах. Размер страницы виртуальной памяти обычно составляет 4 КБ, эти фрагменты распределены по большому диапазону кучи, из-за чего ОС не может выгрузить эти страницы. Таким образом, RSS всегда высокий.

После изменения дизайна модуля управления аудиофрагментами моего сервера он теперь использует мало памяти. Вы можете увидеть рисунок и сравнить с предыдущим.

alt text

В новом дизайне используется массив байтов, а не список строк. Это большой кусок памяти, поэтому больше нет фрагментации.

person Fang-Pen Lin    schedule 09.02.2010

Для меня это звучит как утечка памяти в модуле C. Valgrind — хороший инструмент для отслеживания проблем, связанных с выделением памяти. Я не знаю, насколько хорошо это работает с загружаемыми во время выполнения модулями...

person Wim    schedule 20.01.2010

Вы думали об использовании альтернативы CentOS для dtrace - SystemTap, я думаю, это называется.

Это должно дать вам довольно низкоуровневую трассировку того, что происходит внутри ваших *nix-процессов....... удар в темноте, но может дать вам больше прозрачности внутрипроцессной активности.

Интересный вопрос однако. С нетерпением жду ответов других.

Бен

person Ben Hughes    schedule 20.01.2010