aot-компиляция java

87
AOT компиляция Java Никита Липский Excelsior 1

Upload: tech-talks-nsu

Post on 19-Jan-2017

213 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: AOT-компиляция Java

AOT  компиляция  Java    

Никита Липский Excelsior

1

Page 2: AOT-компиляция Java

ÄДàаâвíнûыìм äдàаâвíнîо  

2

Page 3: AOT-компиляция Java

ÄДàаâвíнûыìм äдàаâвíнîо,

ÂВîо âвðрåеìмåеíнàа ÑС +++ ++++++  

3

Page 4: AOT-компиляция Java

ÄДàаâвíнûыìм äдàаâвíнîо,

ÂВîо âвðрåеìмåеíнàа ÑС +++, ÂВñсåе êкîоìмïпèиëлÿяòтîоðрûы áбûыëлèи ñсòтàаòтèи÷чåеñсêкèиåе ++++++  

4

Page 5: AOT-компиляция Java

ÏПîоêкàа íнåе ïпîоÿяâвèиëлàаñсüь..  

5

Page 6: AOT-компиляция Java

ÏПîоêкàа íнåе ïпîоÿяâвèиëлàаñсüь

Java  

6

Page 7: AOT-компиляция Java

•  Интерпретация  

•  Компиляция  в  машинный  код  и  исполнение  на  “железе”  

Исполнение    Java  байткода  JVM  

7

Page 8: AOT-компиляция Java

Трансляция  Java  to  Na@ve  

•  Динамическая  (Just-­‐In-­‐Time  –  JIT).    – Трансляция  происходит  во  время  исполнения  программы  

•  Статическая  (Ahead-­‐Of-­‐Time  –  AOT)  – Трансляция  происходит  до  исполнения  программы  

8

Page 9: AOT-компиляция Java

9

Page 10: AOT-компиляция Java

Статическая  компиляция  Java  

•  Это  вообще  возможно?  –  Если  да,  то  при  каких  условиях  и  будет  ли  это  все  еще  называться  Java?  

•  Зачем  это  нужно?  –  Обфускация  vs.  статическая  компиляция  –  Старт  приложения  –  Уменьшение  размера  дистрибутива  Java  приложения  без  зависимостей  от  Java  

–  Производительность:  какие  преимущества  перед  JIT  компиляцией  

–  Почему  AOT  лучше  для  Desktop,  Embedded,  Mobile  –  Есть  ли  выгода  от  применения  AOT  на  server  side  

 

10

Page 11: AOT-компиляция Java

11

Page 12: AOT-компиляция Java

Кому  нужен  AOT  для  Java?    

Кто знает про Excelsior JET? Кто знает про Excelsior JET?

12

Page 13: AOT-компиляция Java

 Мифы  вокруг  статической  

компиляции  Java  

13

Page 14: AOT-компиляция Java

•  Reflecron  

•  Динамическая  загрузка  

 Статическая  компиляция  невозможна?  

Миф  1.    Java  -­‐    «слишком»  динамическая    

14

Page 15: AOT-компиляция Java

 WORA:  Write  Once  Run  Anywhere  (пиши  раз,  исполняй  везде)  

!=  BORA:  Build  Once?  (собирай  раз???  …)  

Миф  2.  AOT  компиляция  –    убийца  WORA  

15

Page 16: AOT-компиляция Java

”Я  получу  (маленький)  исполняемый  файл,  который  будет  работать  без  JVM  (как  в  С)”  

 Но:  – Стандартные  классы?  –   GC,  reflecron?  

Миф  3.  AOT  =  маленький  Exe  

16

Page 17: AOT-компиляция Java

 Тем  не  менее,  используя  AOT,  можно  получить    дистрибутив  Java  приложения  без  зависимостей  от  Java  значительно  меньший,  чем  размер  JRE:  

 “Javа  худеет”:    h�ps://www.youtube.com/results?search_query=javaday+худеет    

Миф  3.  AOT  =  маленький  Exe  

17

Page 18: AOT-компиляция Java

Java  «слишком»  динамическая  

18

Page 19: AOT-компиляция Java

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

•  Уникальное  пространство  имен  

•  Позволяют  управлять  зависимостями,  решая  проблемы  JAR  hell  (OSGi,  Java  Module  System)  

