Подтвердить что ты не робот

Настройка производительности JVM для больших приложений

Параметры JVM по умолчанию не оптимальны для запуска больших приложений. Любое понимание людей, которые настроили его на реальном приложении, было бы полезно. Мы запускаем приложение на 32-битной машине Windows, где клиентская JVM используется по умолчанию. Мы добавили -сервер и изменили NewRatio на 1: 3 (большее молодое поколение).

Любые другие параметры/настройки, которые вы пробовали и нашли полезными?

[Обновление] Конкретный тип приложения, о котором я говорю, - это серверное приложение, которое редко отключается, занимая не менее -Xmx1024m. Также предположим, что приложение уже профилировано. Я ищу общие рекомендации с точки зрения производительности JVM.

4b9b3361

Ответ 1

Существует огромное количество этой информации.

Сначала профайлируйте код перед настройкой JVM.

Во-вторых, внимательно прочитайте документацию JVM; вокруг много "городских легенд". Например, флаг -server помогает только в том случае, если JVM остается резидентом и работает некоторое время; -сервер "разворачивает" JIT/HotSpot, и для этого нужно пройти много проходов по тому же пути. -сервер, с другой стороны, замедляет первоначальное выполнение JVM, так как там больше времени установки.

Есть несколько хороших книг и веб-сайтов. См., Например, http://www.javaperformancetuning.com/

Ответ 2

Предисловие

Фон

В магазине Java. Проводились целые месяцы, посвященные проверке производительности на распределенных системах, причем основные приложения находятся на Java. Некоторые из них подразумевают продукты, разработанные и проданные самим Sun (затем Oracle).

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

В мире Java быстро меняются вещи, поэтому часть его может быть уже устаревшей с прошлого года, когда я это сделал. (Уже есть Java 10?)

Хорошая практика

Что вам ДОЛЖНО делать: бенчмарк, контрольный показатель, BENCHMARK!

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

Кроме того, вы должны контролировать JVM. Включить мониторинг. Хорошие приложения обычно предоставляют веб-страницу мониторинга и/или API. В противном случае существует общая инструментария Java (JVisualVM, JMX, hprof и некоторые флаги JVM).

Помните, что при настройке JVM обычно нет производительности. Это скорее "сбой или не сбой, нахождение точки перехода". Это о том, что, когда вы даете такое количество ресурсов вашему приложению, вы можете последовательно ожидать, что количество выступлений взамен. Знание - это сила.

Спектакли в основном продиктованы вашим приложением. Если вы хотите быстрее, вам нужно написать лучший код.

Что вы будете делать большую часть времени: живите с надежными чувствительными значениями по умолчанию

У нас нет времени для оптимизации и настройки каждого отдельного приложения. Большую часть времени мы просто будем жить с разумными значениями по умолчанию.

Первое, что нужно сделать при настройке нового приложения, - это прочитать документацию. Большинство серьезных приложений поставляется с руководством по настройке производительности, включая рекомендации по настройкам JVM.

Затем вы можете настроить приложение: JAVA_OPTS: -server -Xms???g -Xmx???g

  • -server: включить полную оптимизацию (этот флаг на большинстве JVM в настоящее время).
  • -Xms -Xmx: установите минимальную и максимальную кучу (всегда одно и то же значение для обоих, что касается единственной оптимизации).

Хорошо, вы знаете обо всех параметрах оптимизации, которые нужно знать о JVM, поздравления! Это было просто: D

Что вы НЕ ДОЛЖНЫ делать, КОГДА-ЛИБО:

Пожалуйста, НЕ копируйте случайную строку, которую вы нашли в Интернете, особенно когда они принимают несколько строк:

-server  -Xms1g -Xmx1g  -XX:PermSize=1g -XX:MaxPermSize=256m  -Xmn256m -Xss64k  -XX:SurvivorRatio=30  -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled  -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=10  -XX:+ScavengeBeforeFullGC -XX:+CMSScavengeBeforeRemark  -XX:+PrintGCDateStamps -verbose:gc -XX:+PrintGCDetails -Dsun.net.inetaddr.ttl=5  -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=`date`.hprof   -Dcom.sun.management.jmxremote.port=5616 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -server -Xms2g -Xmx2g -XX:MaxPermSize=256m -XX:NewRatio=1 -XX:+UseConcMarkSweepGC

