Решение задачи по составлению расписания турнира с разъездами (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)
- JDK 11
- Опции JVM:
-Xmx3840M
и явное указание сборщика мусора:
-XX:+UseG1GC
для G1GC, сборщика мусора с низкой задержкой (по умолчанию во всех трёх JDK).
-XX:+UseParallelGC
для ParallelGC, сборщика мусора с высокой пропускной способностью.
- Основной класс:
org.optaplanner.examples.app.GeneralOptaPlannerBenchmarkApp
из модуляoptaplanner-examples
в OptaPlanner8.10.0.Final
.
- Каждый проход решает 11 задач в OptaPlanner, таких как ротация сотрудников, составление школьного расписания и оптимизация облачных вычислений. Каждая задача выполняется 5 минут. Логирование установлено на
INFO
. Бенчмарк стартует с 30-секундного разогрева JVM, который не засчитывается в результаты.
Решение задач по оптимизации облачных вычислений и составлению школьного расписания
- Решение задач не требует ввода-вывода (за исключением нескольких миллисекунд для загрузки входных данных после запуска). Полностью загружен один CPU. Он постоянно создаёт множество короткоживущих объектов, а GC потом их собирает.
- Все бенчмарки измеряют количество вычислений в секунду. Чем больше, тем лучше. Выведение оценки нетривиально: тест включает множество вычислений, в том числе взаимную проверку на конфликты между всеми объектами.
- Каждый проход решает 11 задач в OptaPlanner, таких как ротация сотрудников, составление школьного расписания и оптимизация облачных вычислений. Каждая задача выполняется 5 минут. Логирование установлено на
- Проходы: Каждая комбинация 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
.