MailRuChamps / raic-2020

GNU General Public License v3.0
26 stars 27 forks source link

Потребляемое время для jvm-стратегий #106

Open dbf256 opened 3 years ago

dbf256 commented 3 years ago

На данный момент стратегии для jvm-языков испытывают проблемы с доступным процессорным временем.

Например:

  1. Java: https://russianaicup.ru/game/view/191830# - время выводится каждые 100 тиков, после 600 потрачено 3744мс, по тестирующей системе 13001
  2. Java: https://russianaicup.ru/game/view/188119# - после 800 тиков внутри стратегии потрачено 6187ms, по тестирующей системе 21037.

Это не может быть накладными расходами на сеть/распаковку/перепаковку входных данных, т.к. вот пример игры на 1000 тиков, где используемое Java время составило < 6 секунд https://russianaicup.ru/game/view/1865#

Это приводит к следующим проблемам: 1) Стратегия получает значительно меньше 40 секунд 2) Это не какой-то фиксированный штраф (например, 5 секунд), который можно заложить с некоторым запасом и понимать сколько времени доступно. В таких условиях невозможно реализовывать алгоритмы с перебором и отсечением по времени.

По результатам некоторых исследований кажется, что это не GC (лог показывает, что он срабатывает совсм не каждый тик и занимает миллисекунды), а скорее что-то с jit-компилятором, который, возможно из-за работы в фоне (тем более, если доступны несколько ядер) может тратить много процессорного времени. Если это так, то, вероятно, для запуска стратегий для соревнований лучше его как-то сконфигурировать, чтобы уменьшить потребляемое им время.

DragoonXen commented 3 years ago

Варианты, которые могут помочь:

  1. 1 стратегия - не больше 1 ядра CPU
  2. Конфигурация jit. Например (может быть актуально не для любой имплементации java, надо проверять в докере):
    • -XX:-TieredCompilation -XX:CICompilerCount=1 - уменьшит агрессивность оптимизатора, который будет работать в 1 поток
    • дополнительно -XX:CompileThreshold=[20000|50000|100000] - увеличит необходимое кол-во запусков функции до оптимизации (слишком больше число и Java становится интерпретатором как питон)
    • -XX:-TieredCompilation -XX:-BackgroundCompilation - опасная вещь - отключает оптимизации jit в бэкграунд потоках. Стратегия теперь +- понимает, сколько времени ест, однако есть БОЛЬШОЙ риск вылететь за ограничение в 1 секунду на тик хода из-за jit оптимизаций прямо во время обсчётов
    • -Xint - приравнивает java к python :-)
azu0nyan commented 3 years ago

Было бы неплохо хотябы убрать ограничение в 1 секунду на первый тик. Например тут https://russianaicup.ru/game/view/196345 В первый тик отваливается стратегия потаймауту из-за jit. Мой подсчет показывает 800ms на тик, а в последующие тики, когда jit все собрал, стратегия работает за < 20 ms. Это при том что у меня в коде написано if(currentTick == 0) {Делаем намного меньше чем в другие тики} Если пережить первый тик, то стратегия нормально доигрывает до конца без ТЛЕ как тутhttps://russianaicup.ru/game/view/195830

Karloid commented 3 years ago

Так же наблюдаю проблему, стратегия замеряет потребление в ~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

java_no_flags ~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

java_jit_flags

650 тиков, 7s - CPU тайма и ~1.55s засеченного времени в итоге игра вышла дольше на ~100 тиков, но общего CPU времени потратила меньше почти в два раза.

PS: попробую еще запустить с AOT компиляцией в нативный бинарник в GraalVm

Karloid commented 3 years ago

Попробовал скомпилировать бинарник с помощью 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 и собрать ПР

Karloid commented 3 years ago

Можно закрывать, смерджили ПР с граалем, на нем с производительностью все гораздо лучше становится