java ahead-of-time compilation

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

Upload: nikita-lipsky

Post on 04-Jun-2015

716 views

Category:

Presentations & Public Speaking


2 download

DESCRIPTION

Presentation at #JavaDayKiev and #Jokerconf

TRANSCRIPT

Page 1: Java Ahead-Of-Time compilation

1

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

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

Excelsior

Page 2: Java Ahead-Of-Time compilation

2

Давным давно

Page 3: Java Ahead-Of-Time compilation

3

Давным давно,

Во времена С+++ ++++++

Page 4: Java Ahead-Of-Time compilation

4

Давным давно,

Во времена С+++, Все компиляторы были статические ++++++

Page 5: Java Ahead-Of-Time compilation

5

Пока не появилась..

Page 6: Java Ahead-Of-Time compilation

6

Пока не появилась

Java

Page 7: Java Ahead-Of-Time compilation

7

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

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

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

Page 8: Java Ahead-Of-Time compilation

8

Трансляция Java to Native

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

программы

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

программы

Page 9: Java Ahead-Of-Time compilation

9

Page 10: Java Ahead-Of-Time compilation

10

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

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

называться Java?• Зачем это нужно?

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

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

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

Page 11: Java Ahead-Of-Time compilation

11

Page 12: Java Ahead-Of-Time compilation

12

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

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

Page 13: Java Ahead-Of-Time compilation

13

Мифы вокруг статической компиляции Java

Page 14: Java Ahead-Of-Time compilation

14

• Reflection

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

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

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

Page 15: Java Ahead-Of-Time compilation

15

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

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

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

Page 16: Java Ahead-Of-Time compilation

16

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

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

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

Page 17: Java Ahead-Of-Time compilation

17

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

“Javа худеет”: http://www.youtube.com/watch?v=CKWlp8UQQb4

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

Page 18: Java Ahead-Of-Time compilation

18

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

Page 19: Java Ahead-Of-Time compilation

19

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

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

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

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

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

Page 20: Java Ahead-Of-Time compilation

20

Как компилировать статически?• Компилировать каждый класс изолировано

от других– Плохо для производительности

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

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

Page 21: Java Ahead-Of-Time compilation

21

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

Classes

Classes

Page 22: Java Ahead-Of-Time compilation

22

Classes

CL1CL2CL3

CL4

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

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

Page 23: Java Ahead-Of-Time compilation

23

• CL4• CL3

• CL2• CL1

classes classes

classesclasses

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

Page 24: Java Ahead-Of-Time compilation

24

• CL4• CL3

• CL2• CL1

classesclasses

classesclasses

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

Page 25: Java Ahead-Of-Time compilation

25

• CL4• CL3

• CL2• CL1

classes classes

classesclasses

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

Page 26: Java Ahead-Of-Time compilation

26

– Картинка

• CL4• CL3

• CL2• CL1

classes classes

classes

classes

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

Page 27: Java Ahead-Of-Time compilation

27

• CL4• CL3

• CL2• CL1

classes classes

clas

sesclasses

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

Page 28: Java Ahead-Of-Time compilation

28

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

компиляторе:– Определяет, какие загрузчики будут созданы

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

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

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

Page 29: Java Ahead-Of-Time compilation

29

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

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

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

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

Page 30: Java Ahead-Of-Time compilation

30

Зачем AOT для Java?

Page 31: Java Ahead-Of-Time compilation

31

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

Page 32: Java Ahead-Of-Time compilation

32

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

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

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

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

Page 33: Java Ahead-Of-Time compilation

33

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

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

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

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

Page 34: Java Ahead-Of-Time compilation

34

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

Page 35: Java Ahead-Of-Time compilation

35

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

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

библиотек (dll, so)

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

Page 36: Java Ahead-Of-Time compilation

36

Java Quick Start

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

Page 37: Java Ahead-Of-Time compilation

37

AOT быстрее?

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

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

Page 38: Java Ahead-Of-Time compilation

38

AOT быстрее!

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

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

Page 39: Java Ahead-Of-Time compilation

39

