48
Excelsior JET в действии Никита Липский Павел Павлов Excelsior

Excelsior JET в действии

Embed Size (px)

DESCRIPTION

Презентация со встречи на jug.ru -- http://jugru.timepad.ru/event/83954/

Citation preview

Excelsior JET в действии

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

Павел Павлов

Excelsior

История

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

Про Excelsior JET? • Полная реализация Java SE

– первый релиз 2000 год

– c 2005 года cертифицирована как Java Compatible

• AOT compiler + Java Runtime – смешанная компиляция: AOT + JIT

– поддержка нестандартных загрузчиков классов в AOT режиме (для Eclipse RCP, Tomcat)

• Toolkit – Startup Optimizer

– Deployment

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

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

Для чего Excelsior JET?

• Ускорение приложений без переписывания

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

• Распространение приложений без зависимостей в компактном и привычном для конечного пользователя виде

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

компиляции Java

Миф 1.

Java - динамическая

• Reflection

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

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

Миф 2. Машинный код –

убийца WORA

WORA: Write Once Run Anywhere

(пиши раз, исполняй везде)

!= BORA: Build Once?

(собирай раз??? …)

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

Динамический профиль исполнения

РУЛИТ!

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

Машинный код со старта

РУЛИТ!

Ключевые возможности

Excelsior JET

Защита приложений

• Декомпиляция настолько же сложна как для программ,

написанных на C/C++

• На выходе реальный машинный код без символов (невозможно

понять даже структуру приложения)

• Нет 1-1 соответствия между оригинальным байт-кодом и

результирующим машинным кодом

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

подстановки и других оптимизаций, результирующий код далек

от оригинального

• Есть возможность закриптовать ресурсы и reflection программы

(не видны простым просмотром)

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

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

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

теплый

Во второй раз приложение стартует

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

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

диска

– Загрузка системных и сторонних

динамических библиотек (dll, so)

AOT быстрее?

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

• Загрузка кода с диска занимает

больше времени, чем его начальное

исполнение

AOT быстрее!

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

«экзешника»

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

сегмент последовательным чтением

Пользовательские

загрузчики классов

Пользовательские

загрузчики классов • Если AOT компилятор знает логику загрузки

определенного загрузчика, он может классы,

загружаемые этим загрузчиком компилировать до

исполнения

• Eclipse RCP

• Tomcat

Excelsior JET Global Optimizer

• Глобально оптимизированный

исполняемый файл – «нужные» классы приложения и Java

платформы оптимизируются совместно

• Оставшиеся классы – не удаляются

– остается возможность загружать их через

JIT

Java Runtime Slim-Down

• Java SE API делится на

компоненты: – Kernel, XML, SQL, CORBA, AWT/Java2D,

Swing, etc.

• анализатор определяет какие

компоненты “нужны” – содержат достижимые методы

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

Application

Java SE API

Entry points - used

- not used

- component’s boundary

Java Runtime Slim-Down

• Пользователю предоставляются: – результаты анализа c возможностью

исключить неиспользуемые компоненты

Java Runtime Slim-Down

• Исключенные компоненты: – помещаются на веб-сервер (доступны

приложению)

– загружаются VM по требованию

• Соответствует Java SE

спецификации!

Внутренняя архитектура

Excelsior JET

• Оптимизирующий AOT компилятор

– Высокоуровненвый оптимизатор (анализатор типов, утечек (escape), открытые подстановки и т.п.)

– Глобальный оптимизатор

– SSA оптимизатор

– Низкоуровневый оптимизатор

• Excelsior JET Runtime – Memory Manager

– GC

– JIT

– Прочее (JNI, Refection, InDy, файлуха, и.т.п.)

Компоненты Excelsior

JET JVM

– Протяжка констант

– Удаление избыточного кода

– Удаление общих подвыражений

– Открытая подстановка

– Специализация методов

– Развертывание циклов

– Версионирование циклов

– Вынос инвариантов

– Удаление хвостовой рекурсии

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

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

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

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

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

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

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

Оптимизации

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

Анализ потока данных

• Протяжка констант

• Удаление общих подвыражений

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

• И многое другое

Java – ООП

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

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

• Методы по умолчанию

ВИРТУАЛЬНЫЕ

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

вызовов

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

подстановки (inline)

• Анализ иерархии классов

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

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

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

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

на стэке

• Все Java объекты создаются в динамической

памяти – Java heap (куча)

• Большинство объектов временные

• Хочется их размещать на стэке метода

• Escape анализ (анализ утечек) –

определяет утекает ли объект в

разделяемую память.

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

• Типовый и Escape анализы боятся

вызовов, особенно виртуальных.

• Глобальный анализ – анализирует все

методы программы, в частности

уточняя типовый и escapе анализы.

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

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

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

• Глобальный анализ зависит от ВСЕЙ

программы.

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

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

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

• Глобальный анализ зависит от ВСЕЙ

программы.

Все ли это может

себе позволить JIT?

Динамические

оптимизации

Может ли статический компилятор

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

исполнения?

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

• А что будет, если у приложения нет

ярко выраженного горячего кода?

• Долгий прогрев, результаты прогрева

не используются при дальнейших

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

Excelsior JET Runtime

Memory Manager

• Не непрерывная структура хипа (блок – 16 КB)

– Позволяет не только брать память, но и

отдавать

• Специализированные аллокаторы

– Маленькие объекты

– Средние объекты

– Большие объекты

– Ключевые объекты (граф объектов умирает

одновременно, в большинстве случаев)

GC

• Адаптивная сборка мусора – GC старается жить в том пространстве свободной памяти,

что есть (maxheap – это только барьер за который нельзя

заходить)

– Может не только потреблять память, но и отдавать, если

память не нужна

– Пытается ужиться с другими процессами запущенными на

машине

– Наблюдает не только за Java кучей, но и за потреблением

памяти в нативном коде

– Можно выставить gc ratio (хинт GC, говорящий сколько

может потратить GC времени в сравнении с самим

приложением)

Parallel Concurrent Incremental

Mark Compact GC

• Алгоритм из класса трассирующих.

• Parallel – исполняется на нескольких процессорах во

время остановки мира

• Concurrent – делает часть работы во время исполнения

– foreground (потоки приложения занимаются сборкой мусора)

– background (в фоновом потоке)

• Incremental – не обходит все объекты каждый цикл

• Mark-Compact – решает компактизировать ли кучу

– делает это в «плановом порядке», а не «когда уже приперло»

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

– фрагментация кучи < 5% (чаще всего)

JIT + AOT модель исполнения

• Reflective shield: незарезолванные ссылки во время

AOT компиляции превращаются в специальный код

(рефлективные стабы), который может резолваться

во время исполнения.

• JIT и AOT порождают одни и те же ран-тайм

структуры.

• JIT и AOT имеют общий код

Планы

• Java 7 и Linux AMD64 (декабрь 2013)

• Mac OSX (май 2014)

• Java 8, Linux ARM, compact profiles

• iOS

• Android

Вопросы и

ответы

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

Павел Павлов

Excelsior

Компиляторный Hard Core