Очень много задач впихивал на Java, но на следующий спецэффект почему-то до сих пор не обращал внимания.
- Пишем код, использующий где-нибудь маленькую библиотечную функцию вроде Math.max
- Запускаем и получаем TL
- Копипастим эту функцию из библиотеки в свой файл и вызываем скопипасченную функцию
- Ускорение в несколько раз
Почему-то работает на 32-битных JVM, не проявляется на 64-битных.
Следующий код в запуске Codeforces выдал 876 125
под Java 6 и 687 125
под Java 7.
WTF?
Тоже в копилку: запускаем java у себя на ПК с параметром -server, получаем
210 175
. Что то мне подсказывает, что 64-битная java по умолчанию запускается с ключом -server, что и понятно. Однако неизвестно, из за чего такой разброс между версиями JVM server и desktop.Я вижу следующее объяснение.
Inlining для методов внутри одного класса, видимо, работает как и в client-mode, так и в server-mode. Но в server-mode также осуществляется какой-то "aggressive inlining". Видимо эта оптимизация умеет подставлять куски кода методов (виртуальных тоже) из произвольных классов. На CodeForces как Java 6, так и Java 7 запускаются в client-mode (что, в частности, подтверждается этим постом). Следовательно большинство глобальных оптимизаций, которые доступны только в server-mode, не работают, в частности aggressive inlining. Вот цитата отсюда, подтверждающая мои слова:
Поведение JIT не более предсказуемое, чем всяких gcc/msvc. Я как-то натолкнулся на баг, когда добавление в программу строки вида "if (blahblah) while (true);" замедляло её на 5 секунд (blahblah — что-то очень простое, вида "n > 0"). А если добавить 2 таких строки подряд — то на 10 секунд. На фоне таких спецэффектов отсуствие инлайна функции из библиотеки выглядит не так уж страшно :)