[Daily Fresh Mushroom] Введение в параметры JVM и некоторые предложения

Микросервисы
[Daily Fresh Mushroom] Введение в параметры JVM и некоторые предложения

Вообще говоря, каждая компания имеет стандартизированные параметры для JVM и даже сформировала некоторые конфигурации по умолчанию на уровне компании.Если вы столкнетесь с проблемами производительности (более специальные сценарии использования), вы будете учитывать уровень кода, уровень JVM и даже уровень сервера Linux. оптимизировать.

настройки кучи

-Xms: начальный размер кучи

-Xmx: максимальный размер кучи

-XX:NewSize=n: установить размер молодого поколения

-XX:NewRatio=n: установить соотношение молодого поколения к старому. Если n=3, то это означает, что соотношение молодого поколения к старому составляет 1:3, а молодое поколение составляет 1/4 от суммы всего молодого поколения и старого поколения.

-XX:SurvivorRatio=n: отношение площади Эдема к двум областям выживших в молодом поколении. Обратите внимание, что в области выживших их два. Если n=3, то это означает, что Эдем: Выживший=3:2, область Выживших занимает 1/5 всего молодого поколения

-XX:MaxPermSize=n: установить размер постоянного поколения

Настройки коллектора

-XX:+UseSerialGC: установить серийный сборщик

-XX:+UseParallelGC: установить параллельный сборщик

-XX:+UseParalledlOldGC: Установить параллельный коллектор старого поколения

-XX:+UseConcMarkSweepGC: Установить параллельный сборщик

Статистика сбора мусора

-XX:+PrintGC

-XX:+PrintGCDetails

-XX:+PrintGCTimeStamps

-Xloggc:filename

Настройки параллельного коллектора

-XX:ParallelGCThreads=n: установить количество процессоров, используемых параллельным сборщиком для сбора. Количество параллельных потоков сбора.

-XX:MaxGCPauseMillis=n: установить максимальное время паузы для параллельного сбора

-XX:GCTimeRatio=n: установить процентное соотношение времени сборки мусора к времени выполнения программы. Формула: 1/(1+n) настройки параллельного коллектора

-XX:+CMSIncrementalMode: установить инкрементный режим. Подходит для ситуации с одним процессором.

-XX:ParallelGCThreads=n: установить количество ЦП, используемых, когда режим сбора данных молодого поколения параллельного сборщика — параллельный сбор. Количество параллельных потоков сбора.

Стратегия настройки

Настройка молодого поколения

  • Приложения с приоритетом времени отклика:Установите его как можно большим, пока он не будет близок к минимальному пределу времени отклика системы.(Выберите в соответствии с реальной ситуацией). При этом частота сборов молодого поколения также минимальна. В то же время уменьшите объекты, которые достигают старого поколения.
  • Приложения с приоритетом пропускной способности: установите как можно больше, возможно, достигнув уровня Гбит. Поскольку время отклика не требуется, сборка мусора может выполняться параллельно, что обычно подходит для приложений с более чем 8 ЦП.

Настройки старого поколения

  • Приоритетные приложения времени отклика: старое поколение использует одновременно сопутствующие коллекторы, поэтому его размер необходимо тщательно устанавливать, а некоторые параметры, такие как и т. Д. Если настройка кучи невелика, она может привести к фрагментации памяти, высокую частоту сбора и приложение для приложения и использовать традиционный метод Mark-and-Show; если куча большая, она займет много времени, чтобы собрать. Оптимальное решение обычно необходимо сократить время, проведенное в молодого поколения, и старое поколение, которое обычно повышает эффективность применения
    • Одновременная информация о мусоре
    • Параллельное время сбора постоянной генерации
    • Информация об устаревшем ГХ
    • Соотношение времени, затрачиваемого на молодые и старые коллекции
  • Приложения, ориентированные на пропускную способность: как правило, приложения, ориентированные на пропускную способность, имеют большое молодое поколение и небольшое старое поколение. Причина в том, что большинство краткосрочных объектов можно максимально переработать, сократив среднесрочные объекты, а старое поколение может хранить долгоживущие объекты.

