Утечка памяти с H20 в Python веб-приложении - PullRequest
0 голосов
/ 12 апреля 2020

Мой механизм принятия решений построен на python - flask фреймворке с uWSGI и Nginx. В рамках оценки пользователя с помощью HTTP-запроса я запускаю системы показателей с h2o == 3.20.0.7, чтобы сгенерировать оценку для принятия решения о пользователе. Ниже приведены некоторые ясности о том, как я использую h2o в своем приложении

h2o.init()  # initialize 

predictions = h2o.mojo_predict_pandas(features_df, MODEL_MOJO_ZIP_FILE_PATH, MODEL_GENMODEL_JAR_PATH)  # generate score
# features_df -> pandas DF

Детали H2o с момента запуска приложения

--------------------------  ----------------------------------------
H2O cluster uptime:         01 secs
H2O cluster timezone:       Etc/UTC
H2O data parsing timezone:  UTC
H2O cluster version:        3.20.0.7
H2O cluster version age:    1 year, 7 months and 10 days !!!
H2O cluster name:           H2O_from_python_unknownUser_t8cqu9
H2O cluster total nodes:    1
H2O cluster free memory:    1.656 Gb
H2O cluster total cores:    4
H2O cluster allowed cores:  4
H2O cluster status:         accepting new members, healthy
H2O connection url:         http://localhost:54321
H2O connection proxy:
H2O internal security:      False
H2O API Extensions:         XGBoost, Algos, AutoML, Core V3, Core V4
--------------------------  ----------------------------------------

И H2o (работает как отдельная служба), и flask приложение работает на одном сервере (3 - 8 серверов под балансировщиком нагрузки).

Иногда использование памяти постоянно увеличивается и выдает Cannot allocate memory

при вычислении карт результатов. Тогда это автоматически улаживается после иногда. Система показателей запускается вместе с другими правилами (последовательный запуск) по запросу HTTP, но об ошибке сообщает только при вычислении карт показателей. Предполагая, что это требует больше памяти, как это связано с H2O. Трафик c выглядит одинаковым на протяжении всего этого цикла. Поэтому я надеюсь, что это не из-за высокого трафика c.

Согласно моему исследованию, некоторая память где-то висит и не высвобождается.

Я сделал следующее обходные пути для освобождения зависшей памяти и уменьшения воздействия

1 G C в h2o с python

https://aichamp.wordpress.com/2016/11/10/calling-h2o-garbage-collect-from-python

Python Управление памятью H2O

  • Не испытал положительного воздействия.

2 Запланированный перезапуск службы - изящная замена старых серверов новыми серверами.

  • Получил положительный эффект. 60-70% ошибок ушли.

Я хотел бы понять, что происходит внутри, и представить правильное исправление, а не обходной путь. Помощь будет высоко ценится.

Для вашей информации,

Я не пробовал

1 обновление кластера H2o до новой версии в качестве текущей версия слишком старая (1 год, 7 месяцев и 11 дней) - согласен с тем, что лучше использовать последнюю версию, но нет гарантии, что то же самое не повторится, и требуются дополнительные усилия с точки зрения проверки оценки, результата и т. д. c

2 Я не ограничил использование памяти H2o с помощью min_mem_size, так как не хочу, чтобы оценка системы показателей не удалась.

и

Я планирую

1 добавить профилировщик памяти, чтобы легко понять использование памяти каждой части / process, связанный с моим приложением

edit

2 отделяет h2o от приложения flask и размещает его на разных серверах для масштабирования это просто. - Тем не менее, такая же проблема возможна.

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

Спасибо

1 Ответ

0 голосов
/ 12 апреля 2020

Подход, который вы описываете, отличается от того, что я бы порекомендовал.

Для простоты (игнорирование нескольких серверов и балансировка нагрузки) я собираюсь нарисовать диаграмму архитектуры вашей установки следующим образом:

[Client HTTP program] -> [python flask app] -> [java scoring backend]

