Перейти к основному содержимому

Введение в кэш кода JVM

· 3 мин. чтения

1. Введение

В этом руководстве мы кратко рассмотрим и узнаем о кэш-памяти кода JVM .

2. Что такое кэш кода?

Проще говоря, JVM Code Cache — это область, где JVM хранит свой байт-код, скомпилированный в собственный код . Мы называем каждый блок исполняемого нативного кода nmethod . Метод n может быть полным или встроенным методом Java.

Компилятор «точно в срок» (JIT) является крупнейшим потребителем области кэша кода. Вот почему некоторые разработчики называют эту память кэшем JIT-кода.

3. Настройка кэша кода

Кэш кода имеет фиксированный размер . После заполнения JVM не будет компилировать дополнительный код, так как JIT-компилятор отключен. Кроме того, мы получим предупреждающее сообщение «CodeCache заполнен… Компилятор отключен ». В результате мы получим снижение производительности нашего приложения. Чтобы избежать этого, мы можем настроить кеш кода со следующими параметрами размера:

  • InitialCodeCacheSize — начальный размер кеша кода, по умолчанию 160 КБ.
  • ReservedCodeCacheSize — максимальный размер по умолчанию — 48 МБ.
  • CodeCacheExpansionSize — размер расширения кэша кода, 32 КБ или 64 КБ.

Решением может быть увеличение ReservedCodeCacheSize , но обычно это лишь временный обходной путь.

К счастью, JVM предлагает опцию UseCodeCacheFlushing для управления очисткой области кэша кода . Его значение по умолчанию равно false. Когда мы включаем его, он освобождает занятую область при соблюдении следующих условий:

  • кэш кода заполнен; эта область очищается, если ее размер превышает определенный порог
  • пройден определенный интервал с момента последней очистки
  • предварительно скомпилированный код недостаточно горяч. Для каждого скомпилированного метода JVM отслеживает специальный счетчик активности. Если значение этого счетчика меньше вычисленного порога, JVM освобождает этот фрагмент предварительно скомпилированного кода.

4. Использование кэша кода

Чтобы отслеживать использование кеша кода, нам нужно отслеживать размер используемой в данный момент памяти.

Чтобы получить информацию об использовании кеша кода, мы можем указать опцию –XX:+PrintCodeCache JVM . После запуска нашего приложения мы увидим аналогичный вывод:

CodeCache: size=32768Kb used=542Kb max_used=542Kb free=32226Kb

Давайте посмотрим, что означает каждое из этих значений:

  • size в выводе показывает максимальный размер памяти, который идентичен ReservedCodeCacheSize
  • used - это фактический размер памяти, которая в настоящее время используется
  • max_used — максимальный размер, который использовался
  • свободна оставшаяся память, которая еще не занята

Опция PrintCodeCache очень полезна, так как мы можем:

  • посмотреть, когда произойдет промывка
  • определить, достигли ли мы критической точки использования памяти

5. Сегментированный кеш кода

Начиная с Java 9 , JVM делит кэш кода на три отдельных сегмента, каждый из которых содержит определенный тип скомпилированного кода . Чтобы быть более конкретным, есть три сегмента:

  • Сегмент, не относящийся к методу, содержит внутренний связанный код JVM, такой как интерпретатор байт-кода. По умолчанию этот сегмент составляет около 5 МБ. Кроме того, можно настроить размер сегмента с помощью флага настройки -XX:NonNMethodCodeHeapSize.
  • Сегмент профилированного кода содержит слегка оптимизированный код с потенциально коротким временем жизни. Несмотря на то, что размер сегмента по умолчанию составляет около 122 МБ, мы можем изменить его с помощью флага настройки -XX:ProfiledCodeHeapSize.
  • Непрофилированный сегмент содержит полностью оптимизированный код с потенциально длительным временем жизни. Точно так же по умолчанию он составляет около 122 МБ. Это значение, конечно, настраивается с помощью флага настройки -XX:NonProfiledCodeHeapSize.

Эта новая структура по-разному обрабатывает различные типы скомпилированного кода, что приводит к повышению общей производительности.

Например, отделение короткоживущего скомпилированного кода от долгоживущего кода повышает производительность метода очистки — в основном потому, что ему нужно сканировать меньшую область памяти.

6. Заключение

В этой быстрой статье представлено краткое введение в кэш кода JVM.

Кроме того, мы представили некоторые варианты использования и настройки для мониторинга и диагностики этой области памяти.