Единый процесс Erlang, потребляющий больше памяти и запускающий сигнализацию высокого уровня
У меня есть erlang gen_server, который получает сообщения от клиентов асинхронно (используя приведение). При каждой обработке сообщений сервер вставляет их в упорядоченную таблицу ETS и удаляет некоторые из них в зависимости от условий (из-за условного удаления число записей в таблице ETS в большинстве случаев составляет около 5000. Но редко сценарии, которые могут увеличить этот размер до 200 КБ, вводя накладные расходы как для вставки, так и для удаления).
Это работает нормально до тех пор, пока количество сообщений в секунду не достигнет 100 Кб, но выше этого уровня я получаю максимальный уровень памяти для памяти процесса и начинает потреблять много памяти. Когда я закомментирую вставку и удаляю часть для упорядоченных ets, она может обрабатывать более 100 Кб в секунду. Можете ли вы дать мне несколько советов, как решить эту проблему?
Существует ли максимальный предел памяти, который может выделить процесс? Я использую 35 ГБ памяти, и я устанавливаю порог водяного знака с помощью memsup:set_procmem_high_watermark(0.6)
, Я также попробовал gbtree и заказал словарь, но они не решили ошибку памяти.
2 ответа
У меня есть предложение. Когда скорость превышает 100 кбит / с, gen_server не может вовремя обработать очередь сообщений, поэтому он начинает расти => gen_server замедляется и происходит утечка памяти. Попробуй контролировать erlang:process_info(Pid, message_queue_len)
если он растет.
Предел памяти процесса
Там нет такой опции в Эрланге. memsup:set_procmem_high_watermark/1
просто устанавливает порог для выделения памяти процесса. Если порог пройден, сигнал тревоги будет поднят.
В чем может быть причина проблемы?
В начале вы должны выяснить, почему ваш процесс замедляется. Как уже говорилось, проверьте характеристики своей очереди сообщений: растет ли она со временем? Если это так, ваш процесс не может обрабатывать сообщения с той скоростью, с которой они приходят. erlang:process_info/2
будет полезно
Еще одна вещь, которую нужно иметь в виду, - когда вы вставляете / просматриваете данные в ETS, объекты копируются. Таким образом, если условия, которые должны выполняться при удалении объектов, связаны с извлечением данных из ETS, это также может быть причиной вашей проблемы.
Как справиться с этим?
Есть несколько способов решения этой проблемы. Очевидным является простое использование механизма противодействия, например, чтобы клиенты отправляли сообщения синхронно.
В качестве альтернативы вы можете попытаться разделить то, что делает ваш единственный процесс, на несколько из них. Для этого у вас может быть один процесс, распространяющий сообщения среди других на основе некоторой информации, содержащейся в сообщениях.
Наконец, вы можете попытаться применить некоторую оптимизацию в отношении вашего ETS. Например, если вы храните большие объекты, вы можете проверить, не возвращаете ли вы их без необходимости (используя ets:lookup/X
вместо ets:match/X
или же ets:match_object/X
чтобы получить именно те биты, которые вы хотите из сохраненного сообщения).