RythmEngine и TemplateClassManager - самые большие объекты кучи: проблемы с утечкой памяти
В моей компании мы используем Rythm благодаря своему объекту и простому использованию в проекте.
В нашем проекте мы отправляем несколько электронных писем (1000-2000 писем в день); шаблон электронной почты - это шаблон ритма с динамическим синтаксисом (код Java). Производительность кажется прекрасной, и она прошла тесты интеграции.
Тем не менее, мы экспериментировали с несколькими проблемами памяти, которые приводят к утечке памяти через 3-4 дня. Профилирование, мы заметили, что Rythm - самый большой объект кучи (наши профилирования составляют около 1 дня) даже больше, чем ClassLoader или BeanFactory от Spring.
Используя анализатор инструментов кучи, мы заметили, что RythmEngine и TemplateClassManager являются самыми большими объектами
(Instance) - (retained size bytes)
org.rythmengine.RythmEngine#1 - 10,192,894
org.rythmengine.internal.compiler.TemplateClassManager#1 - 9,223,065
org.springframework.boot.loader.LaunchedURLClassLoader#1 - 6,975,661
java.util.Vector#89 - 6,378,290
java.lang.Object[]#7549 - 6,378,254
org.springframework.beans.factory.support.DefaultListableBeanFactory#1 - 3,741,643
......
Из инструментов анализа кучи мы видим, что эти объекты являются большими, и кажется, что они увеличиваются во время.
![введите описание изображения здесь]()
И GC Root.
![введите описание изображения здесь]()
Что касается пулов памяти: Par Eden кажется прекрасным, и CMS Old Generation, кажется, не увеличивается или, по крайней мере, медленно (даже после некоторых крупных GC, кажется, что свободная память). Память кучи кажется прекрасной (тесты и профилирование составляют около одного дня), но в производстве медленно возрастает после достижения максимальной кучи.
Мы спрашиваем, кто-то экспериментировал с этой функцией (используя ритм, а через несколько дней обнаруживает утечку памяти) или просто дайте некоторые рекомендации по повышению производительности с ритмом в производственной среде. Или любая идея о том, как бороться с утечкой памяти глубины, будет приветствоваться.
ВАЖНОЕ ЗАМЕЧАНИЕ [30-09-2015]: Мы изменили с Rythm на FreeMarker в качестве механизма шаблонов, и кажется (как наши системы мониторинга), что память более стабильна и составляет около 20% от максимальной памяти (-Xmx1024). Мы расскажем более подробно на этой неделе. Но, похоже, что у Rythm могут быть проблемы с памятью, которые через пару дней приводят к утечке памяти.
ВАЖНОЕ ПРИМЕЧАНИЕ [06-10-2015]: после нескольких дней интенсивного мониторинга мы проверили, что память стабильна с использованием FreeMarker в качестве механизма шаблонов. Мы удалили все зависимости Rythm в нашем продукте, потому что, поскольку наши исследования показывают , у него есть потенциальная проблема с утечкой памяти, которая не решена, которая через несколько дней движется к OOME для кучи ( в нашем случае два дня). Проблема закрыта.
Ответы
Ответ 1
Мы столкнулись и столкнулись с такой проблемой, но ее из-за компиляции шаблонов снова и снова. Чтобы этого избежать, мы выполнили следующие настройки:
Включить режим работы
Включить кэширование шаблонов
Задайте скомпилированное расположение каталога шаблона - для хранения скомпилированной версии файлов шаблонов. (Не путайте с конфигурацией каталога шаблонов), что повысит скорость вашего приложения.
Map<String, Object> rythmConfigs = new HashMap<>();
//rythmConfigs.put(ENGINE_MODE, this.appMode ? "prod" : "dev");
rythmConfigs.put(PRECOMPILE_MODE_ENABLED, this.config.getBoolean(PRECOMPILE_MODE_ENABLED, true));
rythmConfigs.put(LOAD_PRECOMPILED_ENABLED, this.config.getBoolean(LOAD_PRECOMPILED_ENABLED, true));
rythmConfigs.put("rythm.default.cache_ttl", Integer.MAX_VALUE);
rythmConfigs.put("rythm.cache.enable", this.appMode);
//rythmConfigs.put("cache.prod_only.enabled", this.appMode);
rythmConfigs.put(PRECOMPILED_DIR, getTempDir(config.getString(XoAppConfigKeys.APPLICATION_CONTEXT)).getAbsolutePath());
rythmConfigs.put(TEMPLATE_DIR, this.templateFolderUri.getPath());
rythmEngine = new RythmEngine(rythmConfigs);