•  Java  EE  сервера,  Eclipse  RCP,  плагины  

Нестандартные  загрузчики  классов  

19

Page 20: AOT-компиляция Java

Как  компилировать  статически?  •  Компилировать  каждый  класс  изолировано  от  других  – Плохо  для  производительности  

•  Изучить  логику  разрешения  ссылок  для  популярных  загрузчиков  – Не  работает  для  произвольных  загрузчиков  

Нестандартные  загрузчики  классов  

20

Page 21: AOT-компиляция Java

Нестандартные  загрузчики  классов  

Classes  

21

Page 22: AOT-компиляция Java

Classes  

CL1  CL2  CL3  CL4  

Нестандартные  загрузчики  классов  

CLi: classloader (загрузчик классов)

22

Page 23: AOT-компиляция Java

•  CL4  •  CL3  

•  CL2  •  CL1  

classes   classes  

classes  classes  

Нестандартные  загрузчики  классов  

23

Page 24: AOT-компиляция Java

•  CL4  •  CL3  

•  CL2  •  CL1  

classes  classes  

classes  classes  

Нестандартные  загрузчики  классов  

24

Page 25: AOT-компиляция Java

•  CL4  •  CL3  

•  CL2  •  CL1  

classes   classes  

classes  classes  

Нестандартные  загрузчики  классов  

25

Page 26: AOT-компиляция Java

–  Картинка  

•  CL4  •  CL3  

•  CL2  •  CL1  

classes   classes  

classes  

Нестандартные  загрузчики  классов  

26

Page 27: AOT-компиляция Java

•  CL4  •  CL3  

•  CL2  •  CL1  

classes   classes  

Нестандартные  загрузчики  классов  

27

Page 28: AOT-компиляция Java

Схема  поддержки  загрузчиков  в  AOT:  •  Компонента  разрешения  ссылок  в  AOT    компиляторе:  –  Определяет,  какие  загрузчики  будут  созданы  

во  время  исполнения  и  назначает  каждому  статический  ID  

–  Разбивает  классы  приложения  по  загрузчикам    –  Разрешает  ссылки  между  классами    

Нестандартные  загрузчики  классов  

28

Page 29: AOT-компиляция Java

Схема  поддержки  загрузчиков  в  AOT:  •  Во  время  исполнения:  

–  По  экземпляру  загрузчика  вычисляется  ID  –  Имея  статический  ID,  мы  можем  грузить  

статически  скомпилированные  классы:  •  создание  экземпляра  класса  java.lang.Class  •  наполнение  его  рефлективной  информацией  •  загрузка  кода  осуществляется  OS  

Нестандартные  загрузчики  классов  

29

Page 30: AOT-компиляция Java

Зачем  AOT  для  Java?  

30

Page 31: AOT-компиляция Java

Защита  кода  от  декомпиляции  

31

Page 32: AOT-компиляция Java

•  Java  bytecode  легко  превращается  в  исходный  код  

•  Процесс  обфускации  при  активном  использовании  reflecron  трудоемок  и  трудно  поддерживаем  

•  Даже  по  обфусцированному  коду  часто  можно  понять,  что  код  делает  (ссылки  на  JDK  остаются  в  неизменном  виде)  

Защита  кода  приложения  

32

Page 33: AOT-компиляция Java

•  Машинный  код  можно  только  эффективно  дизассемблировать  

•  По  дизассемблированному  коду  не  понять  структуру  приложения  (нет  имен  классов,  методов)  

•  После  агрессивной  оптимизации  машинный  код  далек  от  оригинального  кода  

Защита  кода  приложения  

33

Page 34: AOT-компиляция Java

Время  старта  приложения  

34

Page 35: AOT-компиляция Java

Во  второй  раз  приложение  стартует  значительно  быстрее,  чем  в  первый  

– Загрузка  кода  и  данных  приложения  с  диска  – Загрузка  системных  и  сторонних  динамических  библиотек  (dll,  so)  

Холодный  старт  vs  теплый  

35

Page 36: AOT-компиляция Java

 Java  Quick  Start  

 

•  Java  Quick  Start  – Предзагружает  rt.jar,  динамические  библиотеки  

