Параметры JVM по умолчанию не оптимальны для запуска больших приложений. Любое понимание людей, которые настроили его на реальном приложении, было бы полезно. Мы запускаем приложение на 32-битной машине Windows, где клиентская JVM используется по умолчанию. Мы добавили -сервер и изменили NewRatio на 1: 3 (большее молодое поколение).
[Обновление] Конкретный тип приложения, о котором я говорю, - это серверное приложение, которое редко отключается, занимая не менее -Xmx1024m. Также предположим, что приложение уже профилировано. Я ищу общие рекомендации с точки зрения производительности JVM.
Ответ 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