O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

AOT для Java: Мифы и Challenges

Языку Java присущ встроенный динамизм.
Reflection, динамическая загрузка — это то, без чего современные Java приложения просто не могут существовать, поэтому существует мнение, что AOT (статическая) компиляция вряд ли применима к Java в общем случае, а там где применима не может составить конкуренцию JIT (динамической) компиляции в плане прозводительности.
В этом докладе показывается почему это не (совсем) так, при этом рассматриваются случаи,
где у статических компиляторов действительно есть определенные сложности в обработке динамической семантики Java.
Также упоминается, где статическая компиляции для Java может быть полезна.

Livros relacionados

Gratuito durante 30 dias do Scribd

Ver tudo

Audiolivros relacionados

Gratuito durante 30 dias do Scribd

Ver tudo
  • Seja o primeiro a comentar

AOT для Java: Мифы и Challenges

  1. 1. AOT для Java Мифы и Challenges 1 Никита Липский Excelsior
  2. 2. Äàâíûì äàâíî, Âî âðåìåíà Ñ+++, Âñå êîìïèëÿòîðû áûëè ñòàòè÷åñêèå ++++++ 2
  3. 3. Äàâíûì äàâíî, Âî âðåìåíà Ñ+++, Âñå êîìïèëÿòîðû áûëè ñòàòè÷åñêèå ++++++ 3
  4. 4. Äàâíûì äàâíî, Âî âðåìåíà Ñ+++, Âñå êîìïèëÿòîðû áûëè ñòàòè÷åñêèå ++++++ 4
  5. 5. Ïîêà íå ïîÿâèëàñü.. 5
  6. 6. Ïîêà íå ïîÿâèëàñü Java 6
  7. 7. •  Интерпретация •  Компиляция в машинный код и исполнение на “железе” Исполнение Java байткода JVM 7
  8. 8. Трансляция Java to NaIve •  Динамическая (Just-In-Time – JIT). –  Трансляция происходит во время исполнения программы •  Статическая (Ahead-Of-Time – AOT) –  Трансляция происходит до исполнения программы 8
  9. 9. 9
  10. 10. План доклада •  Мифы вокруг статической компиляции Java •  Java AOT Challenges •  Применение AOT для ускорения startup, защиты приложений от декомпиляции. •  Производительность •  AOT в разных областях применения Java –  client side, server side, embedded, IOT, mobile. 10
  11. 11. 11
  12. 12. Кому нужен AOT для Java? 12 Кто знает про Excelsior JET?Кто знает про Excelsior JET?
  13. 13. Мифы вокруг статической компиляции Java 13
  14. 14. Миф 1. Java - «слишком» динамическая ReflecIon Динамическая загрузка 14
  15. 15. Миф 2. AOT компиляция – убийца WORA WORA Write Once Run Anywhere BORA Build Once Run Anywhere 15 !=
  16. 16. Миф 3. AOT = маленький Exe ”Я получу (маленький) исполняемый файл, который будет работать без JVM (как в С)” Но: – Стандартные классы? –  GC, reflecron? 16
  17. 17. Миф 3. AOT = маленький Exe Тем не менее, используя AOT, можно получить дистрибутив Java приложения без зависимостей от Java значительно меньший, чем размер JRE: “Javа худеет”: htps://www.youtube.com/results?search_query=javaday+худеет 17
  18. 18. Java «слишком» динамическая 18
  19. 19. Нестандартные загрузчики классов •  Переопределяют умолчательную логику разрешений ссылок между классами •  Уникальное пространство имен •  Позволяют управлять зависимостями, решая проблемы JAR hell (OSGi, Java Module System) •  Java EE сервера, Eclipse RCP, плагины 19
  20. 20. Нестандартные загрузчики классов Как компилировать статически? •  Компилировать каждый класс изолировано от других –  Плохо для производительности •  Изучить логику разрешения ссылок для популярных загрузчиков –  Не работает для произвольных загрузчиков 20
  21. 21. Нестандартные загрузчики классов 21 Classes Classe s Classes
  22. 22. Classes CL1 CL2 CL3 CL4 Нестандартные загрузчики классов 22CLi: class loader
  23. 23. • CL4 • CL3 • CL2 • CL1 classes classes classes classes Нестандартные загрузчики классов 23
  24. 24. • CL4 • CL3 • CL2 • CL1 classes classes classes classes Нестандартные загрузчики классов 24
  25. 25. • CL4 • CL3 • CL2 • CL1 classes classes classes classes Нестандартные загрузчики классов 25
  26. 26. Нестандартные загрузчики классов 26 • CL4 • CL3 • CL2 • CL1 classes classes classes
  27. 27. • CL4 • CL3 • CL2 • CL1 classes classes Нестандартные загрузчики классов 27
  28. 28. Нестандартные загрузчики классов Схема поддержки загрузчиков в AOT: •  Компонента разрешения ссылок в AOT компиляторе: –  Определяет, какие загрузчики будут созданы во время исполнения и назначает каждому статический ID –  Разбивает классы приложения по загрузчикам –  Разрешает ссылки между классами 28
  29. 29. Нестандартные загрузчики классов Схема поддержки загрузчиков в AOT: •  Во время исполнения: –  По экземпляру загрузчика вычисляется ID –  Имея статический ID, мы можем грузить статически скомпилированные классы: •  создание экземпляра класса java.lang.Class •  наполнение его рефлективной информацией •  загрузка кода осуществляется OS 29
  30. 30. Нестандартные загрузчики классов Схема поддержки загрузчиков в AOT: •  Во время исполнения: –  По экземпляру загрузчика вычисляется ID –  Имея статический ID, мы можем грузить статически скомпилированные классы: Как минимум работает для Eclipse RCP и Web приложений на базе Tomcat 30
  31. 31. Зачем AOT для Java? 31
  32. 32. Защита кода от декомпиляции 32
  33. 33. Защита кода приложения •  Java bytecode легко превращается в исходный код •  Процесс обфускации при активном использовании reflecron трудоемок и трудно поддерживаем •  Даже по обфусцированному коду часто можно понять, что код делает –  ссылки на JDK остаются в неизменном виде 33
  34. 34. Защита кода приложения •  Машинный код можно только эффективно дизассемблировать •  По дизассемблированному коду не понять структуру приложения (нет имен классов, методов) •  После агрессивной оптимизации машинный код далек от оригинального кода 34
  35. 35. Время старта приложения 35
  36. 36. Холодный старт vs теплый Во второй раз приложение стартует значительно быстрее, чем в первый –  Загрузка кода и данных приложения с диска –  Загрузка системных и сторонних динамических библиотек (dll, so) 36
  37. 37. Java Quick Start •  Java Quick Start –  Предзагружает rt.jar, динамические библиотеки 37
  38. 38. AOT быстрее? •  Машинный код “толще” Java bytecode •  Загрузка кода с диска занимает больше времени, чем его начальное исполнение 38
  39. 39. AOT быстрее! •  Код исполняемый на старте – в начало исполняемого файла •  Можно предзагружать стартовый сегмент последовательным чтением 39
  40. 40. 40
  41. 41. Производительность 41
  42. 42. Миф 4. AOT быстрее “Скомпилировав Java статически, мы получим скорость приложения как в C, C быстрее Java, следовательно AOT быстрее” 42
  43. 43. Миф 5. JIT быстрее “Эффективно оптимизировать Java приложения можно только на основе динамического профиля исполнения” 43
  44. 44. Виды оптимизаций –  Протяжка констант –  Удаление избыточного кода –  Удаление общих подвыражений –  Открытая подстановка –  Специализация методов –  Развертывание циклов –  Версионирование циклов –  Вынос инвариантов –  Удаление хвостовой рекурсии –  Девиртуализация вызовов –  Аллокация объектов на стэке и их взрыв –  Удаление проверок времени исполнения –  Удаление избыточной синхронизации –  Оптимальная выборка кода и свертка шаблонов –  Планировка инструкций –  Оптимальное распределение регистров 44
  45. 45. Java – ООП • Много методов • Методы маленькие (get/set) • Методы по умолчанию ВИРТУАЛЬНЫЕ 45
  46. 46. Девиртуализация вызовов •  Предусловие дальнейшей открытой подстановки (inline) •  Анализ иерархии классов –  метод не перегружается – невиртуальный •  Типовый анализ –  new T().foo(); //вызов foo() // невиртуальный •  Profile guided 46
  47. 47. A a; … è a.foo(); if (RT_Type(a) in CHA) { inlined body of foo() } else { a.foo(); } Идея: метод не перегружается – невиртуальный Анализ иерархии классов (CHA) 47
  48. 48. Формальный vs фактический тип A a; //A – формальный тип Если A – формальный тип переменой a, то во время исполнения в a могут находится значения типа наследника A. Такие типы называются фактическими. A a = new B(); //B – фактический тип Источником фактических типов для статического анализа являются операторы new. 48
  49. 49. Типовый анализ Идея: new A().foo(); //невиртуальный вызов 49
  50. 50. Типовый анализ A a = b? new B() : new C(); a.foo(); Если foo() в B и С один и тоже, то a.foo() невиртуальный вызов (можно инлайнить) 50
  51. 51. Типовый анализ A a = b? bar() : baz(); … a.foo(); Если bar() возвращает только new B, а baz() экземпляры new С, то a.foo() - опять невиртуальный вызов (можно инлайнить) 51
  52. 52. Типовый анализ Откуда мы знаем, что возвращает bar() и baz()? 52
  53. 53. Глобальный анализ •  Глобальный анализ – анализирует все методы программы, вычисляя про каждый метод полезную информацию •  Результаты глобального анализа используются для оптимизации конкретного метода 53
  54. 54. Аллокация объектов на стэке •  Все Java объекты создаются в динамической памяти – Java heap (куча) •  Большинство объектов временные •  Хочется их размещать на стэке метода Escape анализ (анализ утечек) – определяет утекает ли объект в разделяемую память. 54
  55. 55. Пример for (Object o: getCollection()) { doSomething(o); } 55
  56. 56. Пример Iterator iter = getCollection().iterator(); while (iter.hasNext()) { Object o = iter.next(); doSomething(o); } 56
  57. 57. Пример Допустим анализ показал, что getCollection() всегда возвращает экземпляр ArrayList ArrayList list = getCollection(); Iterator iter = list.iterator(); while (iter.hasNext()) { Object o = iter.next(); doSomething(o); } 57
  58. 58. Пример ArrayList list = getCollection(); ArrayList.ListItr iter = new ListItr(list); while (iter.hasNext()) { Object o = iter.next(); doSomething(o); } 58
  59. 59. Пример 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); } 59
  60. 60. Пример 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); } 60
  61. 61. Пример ArrayList list = getCollection(); int cursor = 0; int size = list.elemData.length; while (cursor < size) { Object o = list.elemData[cursor++]; doSomething(o); } 61
  62. 62. Пример ArrayList list = getCollection(); int size = list.elemData.length; for (int i = 0; i < size; i++) { doSomething(list.elemData[i]); } 62
  63. 63. •  Часто бывают довольно сложными •  Требуют итеративного пересчета •  Глобальный анализ зависит от ВСЕЙ программы. Все ли это может себе позволить JIT? Анализ и оптимизации 63
  64. 64. •  Часто бывают довольно сложными •  Требуют итеративного пересчета •  Глобальный анализ зависит от ВСЕЙ программы. Все ли это может себе позволить JIT? Анализ и оптимизации 64
  65. 65. •  Часто бывают довольно сложными •  Требуют итеративного пересчета •  Глобальный анализ зависит от ВСЕЙ программы. Все ли это может себе позволить JIT? Анализ и оптимизации 65
  66. 66. Динамические оптимизации •  Профилировка и селективная компиляция •  Открытая подстановка на основе профиля исполнения •  Оптимизация трасс исполнения •  Выбор оптимальных инструкций 66
  67. 67. Горячий код vs теплый Q: А что будет, если у приложения нет ярко выраженного горячего кода? A: Долгий прогрев, результаты прогрева не используются при дальнейших стартах приложения Типичный случай: UI приложения 67
  68. 68. 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
  69. 69. 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
  70. 70. Динамические оптимизации Может ли статический компилятор использовать динамический профиль исполнения? 70
  71. 71. Server side •  Процессорное время в облаках – дорого •  Через некоторое время работы сервера профиль исполнения стабилизируется •  Почему этот профиль не передать статическому компилятору? 71
  72. 72. AOT on the Server side •  Стабильная производительность, предсказуемая latency –  нет деоптимизаций во время исполнения •  Нет прогрева, работает в полную силу прямо со старта –  Хорошо для load balancing •  Лучшее время старта –  хорошо, когда много серверов стартует одновременно •  Все еще защищает от декомпиляции 72
  73. 73. Embedded •  Чем слабее железо, тем дороже динамическая компиляция •  Встроенные системы часто не обладают теми же вычислительными мощностями, что и настольные компьютеры/сервера 73
  74. 74. Mobile •  JVM on Mobile: 74
  75. 75. Mobile •  JVM on Mobile: – Платформенные классы 75
  76. 76. Mobile •  JVM on Mobile: – Платформенные классы – GC и Memory Manager 76
  77. 77. Mobile •  JVM on Mobile: – Платформенные классы – GC и Memory Manager – Reflecron 77
  78. 78. Mobile •  JVM on Mobile: – Платформенные классы – GC и Memory Manager – Reflecron – JIT 78
  79. 79. Mobile •  JVM on Mobile: –  Платформенные классы –  GC и Memory Manager –  Reflecron –  JIT Чего не хватает? 79
  80. 80. Mobile •  JVM on Mobile: –  Платформенные классы –  GC и Memory Manager –  Reflecron –  JIT Зарядки! 80
  81. 81. Mobile •  У беспроводных устройств есть БАТАРЕЙКА •  Стоит ли ее тратить на динамическую компиляцию? 81
  82. 82. iOS •  Политика распространения приложений на iOS запрещает любую динамическую загрузку кода •  Для Java возможен либо интерпретатор, либо AOT 82
  83. 83. AOT Java Compilers in 2000 Desktop/Server: BulletTrain Excelsior JET GNU Compiler for Java (GCJ) IBM VisualAge for Java Supercede/JOVE TowerJ Embedded/Mobile: Diab FastJ Esmertec Jbed ME GCJ IBM J9 Sun Java ME (custom offerings) 83
  84. 84. AOT Java Compilers in 2017 Desktop/Server: Excelsior JET GCJ (RIP) IBM Java SDK for AIX IBM Java SDK for z/OS Coming soon: HotSpot AOT (JEP-295) Embedded/Mobile: Excelsior JET Embedded IBM WebSphere Real Time Oracle Java ME Embedded Client Codename One Avian Android ART RoboVM (RIP) Mulr-OS Engine 84
  85. 85. AOT Java Compilers in 2017 Desktop/Server: Excelsior JET GCJ (RIP) IBM Java SDK for AIX IBM Java SDK for z/OS Coming soon: HotSpot AOT (JEP-295) Embedded/Mobile: Excelsior JET Embedded IBM WebSphere Real Time Oracle Java ME Embedded Client Codename One Avian Android ART RoboVM (RIP) Mulr-OS Engine 85
  86. 86. Статическая компиляция Java приложений: 86 Возможна
  87. 87. Статическая компиляция Java приложений: 87 Возможна С сохранением всех Java фич Полезна по многим причинам
  88. 88. Статическая компиляция Java приложений: 88 Возможна С сохранением всех Java фич Полезна по многим причинам
  89. 89. Вопросы и ответы Никита Липский, Excelsior nlipsky@excelsior-usa.com twitter: @pjBooms 89
  90. 90. Ускорение приложений 90

    Seja o primeiro a comentar

    Entre para ver os comentários

  • OlegNenashev

    May. 23, 2017

Языку Java присущ встроенный динамизм. Reflection, динамическая загрузка — это то, без чего современные Java приложения просто не могут существовать, поэтому существует мнение, что AOT (статическая) компиляция вряд ли применима к Java в общем случае, а там где применима не может составить конкуренцию JIT (динамической) компиляции в плане прозводительности. В этом докладе показывается почему это не (совсем) так, при этом рассматриваются случаи, где у статических компиляторов действительно есть определенные сложности в обработке динамической семантики Java. Также упоминается, где статическая компиляции для Java может быть полезна.

Vistos

Vistos totais

784

No Slideshare

0

De incorporações

0

Número de incorporações

1

Ações

Baixados

5

Compartilhados

0

Comentários

0

Curtir

1

×