36

Page 37: AOT-компиляция Java

AOT  быстрее?  

•  Машинный  код  “толще”  Java  bytecode  

•  Загрузка  кода  с  диска  занимает  больше  времени,  чем  его  начальное  исполнение  

37

Page 38: AOT-компиляция Java

AOT  быстрее!  

•  Код  исполняемый  на  старте  –  в  начало  исполняемого  файла    

•  Можно  предзагружать  стартовый  сегмент  последовательным  чтением  

38

Page 39: AOT-компиляция Java

39

Page 40: AOT-компиляция Java

Производительность  

40

Page 41: AOT-компиляция Java

       “Скомпилировав  Java  статически,  мы  получим  скорость  приложения  как  в  C,  C    быстрее  Java,    следовательно  AOT  быстрее”  

   

Миф  4.  AOT  быстрее  

41

Page 42: AOT-компиляция Java

   

“Эффективно  оптимизировать  Java  приложения  можно  только  на  основе  динамического  профиля  исполнения”    

 

Миф  5.  JIT  быстрее  

42

Page 43: AOT-компиляция Java

–  Протяжка  констант  –  Удаление  избыточного  кода  –  Удаление  общих  подвыражений  

–  Открытая  подстановка  –  Специализация  методов  –  Развертывание  циклов  –  Версионирование  циклов  –  Вынос  инвариантов  –  Удаление  хвостовой  рекурсии  

–  Девиртуализация  вызовов  

–  Аллокация  объектов  на  стэке  и  их  взрыв  

–  Удаление  проверок  времени  исполнения  

–  Удаление  избыточной  синхронизации  

–  Оптимальная  выборка  кода  и  свертка  шаблонов  

–  Планировка  инструкций  

–  Оптимальное  распределение  регистров  

Виды  оптимизаций  

43

Page 44: AOT-компиляция Java

Java  –  ООП  

• Много  методов  

• Методы  маленькие  (get/set)  

• Методы  по  умолчанию  ВИРТУАЛЬНЫЕ  

44

Page 45: AOT-компиляция Java

•  Предусловие  дальнейшей  открытой  подстановки  (inline)  

•  Анализ  иерархии  классов    – метод  не  перегружается  –  невиртуальный  

•  Типовый  анализ  – new T().foo(); //вызов foo() невиртуальный

•  Inline  caches  

Девиртуализация  вызовов  

45

Page 46: AOT-компиляция Java

A a; …                                                  è    

a.foo();  

if (RT_Type(a) in CHA) { inlined body of foo() } else { a.foo(); }

Идея: метод не перегружается – невиртуальный

Анализ  иерархии  классов  (CHA)  

46

Page 47: AOT-компиляция Java

A a; //A – формальный тип

Если  A –  формальный  тип  переменой  a,    то  во  время  исполнения  в  a  могут  находится  значения  типа  наследника  A.      Такие  типы  называются  фактическими.   A a = new B(); //B – фактический тип  Источником  фактических  типов  для  статического  анализа  являются  операторы  new.    

Формальный  vs  фактический  тип    

47

Page 48: AOT-компиляция Java

Идея:     new A().foo();  //невиртуальный  вызов      

Типовый  анализ  

48

Page 49: AOT-компиляция Java

A a = b? new B() : new C(); a.foo();  Если  foo()  в  B  и  С один  и  тоже,  то    a.foo() невиртуальный  вызов                                        (можно  инлайнить)  

Типовый  анализ  

49

Page 50: AOT-компиляция Java

A a = b? bar() : baz(); … a.foo();  Если  bar() возвращает  только  new B,                  а  baz()                                экземпляры  new С,  то    a.foo() - опять  невиртуальный  вызов                                                        (можно  инлайнить)  

Типовый  анализ  

50

Page 51: AOT-компиляция Java

   Откуда  мы  знаем,  что  возвращает  bar() и  baz()?  

Типовый  анализ  

51

Page 52: AOT-компиляция Java

•  Глобальный  анализ  –  анализирует  все  методы  программы,  вычисляя  про  каждый  метод  полезную  информацию    

•  Результаты  глобального  анализа  используются  для  оптимизации  конкретного  метода      

Глобальный  анализ  

52

