Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
JIT-компиляция в
виртуальной машине Java
Алексей Рагозин
Обзор доклада
Проблемы динамических языков
 Виртуальные вызовы
 Нетипизированные данные

Подходы к JIT компиляции
 Meth...
Старый добрый C++
Простое наследование
OBJECT
VTABLE

00: methodA
01: methodB
02: methodC
03: methodD

010110010010
CODE
1...
Старый добрый C++
Множественное наследование
OBJECT
VTABLE

00: methodA
01: methodB

VTABLE

02: methodC
03: methodD
00: m...
Старый добрый C++
Множественное наследование
A
B

A
C

D

B

C

D

D
Проблемы виртуальных вызовов
Branch misprediction penalty
• Intel Nehalem – 17 cycles
• Intel Sandy/Ivy bridge – 15 cycles...
Проблемы виртуальных вызовов
Два обращения в память до перехода
• Обращения в память упорядочены
• Конвейер процессор блок...
Проблемы динамических типов
Поля хранятся как хэш-таблица
Доступ к полю
• Арифметическая операция
• Чтение из памяти
• Усл...
Как сделать быстрый интерпретатор?
switch(byteCode) {
case STORE: ...
case LOAD: ...
case ASTORE: ...
case ALOADE: ...
......
Как сделать быстрый интерпретатор?
Интерпретатор HotSpot JVM
• Для каждой инструкции написана процедура на
ассемблере
• Di...
Подходы к JIT компиляции
Классический подход
Независимая компиляция методов
+ использование динамических оптимизаций

Трас...
Подходы к JIT компиляции
Классический подход
Независимая компиляция методов
• JVM, V8, Ion Monkey

Трассирующая компиляция...
Трассирующий JIT
Интерпретация
• Логирование операций и условий ветвления

Профилирование
• Выявление часто используемых т...
Трассирующий JIT
Достоинства
• Девиртуализация и инлайнинг
• Сглаживает проблему динамических типов
• Глубокая оптимизация...
Проблема виртуальных типов
V8 – скрытые типы
• Строгая типизация во время выполнения
TraceMonkey – shape inference/propert...
Ссылки
1. LuaJIT
http://article.gmane.org/gmane.comp.lang.lua.general/58908
2. Incremental Dynamic Code Generation with Tr...
HotSpot JVM
HotSpot JVM JIT
• Быстрый интерпретатор
• Два JIT компилятора (C1 / C2)
• Профилирование для управления компиляцией
• Деоп...
Девиртуализация
Профилирование точек вызовов (call site)
• Мономорфный – большинство переходов на
одну реализацию
• Биморф...
Девиртуализация
“Инлайн” кэш переходов
if (list.getClass == ArrayList.class) {
/* NON VIRTUAL */ list.ArrayList#size()
}
e...
Инкрементальная компиляция
Collections.indexedBinarySearch()

Полиморфный

…
int mid = (low + high) >>> 1;
Comparable<? su...
Инкрементальная компиляция
 JIT компилирует MyPojo.get()
• Collections.binarySort() – инлайнится

 Вызовы в Collections....
On Stack Replacement
public static void main() {
long s = System.nanotime();
for(int i = 0; i != N; ++i) {
/* a lot of cod...
Escape analysis
Тяжёлое наследие молодости – synchronize
public String toString() {
StringBuffer buf = new StringBuffer();...
Scalar replacement
public double length() {
return distance(
new Point(ax, ay),
new Point(bx, by));
}
public double distan...
Сборка мусора и JIT
public class Singleton {
public static final
Singleton INSTANCE = new Singleton()
}

JIT инлайнит fina...
Оптимизация кода

“Красивые самолёты летают быстрее”
– поговорка авиаконструкторов
Спасибо
Алексей Рагозин (alexey.ragozin@gmail.com)

http://blog.ragozin.info
http://aragozin.timepad.ru
Upcoming SlideShare
Loading in …5
×

Алексей Рагозин

853 views

Published on

HighLoad++ 2013

  • Be the first to comment

  • Be the first to like this

Алексей Рагозин

  1. 1. JIT-компиляция в виртуальной машине Java Алексей Рагозин
  2. 2. Обзор доклада Проблемы динамических языков  Виртуальные вызовы  Нетипизированные данные Подходы к JIT компиляции  Method based JIT  Tracing JIT “Грязные трюки” JIT компиляторов
  3. 3. Старый добрый C++ Простое наследование OBJECT VTABLE 00: methodA 01: methodB 02: methodC 03: methodD 010110010010 CODE 101010100110 101010100101 010101001010 101010101010 101010101010 101010101010 101010100010
  4. 4. Старый добрый C++ Множественное наследование OBJECT VTABLE 00: methodA 01: methodB VTABLE 02: methodC 03: methodD 00: methodX 01: methodY 02: methodZ 010110010010 CODE 101010100110 101010100101 010101001010 101010101010 101010101010 101010101010 101010100010 111010100100 011110000010 101001010100
  5. 5. Старый добрый C++ Множественное наследование A B A C D B C D D
  6. 6. Проблемы виртуальных вызовов Branch misprediction penalty • Intel Nehalem – 17 cycles • Intel Sandy/Ivy bridge – 15 cycles • Intel Haskwell – 15 - 20 cycles • AMD K8 / K10 – 13 cycles • AMD Buldozer – 19 - 22 cycles http://www.agner.org/optimize/microarchitecture.pdf
  7. 7. Проблемы виртуальных вызовов Два обращения в память до перехода • Обращения в память упорядочены • Конвейер процессор блокирован Время доступа к памяти • L1 кэш ~0.5 ns • L2 кэш ~7 ns • RAM ~100 ns
  8. 8. Проблемы динамических типов Поля хранятся как хэш-таблица Доступ к полю • Арифметическая операция • Чтение из памяти • Условная операция • Чтение из памяти
  9. 9. Как сделать быстрый интерпретатор? switch(byteCode) { case STORE: ... case LOAD: ... case ASTORE: ... case ALOADE: ... ... } ?
  10. 10. Как сделать быстрый интерпретатор? Интерпретатор HotSpot JVM • Для каждой инструкции написана процедура на ассемблере • Dispath – jump по адресу из таблицы процедур • Каждая процедура заканчивается jump на dispatch  Интерпретация кода в одном кадре стека  Код и таблица переходов кэшируются  Конвейер процессора остаётся загруженным
  11. 11. Подходы к JIT компиляции Классический подход Независимая компиляция методов + использование динамических оптимизаций Трассирующая компиляция Генерация кода для участков без ветвления + использование гардов
  12. 12. Подходы к JIT компиляции Классический подход Независимая компиляция методов • JVM, V8, Ion Monkey Трассирующая компиляция Генерация кода для участков без ветвления • Flash, Trace Monkey, PyPy, LuaJIT
  13. 13. Трассирующий JIT Интерпретация • Логирование операций и условий ветвления Профилирование • Выявление часто используемых трасс Компиляция трасс • • • • Машинный код без ветвлений Гарды в местах проверки условий Глобальная оптимизация трассы Нарушение гарда – возврат к интерпретации
  14. 14. Трассирующий JIT Достоинства • Девиртуализация и инлайнинг • Сглаживает проблему динамических типов • Глубокая оптимизация горячих участков Недостатки • Трассировка – ОЧЕНЬ медленная интерпретация • Долгое время разогрева
  15. 15. Проблема виртуальных типов V8 – скрытые типы • Строгая типизация во время выполнения TraceMonkey – shape inference/property cache • “Инлайн” кэш в скомпилированном коде LuaJIT – трейс компиляция поиска по хешу HREFK: if (hash[17].key != key) goto exit HLOAD: x = hash[17].value -orHSTORE: hash[17].value = x
  16. 16. Ссылки 1. LuaJIT http://article.gmane.org/gmane.comp.lang.lua.general/58908 2. Incremental Dynamic Code Generation with Trace Trees http://www.ics.uci.edu/~franz/Site/pubs-pdf/ICS-TR-06-16.pdf 3. V8 Design aspects https://developers.google.com/v8/design 4. RPython http://tratt.net/laurie/research/pubs/papers/bolz_tratt__the_impact_of_ metatracing_on_vm_design_and_implementation.pdf
  17. 17. HotSpot JVM
  18. 18. HotSpot JVM JIT • Быстрый интерпретатор • Два JIT компилятора (C1 / C2) • Профилирование для управления компиляцией • Деоптимизация кода • On Stack Replacement (OSR)
  19. 19. Девиртуализация Профилирование точек вызовов (call site) • Мономорфный – большинство переходов на одну реализацию • Биморфный - большинство переходов на одну из двух реализаций • Полиморфный
  20. 20. Девиртуализация “Инлайн” кэш переходов if (list.getClass == ArrayList.class) { /* NON VIRTUAL */ list.ArrayList#size() } else { /* VIRTUAL */ list.size(); }
  21. 21. Инкрементальная компиляция Collections.indexedBinarySearch() Полиморфный … int mid = (low + high) >>> 1; Comparable<? super T> midVal = list.get(mid); int cmp = midVal.compareTo(key); … MyPojo Полиморфный List<String> keys = new ArrayList<String>(); List<String> vals = new ArrayList<String>(); public String get(String key) { int n = Collections.binarySearch(keys, key); return n < 0 ? null ? vals.get(n); }
  22. 22. Инкрементальная компиляция  JIT компилирует MyPojo.get() • Collections.binarySort() – инлайнится  Вызовы в Collections.binarySort() становятся мономорфными  JIT продолжает профилирование и перекомпилирует метод  Вызовы get() и compareTo() девиртуализированны и заинлайнены
  23. 23. On Stack Replacement public static void main() { long s = System.nanotime(); for(int i = 0; i != N; ++i) { /* a lot of code */ ... } long avg = (System.nanotime() - s) / N; } JIT может перекомпилировать main и подменить точку возврата на стеке, находясь внутри цикла
  24. 24. Escape analysis Тяжёлое наследие молодости – synchronize public String toString() { StringBuffer buf = new StringBuffer(); buf.append("X=").append(x); buf.append(",Y=").append(y); return buf.toString(); }  buf не выходит за пределы метода  все методы buf заинлайнены  удаляем код синхронизации
  25. 25. Scalar replacement public double length() { return distance( new Point(ax, ay), new Point(bx, by)); } public double distance(Point a, Point b) { double w = a.x - b.x; double h = a.y - b.y; return Math.sqrt(w*w + h*h); } После инлайна distance в length  JIT заменяет объекты Point на скалярные переменные
  26. 26. Сборка мусора и JIT public class Singleton { public static final Singleton INSTANCE = new Singleton() } JIT инлайнит final static переменные • Адрес объекта в памяти в машинном коде • С точки зрения GC код метода структура  Учитывается как корень при маркировке  Адрес в коде корректируется при перемещении объекта
  27. 27. Оптимизация кода “Красивые самолёты летают быстрее” – поговорка авиаконструкторов
  28. 28. Спасибо Алексей Рагозин (alexey.ragozin@gmail.com) http://blog.ragozin.info http://aragozin.timepad.ru

×