Утечки памяти из процессов GenServer - PullRequest
0 голосов
/ 12 сентября 2018

В последнее время у меня возникли небольшие проблемы: объем памяти, используемой процессами GenServer, очень высок, возможно, из-за больших двоичных утечек.

Отсюда проблема: мы получаем большие двоичные файлы через GenServer и передаем их потребителю, который затем взаимодействует с этими данными. Теперь эти большие двоичные файлы никогда не присваиваются переменной, и GC не обрабатывает их.

Я пытался перевести процессы в спящий режим после управления данными, что частично работало, потому что память, используемая процессами, сильно уменьшилась, но, поскольку двоичные файлы не получали GC, объем используемой ими памяти медленно, но неуклонно увеличивался, с 30 МБ без гибернации до 200 МБ с гибернацией процесса за 25 минут.

Я также попытался установить :erlang.system_flag(:fullsweep_after, 0), что также сработало и уменьшило объем памяти, используемой процессами, примерно на 20%.

До и после . Я должен сказать, что время от времени до 60-70 МБ используется процессами.

Редактировать: Использование: recon.bin_leak (15) освобождает много памяти - результат из: recon.bin_leak (15)

Во всяком случае, используемая память все еще высока, и я полностью уверен, что это можно исправить.

Здесь у вас есть скриншот, сделанный у наблюдателя на вкладке Процессы. Как видите, GenServer - это тот, кто пожирает память, как монстр печенья.

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

Любая помощь приветствуется.

Код находится в этом хранилище Github

Код интереса , который, вероятно, вызывает это + Дерево приложений . 3 из 4 процессов (<0.294.0>, <0.295.0>, <0.297.0> используют 27 МБ памяти .

Заранее спасибо за чтение.

1 Ответ

0 голосов
/ 13 сентября 2018

Вы можете попытаться добавить атом :hibernate к вашим handle_events возвращаемым значениям в ваших связанных с GenStage модулях.Например:

def handle_events(events, _from, %{handler: handler, public: public} = state) do
  public = handle(handler, events, public)
  {:noreply, [], %{state | public: public}, :hibernate}
end

Другой вариант - записать PID после :recon.bin_leak(), а затем передать их на Process.info(PID), чтобы получить дополнительную информацию о нарушающих GenServers.

Некоторые дополнительные ресурсы: https://elixirforum.com/t/extremely-high-memory-usage-in-genservers/4035/23

https://www.erlang -in-anger.com / (в частности, глава 7 по утечкам памяти)

...