raic-2020
raic-2020 copied to clipboard
Потребляемое время для jvm-стратегий
На данный момент стратегии для jvm-языков испытывают проблемы с доступным процессорным временем.
Например:
- Java: https://russianaicup.ru/game/view/191830# - время выводится каждые 100 тиков, после 600 потрачено 3744мс, по тестирующей системе 13001
- Java: https://russianaicup.ru/game/view/188119# - после 800 тиков внутри стратегии потрачено 6187ms, по тестирующей системе 21037.
Это не может быть накладными расходами на сеть/распаковку/перепаковку входных данных, т.к. вот пример игры на 1000 тиков, где используемое Java время составило < 6 секунд https://russianaicup.ru/game/view/1865#
Это приводит к следующим проблемам:
- Стратегия получает значительно меньше 40 секунд
- Это не какой-то фиксированный штраф (например, 5 секунд), который можно заложить с некоторым запасом и понимать сколько времени доступно. В таких условиях невозможно реализовывать алгоритмы с перебором и отсечением по времени.
По результатам некоторых исследований кажется, что это не GC (лог показывает, что он срабатывает совсм не каждый тик и занимает миллисекунды), а скорее что-то с jit-компилятором, который, возможно из-за работы в фоне (тем более, если доступны несколько ядер) может тратить много процессорного времени. Если это так, то, вероятно, для запуска стратегий для соревнований лучше его как-то сконфигурировать, чтобы уменьшить потребляемое им время.
Варианты, которые могут помочь:
- 1 стратегия - не больше 1 ядра CPU
- Конфигурация jit. Например (может быть актуально не для любой имплементации java, надо проверять в докере):
- -XX:-TieredCompilation -XX:CICompilerCount=1 - уменьшит агрессивность оптимизатора, который будет работать в 1 поток
- дополнительно -XX:CompileThreshold=[20000|50000|100000] - увеличит необходимое кол-во запусков функции до оптимизации (слишком больше число и Java становится интерпретатором как питон)
- -XX:-TieredCompilation -XX:-BackgroundCompilation - опасная вещь - отключает оптимизации jit в бэкграунд потоках. Стратегия теперь +- понимает, сколько времени ест, однако есть БОЛЬШОЙ риск вылететь за ограничение в 1 секунду на тик хода из-за jit оптимизаций прямо во время обсчётов
- -Xint - приравнивает java к python :-)
Было бы неплохо хотябы убрать ограничение в 1 секунду на первый тик. Например тут https://russianaicup.ru/game/view/196345 В первый тик отваливается стратегия потаймауту из-за jit. Мой подсчет показывает 800ms на тик, а в последующие тики, когда jit все собрал, стратегия работает за < 20 ms. Это при том что у меня в коде написано if(currentTick == 0) {Делаем намного меньше чем в другие тики} Если пережить первый тик, то стратегия нормально доигрывает до конца без ТЛЕ как тутhttps://russianaicup.ru/game/view/195830
Так же наблюдаю проблему, стратегия замеряет потребление в ~7сек за матч от старта парсинга, до выдачи ответа, а система видит 30-40сек + таймлимиты
TLDR: кажется с флагами -XX:-TieredCompilation -XX:CompileThreshold=20000 -XX:CICompilerCount=1
заметно лучше (в 1.5\2 раза) и надо бы их добавить на сайте
Сделал замеры на jdk11 варианта без флагов (как на сайте)
% sh ./runLrBatch4QuickStart.sh && time java -jar ./0_cur.jar
499 tickTook=1 globalTimeConsumed=860 segmentTimeConsumed=128 - игра занимает 500-700 тиков против QuickStart
java -jar ./0_cur.jar 12.32s user 0.20s system 187% cpu 6.661 total
~550 тиков, 12.32s - CPU тайма и ~1c засеченного времени
в профиле на другой экземпляр матча так же видим что стратегия занимает +- 10% от всего времени
матч флагами -XX:-TieredCompilation -XX:CompileThreshold=20000 -XX:CICompilerCount=1
показывает лучшие результаты в ~1.5 раза
% sh ./runLrBatch4QuickStart.sh && time java -jar -XX:-TieredCompilation -XX:CompileThreshold=20000 -XX:CICompilerCount=1 ./0_cur.jar
599 tickTook=1 globalTimeConsumed=1459 segmentTimeConsumed=146
java -jar -XX:-TieredCompilation -XX:CompileThreshold=20000 ./0_cur.jar 6.94s user 0.14s system 91% cpu 7.693 total
650 тиков, 7s - CPU тайма и ~1.55s засеченного времени в итоге игра вышла дольше на ~100 тиков, но общего CPU времени потратила меньше почти в два раза.
PS: попробую еще запустить с AOT компиляцией в нативный бинарник в GraalVm
Попробовал скомпилировать бинарник с помощью GraalVM native-image результат очень хороший
% native-image -jar ./0_cur.jar ./0_cur_native
% sh ./runLrBatch4QuickStart.sh && time ./0_cur_native
499 tickTook=2 globalTimeConsumed=1108 segmentTimeConsumed=197
./0_cur_native 1.16s user 0.07s system 19% cpu 6.438 total
~550тиков, 1.16s CPU time и ~1.15s засеченного времени внутри стратегии (напомню результат с настройками запуска с сайта - ~550 тиков, 12.32s - CPU тайма и ~1c засеченного времени )
т.е. проблемы с JIT нет, все время отводится стратегии, скорость не пострадала.
Выглядит как мастхев, попробую разобраться с докером+граальVm и собрать ПР
Можно закрывать, смерджили ПР с граалем, на нем с производительностью все гораздо лучше становится