Например, эта вещь, найденная на первой странице google, проста. Существуют аргументы, указывающие кратность времени с конфликтующими значениями. Некоторые из них просто форсируют значения JVM по умолчанию (в конечном счете, значения по умолчанию из 2 версий JVM назад). Некоторые из них устарели и просто игнорируются. И, наконец, по крайней мере один параметр настолько недействителен, что он будет последовательно разбивать JVM при запуске им простое существование.

Фактическая настройка

Как выбрать размер памяти:

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

Важное примечание. Процесс java займет до максимальная куча PLUS 10%. Накладные расходы X% представляют собой управление кучей, не включенное в кучу.

Вся память, как правило, предварительно распределяется процессом при запуске. Вы можете увидеть процесс, используя максимальную кучу ВСЕ ВРЕМЯ. Это просто неправда. Вам нужно использовать инструменты мониторинга Java, чтобы увидеть, что действительно используется.

Поиск нужного размера:

  • Если он сбой с OutOfMemoryException, недостаточно памяти
  • Если он не сбой с OutOfMemoryException, это слишком много памяти
  • Если это слишком много памяти, но аппаратное обеспечение получило и/или уже оплачено, это идеальный номер, работа выполнена!

JVM6 - бронза, JVM7 - ​​золото, JVM8 - платина...

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

Для информационных целей. Это, по крайней мере, 4 доступных сборщика мусора в Oracle Java 7-8 (HotSpot) и OpenJDK 7-8. (Другие JVM могут быть совершенно разными, например, Android, IBM, встроенный):

  • SerialGC
  • ParallelGC
  • ConcurrentMarkSweepGC
  • G1GC
  • (плюс варианты и настройки)

[Начиная с Java 7 и далее. Код Oracle и OpenJDK частично разделены. GC должен быть (в основном) одинаковым на обеих платформах.]

JVM >= 7 имеют много оптимизаций и выбирают достойные значения по умолчанию. Он немного меняется по платформе. Он уравновешивает несколько вещей. Например, решение включить многоядерную оптимизацию или нет, имеет ли процессор несколько ядер. Вы должны позволить ему это сделать. Не меняйте или не меняйте настройки GC.

Хорошо, если компьютер примет решение для вас (для чего предназначены компьютеры). Лучше иметь настройки JVM на 95% -оптимальные все время, чем заставлять "всегда 8-ядерную агрессивную коллекцию для более низких времен паузы" на всех коробках, половина из которых в конце концов является t2.small.

Исключение. Когда приложение поставляется с руководством по производительности и конкретной настройкой. Это совершенно нормально оставить предоставленные настройки как есть.

Совет. Переход на новую JVM для улучшения последних улучшений может иногда обеспечить хороший прирост без особых усилий.

Специальный случай: -XX: + UseCompressedOops

JVM имеет специальную настройку, которая принудительно использует внутренний индекс 32 бит (чтение: указатели). Это позволяет адресовать 4 294 967 295 объектов * 8 байт адрес = > 32 ГБ памяти. (НЕ следует путать с адресным пространством 4 ГБ для REAL-указателей).

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

Пример реальной жизни. В документации ElasticSearch указано, что 32GB 32bits 326 бит node может быть эквивалентно 40-битным 64-битным node с точки зрения фактических данных, хранящихся в памяти.

Заметка об истории. Флаг был известен как неустойчивый в эпоху до java-7 (возможно, даже pre-java-6). Он работал отлично в новой JVM на некоторое время.

Улучшения производительности виртуальных машин Java HotSpot ™

[...] В Java SE 7 использование сжатых oops является стандартным для 64-разрядных процессов JVM, когда -Xmx не указан и для значений -Xmx меньше 32 гигабайт. Для JDK 6 перед выпуском 6u23 используйте флаг -XX: + UseCompressedOops с помощью команды java для включения этой функции.

См.: снова JVM горит впереди по ручной настройке. Тем не менее, интересно узнать об этом =)

Специальный случай: -XX: + UseNUMA

Неравномерный доступ к памяти (NUMA) - это компьютерная память, используемая при многопроцессорной обработке, время доступа к памяти зависит от местоположения памяти относительно процессора. Источник: Wikipedia

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

Совершенно очевидно, что доступ к данным в кэше L2 в текущем процессоре намного медленнее, чем для того, чтобы пройти весь путь к карте памяти из другого сокета.