Page 53: AOT-компиляция Java

•  Все  Java  объекты  создаются  в  динамической  памяти  –  Java  heap  (куча)  

•  Большинство  объектов  временные  •  Хочется  их  размещать  на  стэке  метода  

•  Escape  анализ  (анализ  утечек)  –  определяет  утекает  ли  объект  в  разделяемую  память.  

Аллокация  объектов    на  стэке  

53

Page 54: AOT-компиляция Java

void foo() { for (Object o: getCollection()) { doSomething(o);

} }

Пример    

54

Page 55: AOT-компиляция Java

void foo() { Iterator iter = getCollection().iterator(); while (iter.hasNext()) { Object o = iter.next(); doSomething(o);

}

}

Пример    

55

Page 56: AOT-компиляция Java

void foo() { ArrayList list = getCollection(); Iterator iter = list.iterator(); while (iter.hasNext()) { Object o = iter.next(); doSomething(o);

}

}

Пример    

56

Page 57: AOT-компиляция Java

void foo() { ArrayList list = getCollection(); ArrayList.ListItr iter = new ListItr(list); while (iter.hasNext()) { Object o = iter.next(); doSomething(o);

}

}

Пример    

57

Page 58: AOT-компиляция Java

void foo() { ArrayList list = getCollection(); ArrayList.ListItr iter = onStack ListItr(); iter.this$0 = list; iter.cursor = 0; iter.size = list.elemData.length; while (iter.hasNext()) { Object o = iter.next(); doSomething(o);

}

}

Пример    

58

Page 59: AOT-компиляция Java

void foo() { ArrayList list = getCollection(); ArrayList.ListItr iter = onStack ListItr(list); iter.this$0 = list; iter.cursor = 0; iter.size = list.elemData.length; while (iter.cursor < iter.size) { int index = iter.cursor++; Object o = iter.this$0.elemData[index]; doSomething(o);

}

}

Пример    

59

Page 60: AOT-компиляция Java

void foo() { ArrayList list = getCollection(); int cursor = 0; int size = list.elemData.length; while (cursor < size) { Object o = list.elemData[cursor++]; doSomething(o); }

}

Пример    

60

Page 61: AOT-компиляция Java

void foo() { ArrayList list = getCollection();

int size = list.elemData.length; for (int i = 0; i < size; i++) { doSomething(list.elemData[i]); } }

Пример    

61

Page 62: AOT-компиляция Java

•  Часто  бывают  довольно  сложными    

•  Требуют  итеративного  пересчета  

•  Глобальный  анализ  зависит  от  ВСЕЙ  программы.  

Анализ  и  оптимизации  

62

Page 63: AOT-компиляция Java

•  Часто  бывают  довольно  сложными    •  Требуют  итеративного  пересчета  •  Глобальный  анализ  зависит  от  ВСЕЙ  программы.  

Все  ли  это  может  себе  позволить  JIT?  

Анализ  и  оптимизации  

63

Page 64: AOT-компиляция Java

•  Часто  бывают  довольно  сложными    •  Требуют  итеративного  пересчета  •  Глобальный  анализ  зависит  от  ВСЕЙ  программы.  

Все  ли  это  может  себе  позволить  JIT?  

Анализ  и  оптимизации  

64

Page 65: AOT-компиляция Java

•  Часто  бывают  довольно  сложными    •  Требуют  итеративного  пересчета  •  Глобальный  анализ  зависит  от  ВСЕЙ  программы.  

Все  ли  это  может  себе  позволить  JIT?  

Анализ  и  оптимизации  

65

Page 66: AOT-компиляция Java

•  Профилировка  и    селективная  компиляция  

•  Открытая  подстановка  на  основе  профиля  исполнения    

•  Оптимизация  трасс  исполнения  

•  Выбор  оптимальных  инструкций  

Динамические  оптимизации  

66

Page 67: AOT-компиляция Java

•  А  что  будет,  если  у  приложения  нет  ярко  выраженного  горячего  кода?  

•  Долгий  прогрев,  результаты  прогрева  не  используются  при  дальнейших  стартах  приложения  

Горячий  код  vs  теплый  

67

Page 68: AOT-компиляция Java

JFCMark  (Short  Run)  

0%  

