Решение задачи по составлению расписания турнира с разъездами (TTP) — один из вычислительных тестов в нашем наборе

Позавчера вышла Java 17 с кучей новых функций и усовершенствований. Большинство из них требуют изменения кода. Кроме производительности. Просто заменяете JDK — и получаете бесплатную прибавку производительности. Но насколько большую? Стоит ли она того? Для этого мы провели бенчмарки JDK 17, JDK 16 и JDK 11.

Тесты проводятся в сложных вычислительных задачах опенсорсного решателя проблем OptaPlanner, полностью написанного на Java.

Методология


  • Конфигурация: Cтабильная машина без каких-то вычислительных процессов, процессор Intel Xeon Silver 4116 @ 2,1 ГГц (12 ядер / 24 потока) и 128 ГиБ RAM, под управлением RHEL 8 x86_64.

  • JDK (для компиляции и запуска):

    • JDK 11

      openjdk 11.0.12 2021-07-20
      OpenJDK Runtime Environment Temurin-11.0.12+7 (build 11.0.12+7)
      OpenJDK 64-Bit Server VM Temurin-11.0.12+7 (build 11.0.12+7, mixed mode)
    • JDK 16

      openjdk 16.0.2 2021-07-20
      OpenJDK Runtime Environment (build 16.0.2+7-67)
      OpenJDK 64-Bit Server VM (build 16.0.2+7-67, mixed mode, sharing)
    • JDK 17 (загружено 2021-09-06)

      openjdk 17 2021-09-14
      OpenJDK Runtime Environment (build 17+35-2724)
      OpenJDK 64-Bit Server VM (build 17+35-2724, mixed mode, sharing)

  • Опции JVM: -Xmx3840M и явное указание сборщика мусора:

    -XX:+UseG1GC для G1GC, сборщика мусора с низкой задержкой (по умолчанию во всех трёх JDK).

    -XX:+UseParallelGC для ParallelGC, сборщика мусора с высокой пропускной способностью.

  • Основной класс: org.optaplanner.examples.app.GeneralOptaPlannerBenchmarkApp из модуля optaplanner-examples в OptaPlanner 8.10.0.Final.

    • Каждый проход решает 11 задач в OptaPlanner, таких как ротация сотрудников, составление школьного расписания и оптимизация облачных вычислений. Каждая задача выполняется 5 минут. Логирование установлено на INFO. Бенчмарк стартует с 30-секундного разогрева JVM, который не засчитывается в результаты.


      Решение задач по оптимизации облачных вычислений и составлению школьного расписания
    • Решение задач не требует ввода-вывода (за исключением нескольких миллисекунд для загрузки входных данных после запуска). Полностью загружен один CPU. Он постоянно создаёт множество короткоживущих объектов, а GC потом их собирает.
    • Все бенчмарки измеряют количество вычислений в секунду. Чем больше, тем лучше. Выведение оценки нетривиально: тест включает множество вычислений, в том числе взаимную проверку на конфликты между всеми объектами.

  • Проходы: Каждая комбинация JDK и сборщика мусора запускается трижды. Приведённые результаты — среднее трёх проходов.

Результаты


Сравнение Java 11 (LTS), Java 16 и Java 17 (LTS)




Таблица 1. Количество вычислений в секунду с G1GC на разных JDK

Среднее

Балансировка облака

Переназначение машин

Расписание занятий

Расписание экзаменов

Ротация медсестёр

Расписание турнира

Набор данных

200c

800c

B1

B10

c7

c8

s2

s3

m1

mh1

nl14

JDK 11

103 606

96 700

274 103

37 421

11 779

13 660

14 354

8,982

3,585

3,335

5,019

JDK 16

109 203

97 567

243 096

38 031

13 950

16 251

15 218

9528

3817

3508

5472

JDK 17

106 147

98 069

245 645

42 096

14 406

16 924

15 619

9726

3802

3601

5618

11 → 17

8,66%

2,45%

1,42%

-10,38%

12,49%

22,30%