Page 40: Java Ahead-Of-Time compilation

40

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

Page 41: Java Ahead-Of-Time compilation

41

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

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

Page 42: Java Ahead-Of-Time compilation

42

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

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

Page 43: Java Ahead-Of-Time compilation

43

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

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

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

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

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

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

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

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

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

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

Page 44: Java Ahead-Of-Time compilation

44

Java – ООП

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

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

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

Page 45: Java Ahead-Of-Time compilation

45

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

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

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

• Inline caches

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

Page 46: Java Ahead-Of-Time compilation

46

A a;…

a.foo();

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

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

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

Page 47: Java Ahead-Of-Time compilation

47

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

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

Page 48: Java Ahead-Of-Time compilation

48

A a = b? new B() : new C();a.foo();

Если foo() в B и С один и тоже, то

a.foo() невиртуальный вызов (можно инлайнить)

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

Page 49: Java Ahead-Of-Time compilation

49

A a = b? bar() : baz();…a.foo();

Если bar() возвращает только new B, а baz() экземпляры new С, то

a.foo() - опять невиртуальный вызов (можно инлайнить)

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

Page 50: Java Ahead-Of-Time compilation

50

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

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

Page 51: Java Ahead-Of-Time compilation

51

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

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

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

Page 52: Java Ahead-Of-Time compilation

52

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

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

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

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

Page 53: Java Ahead-Of-Time compilation

53

   

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

Пример

Page 54: Java Ahead-Of-Time compilation

54

   

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

Пример

Page 55: Java Ahead-Of-Time compilation

55

   

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

Пример

Page 56: Java Ahead-Of-Time compilation

56

   

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

Пример

Page 57: Java Ahead-Of-Time compilation

57

    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);    }   }

Пример

Page 58: Java Ahead-Of-Time compilation

58

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);    }   }

Пример

Page 59: Java Ahead-Of-Time compilation

59

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

Пример

Page 60: Java Ahead-Of-Time compilation

60

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

Пример

Page 61: Java Ahead-Of-Time compilation

61

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

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

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

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

Page 62: Java Ahead-Of-Time compilation

62

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

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

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

Page 63: Java Ahead-Of-Time compilation

63

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

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

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

Page 64: Java Ahead-Of-Time compilation

64

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

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

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

Page 65: Java Ahead-Of-Time compilation

65

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

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

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

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

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

Page 66: Java Ahead-Of-Time compilation

66

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

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

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

Page 67: Java Ahead-Of-Time compilation

67

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

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

Page 68: Java Ahead-Of-Time compilation

68

Server side

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

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

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

Page 69: Java Ahead-Of-Time compilation

69

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

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

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

Page 70: Java Ahead-Of-Time compilation

70

Embedded

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

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

Page 71: Java Ahead-Of-Time compilation

71

Mobile

• JVM on Mobile:

Page 72: Java Ahead-Of-Time compilation

72

Mobile

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

Page 73: Java Ahead-Of-Time compilation

73

Mobile

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

Page 74: Java Ahead-Of-Time compilation

74

Mobile

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

Page 75: Java Ahead-Of-Time compilation

75

Mobile

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

Page 76: Java Ahead-Of-Time compilation

76

Mobile

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

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

Page 77: Java Ahead-Of-Time compilation

77

Mobile

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

Зарядки!

Page 78: Java Ahead-Of-Time compilation

78

Mobile

• У беспроводных устройств есть БАТАРЕЙКА

• Стоит ли ее тратить на динамическую компиляцию?

Page 79: Java Ahead-Of-Time compilation

79

iOS

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

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

Page 80: Java Ahead-Of-Time compilation

80

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

GCJ

Excelsior JET

Android ART

RoboVM

Avian

CodeNameOne

IBM J9

Java ME

Page 81: Java Ahead-Of-Time compilation

81

Page 82: Java Ahead-Of-Time compilation

82

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

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

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

Итоги

Page 83: Java Ahead-Of-Time compilation

83

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

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

[email protected]: @pjBooms

Page 84: Java Ahead-Of-Time compilation

84

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