Статьи

Java VM — Остерегайтесь пространства YoungGen

Как вы могли видеть из наших предыдущих статей , ориентированных на производительность, исправная JVM является одной из наиболее важных целей для достижения оптимальной производительности и стабильности приложений. Такая оценка здоровья очень часто фокусируется только на частоте (избегании) крупных коллекций или обнаружении утечек памяти . Как насчет размеров и площади пространства молодого поколения или недолговечных объектов? JVM_beware_YG

Эта статья основана на реальной истории и недавнем опыте устранения неполадок, который мы имели с одним из наших ИТ-клиентов. На примере приложения будет продемонстрировано, что чрезмерный объем памяти и частота второстепенных сборов могут вызвать проблемы с производительностью, столь же серьезные, как у его старшего брата, Старого поколения или постоянного пространства.

Диагностика здоровья JVM

Если вы новичок в мире тюнинга JVM, вы скоро поймете, что не существует универсальных решений, применимых для всех приложений. Независимо от высококачественного материала, который вы можете найти в Интернете из различных источников, вам все равно нужно проявить должную осмотрительность и правильно понять тип приложения, с которым вы имеете дело, включая его чувствительность к паузах JVM GC (для некоторых приложений требуется очень время паузы с низкой JVM <1%).

Профилирование Java (включая обнаружение утечек памяти) вместе с тестированием производительности и нагрузки являются хорошими примерами дополнительной работы, которую вам нужно будет выполнить, чтобы собрать все надлежащие данные и факты об объеме памяти вашего приложения и работоспособности JVM.

При этом, что мы подразумеваем под «здоровой» JVM? Пожалуйста, ответьте на следующие вопросы, насколько вам известно.

** Если вы ответите НЕТ, примите уровень достоверности 90% +, в противном случае ответьте, Я НЕ ЗНАЮ.

  • Ваша куча Java или пространство OldGen протекают со временем (после крупных коллекций)?
  • В настоящее время на вашем приложении влияют большие и / или частые паузы JVM GC?
  • Является ли у вас общее время паузы в JVM выше 5% или выше установленного идеального базового уровня?
  • Влияет ли на время отклика вашего приложения активность GV JVM на регулярной основе и выходит за пределы допуска приложения?
  • Вы наблюдали за последние 3 месяца появления ошибок java.lang.OutOfMemoryError ?
  • Вы наблюдали за последние 3 месяца сбоев JVM (внезапный сбой JVM с дампом ядра и отчетом о сбое)?
  • Верите ли вы, что ваша JVM в настоящее время нестабильна и / или требует слишком большого вмешательства человека (регулярный перезапуск и т. Д.)?

Если вы ответили ДА или я НЕ ЗНАЮ на какой-либо из них, это означает, что вам или вашей команде по настройке производительности производства необходимо проделать определенную работу, включая обзор текущей политики GV JVM.

Если вы ответили «НЕТ» всем тем, у кого есть высокий уровень доверия, это означает, что вы, вероятно, достигли надежного приложения и стабильности JVM, поздравляю. Я по-прежнему рекомендую переоценить ситуацию между основными выпусками и прогнозами инкрементальной нагрузки.

Молодое поколение: Остановить мир, правда?

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

HotSpot_Heap_Structure

Одно распространенное заблуждение, которое я видел за последние несколько лет, заключается в том, что YoungGen или второстепенные коллекции полностью прозрачны и не влияют на время отклика приложения. Это утверждение может быть почти верным, если размер кучи Java небольшой (пространство YG <1 ГБ) и имеет дело с умеренным объемом недолговечных объектов или скоростью выделения. В этом сценарии, если второстепенные коллекции выполняются очень быстро (<20 мс) и не слишком часто (каждые 30 секунд +), общее время паузы JVM, вносимое пространством YoungGen, останется небольшим (<< 1%). Тем не менее, ситуация может измениться очень быстро, если скорость выделения памяти YG увеличивается (увеличение занимаемой площади на запрос, увеличение трафика и т. Д.).

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

