OpenJ9 и IBM J9— это реализация JVM, отличная от стандартной JVM Oracle HotSpot. использовать современныеadoptopenjdkБлагодаря готовым образам Docker вы можете легко переключаться и тестировать различные комбинации, а также выбирать подходящую JVM.
Слух кажется правдой, OpenJ9 уже, кажется, опережает HotSpot с точки зрения использования памяти. HotSpot, кажется, имеет преимущество с точки зрения процессора.
OpenJ9
В мире Java большинство людей знакомы с OpenJDK. Это полная реализация JDK, включая реализацию движка HotSpot JVM. Не многие разработчики понимают или пытаются выбрать HotSpot. Расспросив коллег, все они вспомнили название JRockit, но никто не упомянул IBM J9 и/или Eclipse OpenJ9.
я выучилOpenJ9 хорош в управлении памятью, и был оптимизирован для использования в облаке/контейнере. OpenJ9 — это отдельная реализация JVM. Он происходит от IBM Java SDK/IBM J9, который восходит к OTI Technologies Envy Smalltalk (спасибо
Дэн Хейдинга!).
По мере роста использования микросервисов (а большинство сервисов в Javaнетособенно маленькие). Я думаю, что это снова станет горячей темой!
контрольная работа
До эпохи Docker сравнивать разные версии JVM было относительно сложно. Вам нужно скачать, установить, написать сценарий и запустить все зависимости. Но многие готовые изображения теперь доступны в Интернете.
Вот мои мысли о том, как протестировать JVM:
-
Создайте простойSpring Boot заявление
-
Запускайте приложение в различных образах Docker.
-
Измерение использования памяти после запуска и сборщика мусора
-
Измерьте, сколько времени требуется для запуска небольшого теста с интенсивным использованием ЦП
Это ни в коем случае не тщательный тест или тест, но он должен дать нам приблизительное представление о том, чего мы можем ожидать от виртуальной машины.
Приложение Spring Boot
Созданное мной приложение Spring Boot содержит следующие конечные точки:
-
Конечная точка REST вызывает GC (постарайтесь сделать это разумным)
-
Конечная точка REST создает и сортирует большой случайный массив из 1000, возвращает время выполнения (в мс)
Тесты процессора перечислены ниже:
@RestController
public class LoadTestController {
@RequestMapping("/loadtest")
public LoadTestResult loadtest() {
long before = System.currentTimeMillis();
Random random = new Random();
for(int i = 0; i < 1000; i++) {
long[] data = new long[1000000];
for(int l = 0; l < data.length; l++) {
data[l] = random.nextLong();
}
Arrays.sort(data);
}
return new LoadTestResult(System.currentTimeMillis() - before);
}
}
Является ли этот тест разумным и актуальным… можно спорить бесконечно, но он дает нам некоторое базовое представление о том, какой презентации мы можем от него ожидать. Если слухи об увеличении памяти верны, может ли это быть ударом по производительности? Существуют ли компромиссы производительности?
JVM-образ
Я решил протестировать следующие изображения.
Сначала у нас есть версия 8/9/10/11 (облегченная)openjdkЗеркало:
-
openjdk:8-slim
-
openjdk:9-slim
-
openjdk:10-slim
-
openjdk:11-slim
Далее идет версия 8/9/10adoptopenjdkЗеркало:
-
adoptopenjdk/openjdk8
-
adoptopenjdk/openjdk9
-
adoptopenjdk/openjdk10
После этого OpenJ9, такжеadoptopenjdkПредоставляется для версии 8/9 вместе с ежедневными сборками, выпущенными для 9 (об этом см. мой предыдущий пост в блоге):
-
adoptopenjdk/openjdk8-openj9
-
adoptopenjdk/openjdk9-openj9
-
adoptopenjdk/openjdk9-openj9:nightly
В то же время я решил также представить собственный образ J9 от IBM:
-
ibmcom/ibmjava:8-jre
Протестируйте с помощью Докера
После сборки приложения Spring Boot я запускал каждый образ Docker с помощью следующей команды:
docker run -it -v /Projects/temp/spring-boot-example:/app/spring-boot-example -p 8080:8080 IMAGE_NAME /bin/bash
Я сопоставил каталог проекта «spring-boot-example» с «/apps/spring-boot-example», после чего я могу запустить файл JAR в контейнере. В то же время я перенаправляю порт 8080 на свой хост, чтобы я мог вызывать эти конечные точки.
Далее внутри контейнера я запустил приложение Spring Boot:
java -jar /app/spring-boot-example/target/spring-boot-example-0.0.1-SNAPSHOT.jar
Подождите некоторое время, несколько раз вызовите конечную точку и выполните GC, после чего я измеряю использование памяти.
Затем я вызвал конечную точку «/ loadtest», содержащую тест сортировки массива, и дождался результата.
тест памяти
Вот результаты использования памяти для примера приложения Spring Boot:
Во-первых, вы можете видеть, что использование памяти в Java 8 значительно выше, чем в Java 9 и 10.
Но самое удивительное — это объем памяти, используемый OpenJ9 и J9, если сравнивать Java8 и OpenJ9, то последний почти в 4 раза больше первого. Я поражен, как это произошло? Теперь мы почти можем назвать сервисы Spring Boot микро!
Я также пытался запустить некоторый код Spring Boot в производстве (не только простые примеры), и с ними я увидел улучшение на 40-50% сокращения использования памяти.
Тесты процессора
Я узнал, что OpenJ9 уступает HotSpot, если сравнивать с точки зрения задач, интенсивно использующих процессор. Вот почему я создал небольшой тест для этого.
Отсортируйте 1000 массивов с 1000000 случайных длинных значений. Это занимает около 100 секунд, что должно дать JVM достаточно времени для настройки и оптимизации. Я вызывал тест дважды для каждого тестового изображения. Я записал второй раз, чтобы попытаться исключить время горячей загрузки.
Из графика видно, что зеркалирование J9 и OpenJ9 действительно медленное, самое быстрое — не более 18%. В этом конкретном тестовом примере Java 8 превосходит подавляющее большинство реализаций Java 9 (кроме OpenJ9).
Что дальше?
В продакшне мой текущий проект имеет больше проблем с ЦП (переполнение памяти при частых запусках, а загрузка ЦП составляет 1-2%), чем проблем с памятью. Мы обязательно перейдем на использование OpenJ9 в ближайшем будущем.
Во время тестирования мы столкнулись с некоторыми проблемами:
-
Hessian: (двоичный протокол) имеет встроенное предположение, что System.identityHashCode всегда возвращает положительное число. Это верно для HotSpot, но OpenJ9/J9 также может возвращать отрицательные числа. Это открытая проблема, проект Hessian не исправлял ее несколько лет, похоже, что она не обслуживается? Так что наше решение - держаться подальше от Хессиана.
-
Instana: нам нравится наш инструмент мониторинга Instana, но у него возникают проблемы с подключением прокси-сервера к OpenJ9/J9. К счастью, разработчики Instana помогли нам найти ошибку и исправили ее (и автообновление, вау!)
Открытые вопросы, которые я не заметил:
-
Можете ли вы по-прежнему получать/использовать jmap/hprof и т. д. для информации в OpenJ9?
-
Как он будет работать в более длительной производственной среде?
-
Найдем ли мы другие странные ошибки? Это сложно...
Вы пробовали использовать OpenJ9/J9? Поделитесь своим мнением в разделе комментариев!