23,90%

8,81%

8,28%

6,05%

7,98%

11,95%

16 → 17

2,41%

-2,80%

0,51%

1,05%

10,69%

3,27%

4,14%

2,63%

2,08%

-0,39%

2,65%

2,67%




Таблица 2. Количество вычислений в секунду с ParallelGC на разных JDK

Среднее

Балансировка облака

Переназначение машин

Расписание занятий

Расписание экзаменов

Ротация медсестёр

Расписание турнира

Набор данных

200c

800c

B1

B10

c7

c8

s2

s3

m1

mh1

nl14

JDK 11

128 553

121 974

292 761

48 339

13 397

15 540

16 392

9887

4409

4148

6097

JDK 16

128 723

123 314

281 882

45 622

16 243

18 528

17 742

10 744

4608

4348

6578

JDK 17

130 215

124 498

262 753

45 058

16 479

18 904

18 023

10 845

4658

4430

6641

11 → 17

6,54%

1,29%

2,07%

-10,25%

-6,79%

23,00%

21,64%

9,95%

9,68%

5,63%

6,80%

8,92%

16 → 17

0,37%

1,16%

0,96%

-6,79%

-1,24%

1,45%

2,03%

1,59%

0,94%

1,08%

1,89%

0,96%


Примечание. Если посмотреть на необработанные данные (они здесь не показаны), то задача переназначения машин (B1 и B10) в трёх прогонах демонстрирует очень разные результаты на одном и том же JDK и GC. Зачастую они отличаются более чем на 10%. В других задачах такой проблемы нет.

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

Сравнение G1GC и ParallelGC на Java 17




Таблица 3. Количество вычислений в секунду на JDK 17 с различными GC

Среднее

Балансировка облака

Переназначение машин

Расписание занятий

Расписание экзаменов

Ротация медсестёр

Расписание турнира

Набор данных

200c

800c

B1

B10

c7

c8

s2

s3

m1

mh1

nl14

G1GC

106 147

98 069

245 645

42 096

14 406

16 924

15 619

9726

3802

3601

5618

ParallelGC

130 215

124 498

262 753

45 058

16 479

18 904

18 023

10 845

4658

4430

6641

G1 → ParallelGC

16,39%

22,67%

26,95%

6,96%

7,04%

14,39%

11,69%

15,39%

11,50%

22,50%

23,01%

18,20%


Резюме


В среднем, для сценариев OptaPlanner эти тесты показывают:

Java 17 на 8,66% быстрее Java 11 и на 2,41% быстрее Java 16 для G1GC (дефолтный сборщик мусора).

Java 17 на 6,54% быстрее Java 11 и на 0,37% быстрее Java 16 с ParallelGC.

Parallel Garbage Collector на 16,39% быстрее, чем G1 Garbage Collector.

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

Минуточку...


Когда мы замеряли JDK 15, то она оказалась на 11,24% быстрее, чем Java 11. Теперь же выигрыш меньше. Это значит, что Java 17 медленнее Java 15?

Ну, нет. Конечно, Java 17 быстрее, чем Java 15. Предыдущие бенчмарки выполнялись на другой кодовой базе (OptaPlanner 7.44 вместо 8.10), так что не будем сравнивать яблоки с апельсинами.

Заключение


В заключение следует отметить, что прирост производительности в JDK17 вполне оправдывает обновление — по крайней мере, для OptaPlanner.

Самым быстрым сборщиком мусора для нас остаётся ParallelGC, а не дефолтный G1GC.



Комментарии (2)


  1. UbuRus
    16.09.2021 15:40
    +1

    Не смогли использовать G1GC из-за багов которые приводили к падению приложения.
    А вот Shenandoah хорошо зашел и там тоже хорошо становится https://developers.redhat.com/articles/2021/09/16/shenandoah-openjdk-17-sub-millisecond-gc-pauses


  1. kacetal
    17.09.2021 18:27
    +3

    Интересно было бы увидеть сравнение с 8 java, все таки многие ещё на ней пока.