Проблемы фрагментации, вызванные меньшими кучами

  • XX:+UseCMSCompactAtFullCollection: при использовании параллельного сборщика включите сжатие старого поколения.

  • XX:CMSFullGCsBeforeCompaction=0: когда приведенная выше конфигурация включена, сколько раз задается полный сборщик мусора для сжатия старого поколения.

официальное руководство

  • -Xms180m -Xmx180m Размер кучи: установить в 3-4 раза больше выживших объектов в старом поколении, то есть в 3-4 раза больше памяти, занимаемой старым поколением после FullGC.

  • -XX:MetaspaceSize=64M -XX:MaxMetaspaceSize=64M Metaspace: установить в 1,2-1,5 раза больше, чем объекты, пережившие старость.

  • -Xmn64m молодое поколение: установлено в 1-1,5 раза больше выживших объектов в старом поколении

  • Старость: Установите в 2-3 раза больше объектов, доживших до старости.

    Пример

  jstat -gc pid
  ###
   S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
  13824.0 22528.0 13377.0  0.0   548864.0 535257.2  113152.0   46189.3   73984.0 71119.8 9728.0 9196.2     14    0.259   3      0.287    0.546

OU указывает на то, что память, занятая старым возрастом, составляет 47189,3 К (около 47М), тогда соответствующие параметры конфигурации jvm следует изменить следующим образом

-XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=128M -Xms256m -Xmx256m

Рекомендации по производственной конфигурации

Рекомендации по параметрам JVM для критических систем

  1. Отменить предвзятую блокировку: -XX:-UseBiasedLocking

  2. Увеличить целочисленный кэш: -XX:AutoBoxCacheMax=20000

  3. Доступ и нулевые страницы памяти при запуске: -XX:+AlwaysPreTouch

  4. Ускорение генерации SecureRandom: -Djava.security.egd=file:/dev/./urandom

дополнительные параметры производительности

  1. -XX:+PerfDisableSharedMem Оказывается, JVM часто молча записывает немного статистических данных в каталог */tmp/hperf*.Если PageCache сбрасывается и файл блокируется, он не может закончить точку безопасности Stop мир.
  2. -XX:-UseCounterDecay Отключить затухание счетчика вызовов JIT. По умолчанию счетчик вызовов будет уменьшаться вдвое каждый раз, когда происходит сборка мусора, в результате чего некоторые методы всегда остаются «теплыми» и никогда не достигают порога в 10 000 раз для запуска компиляции C2.
  3. -XX:-TieredCompilation Многослойная компиляция — это гордая функция, которая включена по умолчанию после JDK8.Он статически компилируется сначала с C1, а затем компилируется с C2 после достаточной выборки. Но на самом деле мы измерили, что производительность в конце концов немного снизилась на 2%, что может быть связано с тем, что некоторые методы C1 больше не компилируются после компиляции C1. Есть также более случайные тайм-ауты службы при запуске приложения, вероятно, занятые компиляцией. Поэтому мы запретили его, но не забудьте включить предыдущий -XX:-UseCounterDecay, чтобы избежать некоторых теплых методов, которые всегда будут интерпретироваться и выполняться.

ГК стратегия

Ради стабильности куча ниже 8G по-прежнему является CMS.Хотя G1 сейчас по умолчанию, его производительность в малой куче не лучше, чем у CMS.Это все еще ZGC JDK11, который вызывает ожидания.

-XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly

Сборщик мусора с первой пропускной способностью

-XX:+UseParallelGC

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

-XX:MaxTenuringThreshold=2

Это самый очевидный параметр для изменения. Максимальное количество раз, когда объект пережил молодой GC в области Survivor и был переведен в старое поколение.Значение CMS по умолчанию в JDK8 равно 6, а в других, таких как G1, равно 15.