# Oracle HotSpot в основном параллельные коллекторы: CMS vs. G1

# Oracle HotSpot незначительные коллекции исчерпывающий охват

Независимо от политики HotCpot GC, которую вы используете, включая в основном одновременные коллекторы, такие как CMS или G1, коллекция пространства YoungGen остается событием «остановить мир». Насколько нам известно, Azul Zing C4 является единственным сборщиком JVM, объявленным истинно непрерывным уплотняющим коллектором. У нас не было возможности поэкспериментировать с этим коллектором на данный момент. Я приветствую всех, у кого есть опыт настройки C4, чтобы поделиться своими наблюдениями, особенно фактическими цифрами и в основном параллельными коллекционерами, такими как G1.

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

Пример приложения

Чтобы сравнить% времени отклика и паузы JVM между различными уровнями распределения YG, мы создали пример приложения в соответствии с приведенными ниже спецификациями:

  • Веб-служба JAX-RS (REST) ​​была создана и представлена ​​через URI jvm в соответствии с приведенными ниже атрибутами.
1
2
3
4
@GET
   @Path("/jvm")
   @Produces(MediaType.APPLICATION_JSON)
   public Integer jvm() {}

Каждый вызов jvm выполняет следующую логику:

1. Выделите заранее определенный размер недолговечных объектов (подходящих для быстрого YG GC).

Кроме того, начальный объем памяти в 1 ГБ долгоживущих объектов (не подходящих для GC) выделяется во время загрузки класса, чтобы создать некоторый шум для коллектора CMS.

Распределение памяти недолговечных объектов YG и статическое сохранение OldGen было просто достигнуто за счет создания статического массива примитивных байтовых значений согласно приведенному ниже фрагменту кода. Истинный объем памяти можно наблюдать согласно анализу дампа кучи JVM с использованием MAT .

01
02
03
04
05
06
07
08
09
10
private final static int LONG_LIVED_OBJ_FOOTPRINT = (1024 * 1024 * 1024);
private final static int SHORT_LIVED_OBJ_FOOTPRINT = (100 * 1024 * 1024);
 
// 1 GB static memory footprint
private final static byte byteArrayLongLivedObj[] = new byte[LONG_LIVED_OBJ_FOOTPRINT];
 
// 100 MB memory allocation (waste) created per execution
public void generateShortLivedObj(String objId) {         
  byte byteArrayShortLivedObj[] = new byte[SHORT_LIVED_OBJ_FOOTPRINT];
}

OldGen_1GB_retention

Наконец, найдите ниже спецификации среды и программное обеспечение, используемое для создания, выполнения и мониторинга этого теста производительности сравнения YG.

  • ОС: Windows 7 @ 64-битная
  • Контейнер Java EE: WildFly 8 Beta1
  • JVM: Oracle HotSpot 1.7 @ 64-разрядная с размером кучи Java 5 ГБ (пространство YG: 1152 МБ XX: NewRatio = 3). GC коллектор: CMS
  • IDE: JBoss Developer Studio 7.0.0.GA
  • Мониторинг JVM: JVisualVM
  • Анализатор утечек памяти JVM: Plumbr 3.0
  • JVM подробный: gc log анализатор: GCMV
  • Тестирование производительности и нагрузки: Apache JMeter 2.9

Результаты тестирования производительности и наблюдения

Следующее тестирование производительности имитировало реальное приложение, которое имело дело с большим временем паузы JVM и серьезным ухудшением при пиковой нагрузке. Было выполнено 3 прогона, один для базового уровня, и 2 прогона после имитации улучшений (сокращения) объема памяти приложения для каждого запроса.

базисный

  • 10 одновременных потоков
  • 100 МБ недолговечных объектов, созданных за исполнение на процесс JVM

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

Полученные результаты

  • Среднее время отклика: 140 мс
  • Пропускная способность: 68 рэк / сек
  • Общее время паузы JVM: 25,8%
  • Частота сбора YG: 7 сборов в секунду
  • Скорость GC: 308 909 МБ в минуту

