Про утечки памяти в Erlang
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))).
сколько блобов сейчас захвачено процессом. В одной из устраненных ошибок это число росло где-то раз в пол-минуты. Проблема была устранена после детального изучения состояния процесса.
К счастью количество мест, куда может приткнуть потерянные данные процесс, вполне себе ограничено. Самое главное — это структура с его состоянием, которое переживает циклы. Надо внимательно посмотреть на него. В группе риска:
- списки, куда складываются приходящие из сети настройки. Именно туда раз в пол-минуты утекали данные, потому что я делал [Setting | Settings], а не lists:keyreplace, в итоге в списке накапливались кортежи с одинаковыми именами;
- списки с данными, которые выгребают медленнее, чем приходят данные из сети;
- блобовые буферы. Ещё одна утечка была связана с обработкой потока двойной вложенности. Поток первого уровня имел частые пакеты, поток уровнем выше имел пакеты гораздо реже, а я запускал вложенную обработку один раз на поток верхнего уровня, в итоге буфер накапливался;
- невыгребающиеся очереди сообщений: process_info(pid(0,2807,0), message_queue_len).
Что делать. Вполне возможно прям на ходу в живом процессе воткнуть отладочный вывод размера буферов и списков. При простом коде у меня получалось достаточно быстро найти, куда именно утекли данные.
