Я также пытался решить проблемы, связанные с управлением памятью в приложениях OTP, и одним из инструментов, который был особенно полезен для меня, является библиотека, написанная Фредом Хебертом, под названием conconnection .Особенно модуль recon_alloc
, который предоставляет очень полезную информацию об использовании памяти в виртуальной машине Erlang.
Недостающие мегабайты
Следующая цитата непосредственно взята из документации по функции recon_alloc:memory()
иможет дать вам представление о том, что происходит:
Память, сообщаемая `selected ', должна приблизительно соответствовать тому, что сообщает ОС.Если это количество отличается с большим отрывом, это может быть признаком того, что кто-то выделяет память непосредственно в C, вне собственного распределителя Эрланга - большой предупредительный знак.В настоящее время существует три источника выделения памяти, которые не учитываются в этом значении: кэшированные сегменты в распределителе mseg, любая память, выделенная как супер-носитель, и небольшие фрагменты памяти, выделенные во время запуска до инициализации распределителей памяти.Также обратите внимание, что низкое использование памяти может быть признаком фрагментации в памяти, и в этом случае рекомендуется исследовать, какой конкретный распределитель виноват.
Так что я думаю, что дополнительные 23 МБ использования памяти могут бытьвызванные некоторыми нежелательными выделениями или, возможно, из-за фрагментации.
Тонкая настройка (с большой осторожностью /! \)
Что касается вашего второго вопроса, в Эрланге есть инструмент под названием erts_alloc , который также описывает ручную настройкураспределители памяти.Это может быть сделано путем передачи флагов командной строки в эмулятор, например:
erl +SOMEFLAG +SOMEOTHERFLAG
Но в документации есть большое красное предупреждение, в котором настоятельно рекомендуется, что использование этих флагов можетприведет к гораздо худшему поведению, чем при конфигурации по умолчанию.
Поэтому я бы посоветовал прибегнуть к этим модификациям, если это действительно единственный способ решить проблему.В этом случае есть книга о системе исполнения Erlang, которая помогла мне понять некоторые аспекты, поэтому я также рекомендовал бы прочитать ее заранее.
ПРИМЕЧАНИЕ: Дикий выстрел здесь, в темноте, и если вы не отвечаете на ваш вопрос напрямую, но может быть полезно дважды проверить, что происходит с вашими двоичными файлами, так как я вижу, что их 13МБ сообщил наблюдатель.В зависимости от их размера (меньше или больше, чем 64 байта), они хранятся в кучах процессов или доступны по ссылке.Я столкнулся со случаем # 1 с множеством маленьких двоичных файлов, которые в конечном итоге приводили к краху моей системы.
Есть несколько других полезных ресурсов, которые я нашел, пытаясь решить эти проблемы:
- Этот конкретный фрагмент из сообщения в блоге , автором которого является ФредХеберт, а также:
[erlang:garbage_collect(Pid) || Pid <- processes()].
Это немедленно запустит GC на всех запущенных процессах.В моем случае это творило чудеса.Вы также можете добавить опцию для асинхронного вызова, так что вам не придется блокировать, пока все не будет сделано:
[erlang:garbage_collect(Pid, [{async, RequestId}]) || Pid <- processes()].
Надеюсь, это поможет:)