Я работаю над демоном Haskell, который получает и обрабатывает запросы JSON. В то время как операции демона сложны, основная структура намеренно остается простой: ее внутреннее состояние - это просто IORef
с структурой данных, и все потоки выполняют атомарные операции над этим IORef
. Затем есть несколько потоков, которые на триггере принимают значение a что-то с ним.
Проблема заключается в том, что демона утечка памяти, и я не могу понять, почему. Это, безусловно, связано с запросами: когда демон получает несколько запросов в секунду, он течет примерно как 1 МБ/с (как сообщается инструментами Linux). Потребление памяти неуклонно увеличивается. Без запросов потребление памяти остается постоянным.
Что меня озадачивает, что ничто из этого не показывает в профилировании GHC. Либо я пропускаю что-то в параметрах профилирования, либо память потребляется чем-то другим:
Выполнить с +RTS -hc -xt -p
:
Запустите с помощью +RTS -hr -xt -p
:
Во время этого пробного запуска демона впоследствии потребляет более 1 ГБ. Таким образом, данные профилирования явно не соответствуют фактической потребляемой памяти на порядки. (Я понимаю, что RTS, GC и профилирование сами по себе добавляют к реальному потреблению памяти, но эта разница слишком велика и не соответствует постоянно растущему потреблению.)
Я уже пробовал rnf
все данные состояния демона внутри IORef
, а также разобранные JSON-запросы (чтобы избежать частичных JSON-строк), но без особого успеха.
Любые идеи или предложения приветствуются.
Обновление: Демон работает без -threaded
, поэтому нет потоков уровня ОС.
Статистика GC намного ближе к профилированию кучи, чем к числам, указанным в Linux:
Alloc Copied Live GC GC TOT TOT Page Flts
bytes bytes bytes user elap user elap
[...]
5476616 44504 2505736 0.00 0.00 23.21 410.03 0 0 (Gen: 0)
35499296 41624 2603032 0.00 0.00 23.26 410.25 0 0 (Gen: 0)
51841800 46848 2701592 0.00 0.00 23.32 410.49 0 0 (Gen: 0)
31259144 36416 2612088 0.00 0.00 23.40 410.61 0 0 (Gen: 0)
53433632 51976 2742664 0.00 0.00 23.49 412.05 0 0 (Gen: 0)
48142768 50928 2784744 0.00 0.00 23.54 412.49 0 0 (Gen: 0)
[...]
Обновление 2: я нашел причину проблемы, утечка памяти вызвана handleToFd
(см. эту проблему для библиотека unix). Мне просто интересно, как можно было бы более точно определить такую утечку (возможно, в чужом фрагменте кода).