Интерпретация данных jemaloc возможной утечки из кучи - PullRequest
0 голосов
/ 02 декабря 2018

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

Я работаю на Ubuntu 16.04, используя oracle java 8, так как openjdk 8 не имел символов отладки, которые мне нужны, чтобы jemaloc предоставляла правильные данные

-XX:NativeMemoryTracking=detail -XX:+UseG1GC -XX:+UseStringDeduplication -Xms64m -Xmx256m -XX:MaxMetaspaceSize=128m -Xss256k

Как вы можете видеть мой Xmxустановлен на 256м.Однако top в настоящее время показывает, что мой процесс находится на уровне 1.1G

. После использования JProfiler и JVisualVm I и многих других вещей, которые я смог найти в Google, я пришел к выводу, что это должно быть проблема вне кучи.

После долгих поисков я наткнулся на jemaloc, и статьи, которые я прочитал об этом, показались многообещающими.Но у меня возникли проблемы с интерпретацией этих данных.И выяснить, как точно указать источник моей проблемы.

максимальное использование памяти

граф jemaloc

Данные отслеживания собственной памяти

Native Memory Tracking:

Total: reserved=1678MB, committed=498MB
-                 Java Heap (reserved=256MB, committed=256MB)
                            (mmap: reserved=256MB, committed=256MB)

-                     Class (reserved=1103MB, committed=89MB)
                            (classes #14604)
                            (malloc=3MB #32346)
                            (mmap: reserved=1100MB, committed=85MB)

-                    Thread (reserved=26MB, committed=26MB)
                            (thread #53)
                            (stack: reserved=26MB, committed=26MB)

-                      Code (reserved=261MB, committed=96MB)
                            (malloc=17MB #17740)
                            (mmap: reserved=244MB, committed=79MB)

-                        GC (reserved=1MB, committed=1MB)
                            (mmap: reserved=1MB, committed=1MB)

-                  Internal (reserved=6MB, committed=6MB)
                            (malloc=6MB #48332)

-                    Symbol (reserved=19MB, committed=19MB)
                            (malloc=16MB #168491)
                            (arena=4MB #1)

-    Native Memory Tracking (reserved=5MB, committed=5MB)
                            (tracking overhead=4MB)

1 Ответ

0 голосов
/ 03 декабря 2018

Проверка карты памяти процесса

Собственное отслеживание памяти учитывает только структуры виртуальной машины Java, но не учитывает отображенные в памяти файлы и собственную память, выделенную общими библиотеками (включая собственный код библиотеки классов Java),Кроме того, NMT не отслеживает какую-либо внутреннюю фрагментацию malloc - стандартного распределителя libc.

Во-первых, чтобы проанализировать использование Java-процесса вне кучи, рассмотрим его полную карту памяти:

pmap -X <pid>

Это позволит пролить свет на то, используется ли память сопоставленными файлами или анонимными областями.

Изменение стандартного распределителя

Если вы видите количество анонимных областей, кратное 64 МБ, это может быть признаком малокен арена.Известно, что libc malloc имеет проблемы с чрезмерным использованием виртуальной памяти в некоторых системах.Использование jemalloc или tcmalloc в качестве замены для замены (даже без функции профилирования) может стать решением в этом случае.

Собственные распределения профилей

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

Async-profiler позволяет отслеживать собственные распределенияв контексте Java.Выполнить

./profiler.sh -d <duration> -e malloc -f malloc.svg <pid>

Это приведет к появлению Графика пламени из malloc вызовов, например:

Malloc Flame Graph

Это всего лишь пример, демонстрирующий, как java.util.zip.GZIPOutputStream может быть источником встроенной памяти.Конечно, ваш случай будет другим.

Обратите внимание , что malloc сами вызовы не означают утечку памяти.Например, память может быть выделена, а затем освобождена вскоре после этого.График - это просто подсказка, где искать.

Чтобы найти места, где RSS увеличивается, вы можете отслеживать mprotect или mmap звонки.Это можно сделать с помощью async-profiler аналогичным образом:

./profiler.sh -d <duration> -e mprotect -f mprotect.svg <pid>
./profiler.sh -d <duration> -e mmap -f mmap.svg <pid>

Обратите внимание на библиотеки агентов

Я заметил функции cbClassPrepare и classTrack_processUnloads в вашем графе jemalloc.Это означает, что вы используете jdwp агент отладки.Это определенно может быть причиной чрезмерного выделения памяти - раньше я видел утечки памяти в jdwp.Любая другая библиотека агентов, включенная с помощью опций -agentlib, -agentpath или -javaagent, также является подозрительной, поскольку ее собственное использование памяти не отслеживается JVM.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...