Эта высокоуровневая архитектура хороша, но вы пошли на реализацию части слоя оценки java, что, как я скажу, является самым сложным из возможных способов вместо намеченного.

Предполагаемый путь состоит в том, чтобы использовать только MOJO и облегченную среду исполнения MOJO. Один простой способ сделать это - заключить MOJO в очень простой минимальный веб-сервис.

Вот ссылки на javado c для MOJO:

и репозиторий github, демонстрирующий использование MOJO в простом Java контейнере сервлета:

Кроме того, вот более старое репозиторий github, которое может оказаться полезным, в котором используется POJO вместо MOJO. MOJO лучше. Используйте MOJO, а не POJO, но чтение документации в этом репо может оказаться полезным:

Обратите внимание, если вы если вы будете действовать таким образом, вы все равно сможете по отдельности масштабировать / балансировать нагрузку между службами [python flask app] и [java scoring backend], хотя я ожидаю, что java будет существенно быстрее, чем python, поэтому может быть проще просто масштабировать python и java в группы по два, и python делать запросы к локальному java.


Хорошо, теперь, когда я говорил о методе наилучшей практики, позвольте мне указать на некоторые проблемы, которые я могу заметить в том, что вы делаете сейчас (трудный путь).

  1. Вы не сделали не упоминайте, забиваете ли вы по одной строке за раз или выполняете пакетную оценку. Использование самого сервера H2O-3 для скоринга намного лучше подходит для пакетного скоринга и ужасно неэффективно для подсчета по одной строке за раз. Процесс синтаксического анализа является тяжелым, а процесс оценки - тяжелым для одной строки за раз. Это повлияет на задержку.

  2. Хотя вы можете считывать в самом объекте MOJO полный серверный процесс H2O-3 и использовать его для пакетного скоринга, делая это в реальном HTTP-процессе в реальном времени. никогда не был намерением. (Интересно, что поддержка для этого не была возможна даже в течение первых 5 лет существования H2O-3.)

  3. Определенно есть утечки памяти, если вы не очистите после самостоятельно.

    Запуск процесса сервера H2O-3 в качестве долгосрочной службы для скоринга не рекомендуется. Но если вы действительно хотите это сделать, выполните следующие действия:

    • Объекты в памяти необходимо очистить. Вы можете найти их с помощью h2o.ls () и удалить их с помощью вызовов h2o.rm () в клиентских API R / python. Оба набора данных и оценки должны быть очищены. Вы, вероятно, не хотите удалять саму модель.

    • Я не ожидаю, что вам нужно вручную запускать сборку мусора в процессе Java, но вы можете, если вы хочу. Лично я делаю это только тогда, когда я включаю Java флаги, такие как -XX: + PrintGCDetails -XX: + PrintGCTimeStamps, чтобы я мог видеть эффект сжатия на том, сколько свободной памяти кучи остается после Full G C. Я делаю это, чтобы видеть, действительно ли объекты сохраняются, и я могу подтвердить, что они очищаются. Мне нравится отдавать эти журналы на http://gceasy.io и визуализировать их.

    • Контролировать журналы, чтобы увидеть свободную кучу, оставшуюся после полной G C.

    • Даже если вы делаете правильные вещи с точки зрения очистки памяти, дайте серверу H2O-3 обрабатывать много памяти. Я бы даже не запустил его на своем ноутбуке с меньшим -Xmx, чем 5G. Таким образом, я бы охарактеризовал кучу Java оригинального плаката как крайне недостаточно обеспеченную (H2O cluster free memory: 1.656 Gb).

    • Если после того, как Full G C набирает обороты, остается свободная куча, перезапустите процесс Java, поскольку это не стандартный вариант использования и не то, что тщательно проверяется. Кластеры H2O-3 рассматриваются группой разработчиков как сервисы с коротким и средним сроком службы (часы / дни), чем сервисы длительного действия (месяцы +, например, nginx / apache).


Надеюсь, это поможет!

...