Я считаю, что все продаваемые сегодня системы с несколькими сокетами являются NUMA по дизайну, тогда как все системы потребителей НЕ. Проверьте, поддерживает ли ваш сервер NUMA с помощью команды numactl --show в linux.

Флаг, поддерживающий NUMA, сообщает JVM оптимизировать распределения памяти для базовой аппаратной топологии.

Повышение производительности может быть значительным (например, две цифры: + XX%). Фактически, кто-то переключился с "NOT-NUMA 10CPU 100GB" на "NUMA 40CPU 400GB", возможно, [драматическая] потеря в исполнении, если он не знает о флагове.

Примечание. Обсуждаются обнаружение NUMA и автоматический флаг в JVM http://openjdk.java.net/jeps/163 p >

Бонус. Для этого нужно оптимизировать все приложения, предназначенные для работы на большом аппаратном уровне (т.е. NUMA). Это не относится к Java-приложениям.

К будущему: -XX: + UseG1GC

Последнее улучшение в Garbage Collection - это сборщик G1 (прочитайте: Garbage First).

Он предназначен для высоких ядер, систем с высокой памятью. При абсолютном минимуме 4 ядра + 6 ГБ памяти. Он ориентирован на базы данных и приложения с интенсивной памятью, используя в 10 раз больше и больше.

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

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

Не трогайте: размеры поколений (NewGen, PermGen...)

GC разбивает память на несколько секций. (Не вдаваясь в подробности, вы можете "Google GC Generations" Google.)

Последний раз, когда я проводил неделю, чтобы попробовать 20 различных комбинаций флагов поколений в приложении, принимающем 10000 хитов/с. Я получал великолепный импульс от -1% до +1%.

Генерации Java GC - интересная тема для чтения статей или написания. Они не могут настраиваться, если вы не являетесь частью 1%, которые могут посвятить значительное время ничтожному выигрышу среди 1% людей, которым действительно нужны оптимизации.

Заключение

Надеюсь, это может вам помочь. Получайте удовольствие от JVM.

Java - лучший язык и лучшая платформа в мире! Иди распространяй любовь: D

Ответ 3

Посмотрите здесь (или выполните поиск google для настройки hotspot) http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html

Вы определенно хотите профилировать свое приложение, прежде чем пытаться настроить vm. NetBeans имеет хороший профилировщик, встроенный в него, что позволит вам видеть всевозможные вещи.

Я когда-то рассказывал, что GC был нарушен для своего приложения - я посмотрел на код и обнаружил, что они никогда не закрывали какие-либо результаты своих запросов к базе данных, поэтому они сохраняли огромное количество байтовых массивов. Как только мы закрыли результаты, время прошло от 20 минут и ГБ памяти до 2 минут и очень небольшой объем памяти. Они смогли удалить параметры настройки JVM, и все было счастливо.

Ответ 4

Абсолютным лучшим способом ответить на этот вопрос является выполнение контролируемого тестирования в приложении в непосредственной близости от "производственной" среды, которую вы можете создать. Вполне возможно, что использование -сервера, разумного размера начальной кучи и относительно умного поведения последних JVM будет вести себя так же хорошо или лучше, чем подавляющее большинство настроек, которые обычно можно попробовать.

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

Ответ 5

Я предлагаю вам одновременно профилировать ваше приложение с помощью выборочного контроля процессора и мониторинга размещения объектов. Вы найдете очень разные результаты, которые могут быть полезны при настройке кода. Также попробуйте использовать встроенный профилировщик hprof, он также может дать очень разные результаты.

В общем профилировании ваше приложение имеет гораздо большую разницу, чем аргументы JVM.

Ответ 6

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

  • размеры памяти
  • выбор коллектора GC
  • параметры, связанные с коллекторами GC

Ответ 7

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

Я бы, вероятно, начинал с опции -verbose: gc JVM, чтобы посмотреть, как работает сбор мусора. Много раз, самое простое исправление, чтобы просто увеличить максимальный размер кучи с -Xmx. Если вы научитесь интерпретировать вывод -verbose: gc, он расскажет вам почти все, что вам нужно знать о настройке JVM в целом. Но делать это самостоятельно не будет волшебным образом, плохо настроенный код просто пойдет быстрее. Большинство параметров настройки JVM предназначены для повышения производительности сборщика мусора и/или объема памяти.

Для профилирования мне нравится yourkit.com