JVM_beware_YG1

Согласно JVisualVM, это выглядит так, как будто JVM исправна (нет утечки памяти, стабильный и низкий OldGen и т. Д.). Однако, если вы углубитесь в подробные записи журнала gc, вы поймете, что общее время паузы JVM составляет 25,8%, и все из-за чрезмерной частоты сборов YG. Это убедительно доказывает, что нужно правильно анализировать подробные данные: журналы gc по сравнению только с фокусировкой на космических тенденциях JVM.

YG_Activity_1

JVM_beware_YG2

Тестирование и тюнинг # 1

  • 10 одновременных потоков
  • 50 МБ недолговечных объектов, созданных за исполнение на процесс JVM

Этот прогон имитирует первоначальное улучшение площади приложения и скорости выделения памяти со 100 МБ до 50 МБ на выделение. Мы можем ясно видеть улучшение всех показателей, особенно пропускной способности, просто уменьшая объем памяти приложения для каждого запроса.

Полученные результаты

  • Среднее время отклика: 119 мс -21
  • Пропускная способность: 79 запросов / сек +11
  • Общее время паузы JVM: 15,59% -10,21
  • Частота сбора YG: 3-4 коллекции в секунду -3
  • Скорость GC: 164 950 МБ в минуту -143 959

JVM_beware_YG4

JVM_beware_YG5

Тестирование и тюнинг №2

  • 10 одновременных потоков
  • 5 МБ недолговечных объектов, созданных за исполнение на процесс JVM

Этот прогон имитирует значительно уменьшенную площадь приложения и скорость выделения памяти со 100 МБ до всего 5 МБ на выделение.

Полученные результаты

  • Среднее время отклика: 107 мс -33
  • Пропускная способность: 90 рэк / сек +22
  • Общее время паузы JVM: 1,9% -23,9
  • Частота сбора YG: 1 сбор каждые 2-3 секунды * значительное снижение
  • Скорость GC: 15 841 МБ в минуту -293 068

JVM_beware_YG6

JVM_beware_YG7

Как видите, окончательное улучшение занимаемой площади приложения и выделения памяти значительно сократило время паузы JVM до более приемлемого уровня 1,9%. Важно отметить, что на протяжении этих трех тестов занимаемая площадь OldGen и активность CMS не оказывали существенного влияния на время паузы JVM, проблема с производительностью была связана с чрезмерной активностью и большим объемом событий остановки мира, связанных с YG. коллекции.

Решения и рекомендации

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

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

  • Горизонтальное и вертикальное масштабирование: разделение трафика с помощью увеличения числа процессов JVM за счет доступного оборудования, что снижает скорость выделения и частоту сборов YG. По сути, это означает бросить оборудование на проблему. Моя рекомендация всегда состоит в том, чтобы сначала точно настроить объем используемой памяти приложения, а затем параллельно изучить другие варианты масштабирования.
  • Настройка размера кучи Java и соотношения YG: увеличение размера пространства YG определенно поможет снизить частоту остановки мировых коллекций YG. Теперь, пожалуйста, будьте осторожны, чтобы не «голодать» пространство OldGen, иначе вы просто перенесете проблему с еще более серьезными последствиями, такими как перебои JVM и события OOM.

Заключительные слова

Я надеюсь, что вам понравилась эта статья, и теперь вы лучше понимаете потенциальное влияние на производительность избыточных коллекций JVM YG.

Я рекомендую вам сделать следующее упражнение после прочтения этой статьи:

  • Выберите одно из самых загруженных приложений.
  • Просмотрите подробный журнал: gc log и определите время паузы JVM с помощью GCMV.
  • Определите частоту и влияние коллекций YG и определите возможности настройки.

Я с нетерпением жду ваших комментариев и, пожалуйста, поделитесь своим опытом настройки JVM.

Ссылка: Java VM — Остерегайтесь пространства YoungGen от нашего партнера JCG Пьера Хьюга Шарбонно в блоге Шаблоны поддержки Java EE .