JIT vs. AOT
Единство и борьба динамического и
статического компиляторов для Java
Никита Липский
Excelsior
Интерпретатор vs.
Компилятор
• Интерпретатор исполняет
программу сразу
• Компилятор транслирует
программу в машинный код
Java to Java Bytecode
• Программа на языке Java
транслируется в Java bytecode
• JVM – исполняет Java bytecode
Исполнение
Java байткода JVM
• Интерпретация
• Компиляция в машинный код и
исполнение на “железе”
Трансляция Java to Native
• Динамическая (Just-In-Time – JIT).
– Трансляция происходит во время
исполнения программы
• Статическая (Ahead-Of-Time – AOT)
– Трансляция происходит до исполнения
программы
Java vs. C/C++
• Умолчательный компилятор в
машинный код для Java – динамический
• Умолчательный компилятор в
машинный код для С/С++ – статический
Мифы вокруг статической
компиляции Java
Миф 1.
Java - динамическая
• Reflection
• Динамическая загрузка
Статическая компиляция невозможна?
Миф 2. Машинный код –
убийца WORA
WORA: Write Once Run Anywhere
(пиши раз, исполняй везде)
!= BORA: Build Once?
(собирай раз??? …)
Миф 3. JIT быстрее
Динамический профиль исполнения
РУЛИТ!
Или не рулит?
Миф 4. AOT быстрее
Машинный код со старта
РУЛИТ!
Java динамическая?
Бинарная совместимость
Позволяет менять один “слегка”
изменившийся класс независимо от
“окружения”
– Замена кода на лету (hotswapping)
– Маленькие обновления
Пользовательские
загрузчики классов
• Умолчательная логика загрузки
провоцирует JAR Hell
Пользовательские
загрузчики классов
Время старта приложения
Холодный старт vs
теплый
Во второй раз приложение стартует
значительно быстрее, чем в первый
– Загрузка кода и данных приложения с
диска
– Загрузка системных и сторонних
динамических библиотек (dll, so)
Java Quick Start
• Java Quick Start
– Предзагружает rt.jar, динамические
библиотеки
AOT быстрее?
• Машинный код “толще” Java bytecode
• Загрузка кода с диска занимает
больше времени, чем его начальное
исполнение
AOT быстрее!
• Код исполняемый на старте – в начало
«экзешника»
• Можно предзагружать стартовый
сегмент последовательным чтением
Оптимизации
• Зависят от выбора внутреннего представления
• Часто невозможны без предварительного анализа программы
• Качество оптимизаций зависит от мощи/точности анализа
Оптимизации
– Протяжка констант
– Удаление избыточного кода
– Удаление общих подвыражений
– Открытая подстановка
– Специализация методов
– Развертывание циклов
– Версионирование циклов
– Вынос инвариантов
– Удаление хвостовой рекурсии
– Девиртуализация вызовов
– Аллокация объектов на стэке и их взрыв
– Удаление проверок времени исполнения
– Удаление избыточной синхронизации
– Оптимальная выборка кода и свертка шаблонов
– Планировка инструкций
– Оптимальное распределение регистров
Оптимизации
• Виды оптимизаций
• На каком внутреннем представлении и с помощью каких анализов?
Анализ потока данных
• Протяжка констант
• Удаление общих подвыражений
• Оптимальное распределение регистров.
• И многое другое
Java – ООП
• Много методов
• Методы маленькие (get/set)
• Методы по умолчанию
ВИРТУАЛЬНЫЕ
Девиртулизация
вызовов
• Предусловие дальнейшей открытой
подстановки (inline)
• Анализ иерархии классов
– метод не перегружается – невиртульный
• Типовый анализ
– new T().foo(); //вызов foo() невиртульный
Аллокация объектов
на стэке
• Все Java объекты создаются в динамической
памяти – Java heap (куча)
• Большинство объектов временные
• Хочется их размещать на стэке метода
• Escape анализ (анализ утечек) –
определяет утекает ли объект в
разделяемую память.
Глобальный анализ
• Типовый и Escape анализы боятся
вызовов, особенно виртуальных.
• Глобальный анализ – анализирует все
методы программы, в частности
уточняя типовый и escapе анализы.
Анализы и оптимизации
• Часто бывают довольно сложными
• Требуют итеративного пересчета
• Глобальный анализ зависит от ВСЕЙ
программы.
Анализы и оптимизации
• Часто бывают довольно сложными
• Требуют итеративного пересчета
• Глобальный анализ зависит от ВСЕЙ
программы.
Все ли это может
себе позволить JIT?
Динамические
оптимизации
• Профилировка и селективная компиляция
• Открытая подстановка на основе профиля исполнения
• Оптимизация трасс
исполнения
• Выбор оптимальных инструкций
Динамические
оптимизации
Может ли статический компилятор
использовать динамический профиль
исполнения?
Горячий код vs теплый
• А что будет, если у приложения нет
ярко выраженного горячего кода?
• Долгий прогрев, результаты прогрева
не используются при дальнейших
стартах приложения
Не кодом единым …
• Кроме кода приложения, есть еще код JVM
– Управление памятью
– Сборка мусора
– Потоки и синхронизация
– Обработка исключительных ситуаций
– …
• Кроме Java кода, есть сторонний код
– Native методы + нативные библиотеки (в т.ч. ОС)
А что сравниваем?
Динамические
компиляторы
HotSpot client
HotSpot server
JRockit
IBM J9
Java ME
.NET
Статические
компиляторы
GCJ
Excelsior JET
IBM J9
Java ME
.NET
А что сравниваем?
• Качество самой реализации влияет на
производительность приложения
– HotSpot server vs HotSpot client
– Java ME JIT vs Java ME AOT
– .NET JIT vs .NET AOT
– GCJ vs Excelsior JET
– HotSpot vs Excelsior JET
Будущее Java
• У беспроводных устройств есть
БАТАРЕЙКА
• Процессорное время в облаках дорого
Будущее Java
• У JIT и AOT есть свои преимущества
• Совмещение двух подходов даст
максимальный эффект
Для тех, кто в танке
Для тех, кто в танке
• Есть много JVM с уникальными
свойствами
• Статическая компиляция Java возможна
и дает преимущества
• Будущее за гибридным подходом