Один процесс erlang потребляет больше памяти и запускает аварийные сигналы высокого уровня памяти процесса.

У меня есть erlang gen_server, который асинхронно получает сообщения от клиентов (используя приведение). При обработке каждого сообщения сервер вставляет их в упорядоченную таблицу ETS и удаляет некоторые из них в зависимости от условий (из-за условного удаления количество записей в таблице ETS в большинстве случаев составляет около 5000. Но есть редкие сценарии, которые могут увеличить этот размер до 200 КБ, что приводит к накладным расходам как на вставку, так и на удаление).

Это работает нормально до тех пор, пока количество сообщений в секунду не достигнет 100 КБ, но выше этого я получаю верхний водяной знак памяти процесса и начинает потреблять много памяти. Когда я комментирую часть вставки и удаления в упорядоченный ets, он может обрабатывать более 100 тыс. В секунду. Не могли бы вы дать мне несколько советов о том, как решить эту проблему?

Существует ли какой-либо максимальный объем памяти, который может выделять процесс? Я использую 35 ГБ памяти и установил порог водяного знака на memsup:set_procmem_high_watermark(0.6). Я также попробовал gbtree и заказал словарь, но они не решили проблему с памятью.


person Chathuri Gunawardhana    schedule 31.03.2016    source источник
comment
Я думаю, что очередь сообщений слишком длинная, ваш gen_server не может быстро обработать сообщение. Не могли бы вы поделиться своим кодом?   -  person BlackMamba    schedule 01.04.2016


Ответы (2)


У меня есть предложение. Когда она достигает более 100k/s, gen_server не может вовремя обрабатывать очередь сообщений, поэтому она начинает расти => gen_server становится медленнее и происходит утечка памяти. Попробуйте следить за erlang:process_info(Pid, message_queue_len), если он растет.

person nikit    schedule 31.03.2016
comment
В Erlang нет утечки памяти, однако я также подозреваю, что очередь сообщений растет, поглощая память процесса. process_info также можно использовать для получения большей информации о процессе, а не только о длине очереди, то есть о выделенной куче/стеке. Другой возможностью было бы установить recon, чтобы обеспечить лучший мониторинг узла, также см. этот ответ: stackoverflow.com/questions/36184551/ - person Greg; 31.03.2016

Лимит памяти процесса

В Эрланге такой опции нет. memsup:set_procmem_high_watermark/1 просто устанавливает порог для выделения памяти процесса. Если порог будет пройден, будет поднята тревога.

Что может быть причиной проблемы?

В начале вы должны выяснить, почему ваш процесс замедляется. Как уже говорилось здесь, проверьте характеристики вашей очереди сообщений: растет ли она со временем? Если это так, ваш процесс не может обрабатывать сообщения с той скоростью, с которой они приходят. erlang:process_info/2 будет полезно.

Еще одна вещь, о которой следует помнить, это то, что когда вы вставляете/ищете данные в ETS, объекты копируются. Таким образом, если условия, которые должны быть выполнены при удалении объектов, включают получение данных из вашей ETS, это также может быть возможной причиной вашей проблемы.

Как справиться с этим?

Есть несколько подходов к решению этой проблемы. Очевидным является простое использование механизма обратного давления, например, заставляя клиентов отправлять сообщения синхронно.

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

Наконец, вы можете попытаться применить некоторую оптимизацию в отношении вашего ETS. Например, если вы сохраняете большие объекты, вы можете проверить, не извлекаете ли вы их обратно без необходимости (используя ets:lookup/X вместо ets:match/X или ets:match_object/X, чтобы получить именно те биты, которые вам нужны, из сохраненного сообщения).

person mentels    schedule 01.04.2016
comment
Я думаю, что ets: вставка и удаление занимают некоторое время, что приводит к постепенному росту очередей сообщений (я не читаю из ets, и, поскольку я использую упорядоченный ets для удаления, я удаляю соответствующие объекты, начиная с корня, пока не будет выполнено условие ). Отслеживал тяжелую очередь сообщений и большую кучу. Я попробую разделить вставки и удаления на 2 процесса. Большое спасибо за ваши предложения. - person Chathuri Gunawardhana; 01.04.2016
comment
Вот код для gen_server, включая вставки и удаления. Пожалуйста, дайте мне знать, если я делаю что-то неэффективное ="nofollow noreferrer">github.com/chathurilanchana/riak_kv/blob/ ]. - person Chathuri Gunawardhana; 01.04.2016