50%  

100%  

150%  

200%  

250%  

2  core  Celeron,  2.60Ghz   4  core  i5,  3.8GZ  

Excelsior  JET  

HotSpot  client  

HotSpot  server  

68

Page 69: AOT-компиляция Java

JFCMark  (Long  Run)  

0%  

20%  

40%  

60%  

80%  

100%  

120%  

140%  

160%  

2  core  Celeron,  2.60Ghz   4  core  i5,  3.8GZ  

Excelsior  JET  

HotSpot  client  

HotSpot  server  

69

Page 70: AOT-компиляция Java

 Может  ли  статический  компилятор  использовать  динамический  профиль  исполнения?  

Динамические  оптимизации  

70

Page 71: AOT-компиляция Java

Server  side  

•  Процессорное  время  в    облаках  –  дорого    

•  Через  некоторое  время  работы  сервера  профиль  исполнения  стабилизируется  

•  Почему  этот  профиль  не  передать  статическому  компилятору?  

71

Page 72: AOT-компиляция Java

•  Кроме  кода  приложения,  есть  еще  код  JVM  –  Управление  памятью  –  Сборка  мусора  –  Потоки  и  синхронизация  –  Обработка  исключительных  ситуаций  –  …  

•  Кроме  Java  кода,  есть  сторонний  код    –  Narve  методы  +  нативные  библиотеки  (в  т.ч.  ОС)  

Не  кодом  единым  …  

72

Page 73: AOT-компиляция Java

Embedded  

•  Чем  слабее  железо,  тем  дороже  динамическая  компиляция  

•  Встроенные  системы  часто  не  обладают  теми  же  вычислительными  мощностями,  что  и  настольные  компьютеры/сервера    

73

Page 74: AOT-компиляция Java

Mobile  

•  JVM  on  Mobile:  

74

Page 75: AOT-компиляция Java

Mobile  

•  JVM  on  Mobile:  – Платформенные  классы  

75

Page 76: AOT-компиляция Java

Mobile  

•  JVM  on  Mobile:  – Платформенные  классы  – GC  и    Memory  Manager  

76

Page 77: AOT-компиляция Java

Mobile  

•  JVM  on  Mobile:  – Платформенные  классы  – GC  и    Memory  Manager  – Reflecron  

77

Page 78: AOT-компиляция Java

Mobile  

•  JVM  on  Mobile:  – Платформенные  классы  – GC  и    Memory  Manager  – Reflecron  –  JIT  

78

Page 79: AOT-компиляция Java

Mobile  

•  JVM  on  Mobile:  – Платформенные  классы  – GC  и    Memory  Manager  – Reflecron  –  JIT  

Чего  не  хватает?  

79

Page 80: AOT-компиляция Java

Mobile  

•  JVM  on  Mobile:  – Платформенные  классы  – GC  и    Memory  Manager  – Reflecron  –  JIT  

Зарядки!    

80

Page 81: AOT-компиляция Java

Mobile  

•  У  беспроводных  устройств  есть  БАТАРЕЙКА    •  Стоит  ли  ее  тратить  на  динамическую  компиляцию?  

81

Page 82: AOT-компиляция Java

iOS  

•  Политика  распространения  приложений  на  iOS  запрещает  любую  динамическую  загрузку  кода  

•  Для  Java  возможен  либо  интерпретатор,  либо  AOT      

82

Page 83: AOT-компиляция Java

AOT  компиляторы  для  Java  

GCJ Excelsior JET Android ART RoboVM Avian CodeNameOne IBM J9 Java ME

83

Page 84: AOT-компиляция Java

84

Page 85: AOT-компиляция Java

Статическая  компиляция  Java    •  возможна  

–  с  сохранением  всех  возможностей  Java  –   даже  в  присутствии  нестандартных  загрузчиков  классов    

•  полезна    –  для  защиты  кода  –  быстрого  старта  –  лучшего  UX  –  улучшения  производительности  –  экономии  батарейки,  памяти,  диска  

Итоги  

85

Page 86: AOT-компиляция Java

Вопросы и ответы

Никита Липский, Excelsior

[email protected] twitter: @pjBooms

86

Page 87: AOT-компиляция Java

Ускорение  приложений  

87