Young GC является крупнейшим источником пауз приложения, а количество уцелевших объектов после YGC напрямую влияет на время паузы, поэтому, если вы знаете частоту выполнения Young GC и самый длинный жизненный цикл большинства временных объектов в приложении, вы можете установите для него более высокое значение. Короче говоря, пусть объекты молодого поколения, которые на самом деле не являются временными объектами, быстро продвигаются к старому поколению, не остаются.

использовать-XX:+PrintTenuringDistributionОбратите внимание, если размер следующих поколений всегда одинаков, что доказывает, что объекты после определенного возраста всегда можно повысить до старого поколения, порог продвижения можно установить небольшим, например, 2 в JMeter достаточно.

-XX:+ExplicitGCInvokesConcurrent, но не добавляйте -XX:+DisableExplicitGC

Пусть алгоритм CMS используется в полном gc, а не на паузе всего процесса, это требуется.

Но, как сказал R, System GC — это защитный механизм (например, очистка его ссылочных объектов в куче, когда память вне кучи заполнена). повод для тюнинга, поэтому параметры этой плохой улицы не должны быть добавлены.

Конфигурация мониторинга

1. -XX:+PrintCommandLineFlags

Эксплуатация и техническое обслуживание иногда вносят некоторые временные изменения в параметры запуска и выводят параметры каждого запуска на стандартный вывод, что может быть задокументировано в будущем. Выводятся параметры, установленные в командной строке, и параметры, на которые эти параметры неявно влияют, например, после открытия CMS,-XX:+UseParNewGCтакже автоматически открывается.

2. -XX:-OmitStackTraceInFastThrow

Настройка StackTrace для исключений — дорогостоящая операция, поэтому, когда приложение выдает одно и то же исключение N раз (20 000?) в одном и том же месте, JVM оптимизирует некоторые специфические исключения, такие как NPE, выход за пределы массива и т. д., и больше не принести стек исключений. На этом этапе вы можете увидеть запись в журналеNul Point Exception, а логи, выдающие полный стек, скатились в никуда, поэтому я понятия не имею, где произошел NPE, и хочется плакать без слез. Итак, запретите, ElasticSearch делает то же самое.

файл сбоя

1. -XX:ErrorFile

Когда JVM дает сбой, точка доступа генерирует файл ошибки, в котором содержится подробная информация о состоянии JVM. Как и прежде, выводите его в фиксированный каталог, чтобы не искать этот файл повсюду. %p в имени файла будет автоматически заменен PID приложения.

-XX:ErrorFile=/var/log/hs_err_pid<pid>.log

2. coredump

Конечно, лучше сгенерировать coredump.Из CoreDump можно извлечь Heap Dump, Thread Dump и места краха, что очень практично.

добавить в сценарий запускаulimit -c unlimitedИли другие методы настройки, если у вас есть права root, лучше установить выходной каталог

echo "/{MYLOGDIR}/coredump.%p" > /proc/sys/kernel/core_pattern

Какие? Вы не знаете, для чего нужен coredump? Похоже, вы счастливый человек, который не сталкивался с JVM Segment Fault.

3. -XX:+HeapDumpOnOutOfMemoryError(необязательно)

В Out Of Memory, когда JVM вот-вот умрет, выведите дамп кучи в указанный файл. В противном случае разработчики часто не знают, как воспроизвести ошибку.

Путь указывает только на каталог, и JVM сохранит уникальное имя файла, называемое java_pid${pid}.hprof. Потому что, если он указывает на файл, а файл уже существует, его нельзя записать.

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${LOGDIR}/

Однако в контейнерной среде вывод 4G HeapDump приведет к тому, что операция ввода-вывода на жестком диске будет заполнена более чем на 20 секунд на общем жестком диске. Это также полный злой сосед и влияет на все остальные контейнеры на том же хосте.