новости сообщество форум вики полезно

Про утечки памяти в Erlang

09/01/2010 20:50

http://levgem.livejournal.com/261075.html

Первым делом надо понять, кто сейчас активно растет.

Если утечка памяти проявляется под небольшим количеством клиентов (скорее всего будет под одним-двумя), то запускаем клиентов на сервер, заходим в соседней консоли на сервер:

erl -name node -remsh ems@maxbook.local

Там запускаем etop:

etop:start([{output,text}]).

Немного смотрим и запоминаем пиды (что-то вида <4535.424.0>) тех процессов, которые склонны к распуханию. Нам потребуется только вторая часть этого вида. Первая будет ненулевой из-за того, что удаленная консоль физически находится в другой ноде, а третья скорее всего будет нулем и нас не интересует. Соседняя нода нужна потому что из etop-а кроме как прибив консоль не выйдешь (на самом деле, надо нажать ^G, i, c)

Дальше нам нужно выяснить про сбойные процессы всё, что нужно.

process_info(pid(0,2807,0), [memory,total_heap_size]).

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

Интерес предоставит ещё одна характеристика:

length(element(2, process_info(pid(0,2807,0), binary))).

сколько блобов сейчас захвачено процессом. В одной из устраненных ошибок это число росло где-то раз в пол-минуты. Проблема была устранена после детального изучения состояния процесса.

К счастью количество мест, куда может приткнуть потерянные данные процесс, вполне себе ограничено. Самое главное — это структура с его состоянием, которое переживает циклы. Надо внимательно посмотреть на него. В группе риска:

  1. списки, куда складываются приходящие из сети настройки. Именно туда раз в пол-минуты утекали данные, потому что я делал [Setting | Settings], а не lists:keyreplace, в итоге в списке накапливались кортежи с одинаковыми именами;
  2. списки с данными, которые выгребают медленнее, чем приходят данные из сети;
  3. блобовые буферы. Ещё одна утечка была связана с обработкой потока двойной вложенности. Поток первого уровня имел частые пакеты, поток уровнем выше имел пакеты гораздо реже, а я запускал вложенную обработку один раз на поток верхнего уровня, в итоге буфер накапливался;
  4. невыгребающиеся очереди сообщений: process_info(pid(0,2807,0), message_queue_len).

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


 
 
 
 

так же

Ссылки

via

См. также

twitter