GraalVM — Об этом уже нельзя молчать!

Вчера я листал Reddit и увидел, как чувак про Kubernetes написал — «супер сложная штука, которая решает непонятные мне проблемы». Так вот, если про k8s ещё можно так думать (хотя я не согласен с этим), то с GraalVM всё однозначно понятно. Это серьезный инженерный проект, который решает реальные проблемы бизнеса и инженеров.

Итак, краткое Интро, что же такое Грааль в мире Java (и не только). Это проект, который содержит в себе несколько независимых компонентов, каждый из которых, на самом деле, можно использовать отдельно, не зависимо от других частей системы.

Главное, что может быть интересно простому прикладному Java-разработчику, который гоняет JSON по своей системе из одного микросервиса в другой микросервис, попутно сохраняя это в Базу Данных — это JIT Compiler (он кстати написан на Java, в отличие от C1/C2, которые написаны на С/С++).

Почему Graal JIT компилятор интересен прикладному программисту? Всё очень просто. Запустив свой Jar-ник с парой новых ключей (-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler), вы нахялву получаете до 10% прироста производительности по сравнению с HotSpot реализацией JIT-компилятора. То есть, потратив минимум усилий, вы уже сейчас, используя Java 10, сможете получить бенифиты. В этой статейке на хабре, кажется, были Бенчмарки — https://habr.com/company/billing/blog/351682/.

Кстати говоря, почему так просто использовать новый JIT-компилятор? Всё дело в том, что в Java 9 были вынесены API для компиляции (JEP 243: Java-Level JVM Compiler Interface). Теперь кто угодно может писать свою реализацию компилятора, имлементируя те интерфейсы.

package jdk.vm.ci.runtime;

import jdk.vm.ci.code.CompilationRequest;
import jdk.vm.ci.code.CompilationRequestResult;

public interface JVMCICompiler {
    int INVOCATION_ENTRY_BCI = -1;

    CompilationRequestResult compileMethod(CompilationRequest request);
}

Другая важная часть проекта Graal — это Truffle. На самом деле, это относительно уникальный продукт, поэтому Трюфель категоризировать каким-либо способом довольно трудно. Самое простое описани Truffle, что видел я, это — фреймворк для написания парсеров новых языков программирования, которые хотят интегрироваться с Graal.

В этом месте, наверное, нужно лирическое отступление. Если с JIT-ом всё понятно — берём и используем, особо не думая, зачем это было сделано, то с остальными частями Грааля — так не выйдет. Уже нужно понимать общую концепцию происходящего.

Проше всего понять Graal можно с помощью одного из докладов сотрудников Oracle Labs (именно они этот продукт и делают), либо парней из Twitter — эта социальная сеть — самый большой пользователь Грааля в продакшене. На самом деле, это не связано с тем, что Twitter безумно верит в этот проект, или попросту доверяет Oracle. Причина полностью прагматична. Весь Твиттер, почти полностью, написан на Scala, которая… медленнее Java. А Грааль даёт Performance Boost на ровном месте.

Для лучшего понимания происходящего, я могу порекомнедовать новый Майский доклад от Developer advocate Грааля — Олега (наверное, это наш с вами соотечествненик в прошлом) — Run Code in Any Language Anywhere with GraalVM.

Давайте всё же кратко рассмотрим две вещи: зачем создавался Graal, и как на самом верхнем уровне работает набор компонентов Graal.

Рассмотрим современный мир. У нас есть Языки программирования (читай, frontend часть компиляторов), и платформы — виртуальные машины (в случае Java, C#, JavaScript и других), или попросту рантаймы/среды выполнения (как в Go, C/C++ и других). А ещё есть платформы, на которых работают Виртуальные машины — Linux, Windows, ARM, Spark. Короче говоря, Языки выполняются на Виртуальных машинах и Рантаймах, которые, в свою очередь, работают на физически разных платформах.

Написать свой Фронтенд Языка программирования (читай, придумать синтаксис) — это задача хоть и сложная, но, как признают создатели языков, это самое простое в разработке нового Языка Программирования. Не даром, только для JVM сделано больше 10 сколько-нибудь значемых языков программирования.

Сложная часть в разработки нового языка программирования — это Тулинг (IDE, дебаггеры, профайлеры, инструменты для тестирования, и другое), а также быстродействие платформы. Именно на эти вещи тратится основной бюджет создания своего языка.

Разработчики Graal решили подойти к процессу создания новых языков, как настоящие промышленные программисты. Были выделены части, которые можно переиспользовать. А для уникальных частей был разработан общий API.

GraalVM

Посмотрим на картинку. У нас есть Truffle API — вещь очень простая. Это API для построения парсера вашего нового языка программирования.

Ещё у нас есть GraalVM Runtime — абстрактная Виртуальная машина (да-да! это не реализация виртуальной машины, а лишь набор интерфейсов, которые должны быть реализованы конкретной Виртуальной машиной (или физической платформой), для того чтобы всё это дело запустилось).

Когда кто-то хочет сделать новый язык программирования, он попросту с помощью Truffle API описывает синтаксис своего языка. За финальный перфоманс — все возможные оптимизации, отвечают уже ребята из Oracle. Ведь вся оптимизация находится уже внутри проекта Graal.

Во всей этой истории я не упомянул ещё одну важную часть. Вы, наверное, уже слышали, что в Java появилась AOT компиляция. Причём, это не с помощью Excelsior JET — платной реализации JVM, а с помощью OpenJDK.

На картинке выше вы видите GraalVM Runtime, который находится над Оракловым HotSpot. Но, если вы внимательный читатель, вы могли заметить, что я сказал, что GraalVM Runtime — это лишь описание API виртуальной машшины, а не реализация. Так вот, в данном примере HotSpot непосредственно реализует это API. Там нужно реализовать свою работу с Потоками, свой GC, а также ряд других важных вещей. После этого, Язык программирования, использующий стек Graal, может запускаться на Оракловой виртуальной машине. Однако есть и другая реализация GraalVM Runtime.

Substrate VM — это альтернативная реализация GraalVM Runtime. В отличие от HotSpot, Substrate не тянет вместе с собой зависимость на JVM. Программа, использующая эту реализацию Грааля, будет скомпилирована в исполняемый бинарник — это как раз и есть новая реализация AOT компиляции.

Конечно же, в Substrate есть ряд вещей, о которых важно знать. Во-первых, пока это не production ready. Возможны corner cases, на которых AOT компиляция не сработает. Кроме того, в Substrate своя реализация Сборщика Мусора (тут ведь нет нашей JVM). Поэтому, если ваше приложение активно работает с памятью, возможны просадки по производительности и другие сайд-эффекты.

В общем, пора закгругляться. Graal — это набор компонент — JIT-компилятор, Api для реализации парсеров языков (Truffle), Абстрактная виртуальная машина (GraalVM Runtime), главная цель которых — сделать разработку новых языков дешевой и простой, а также ускорить работу современных языков программирования за счёт применения существующих оптимизаций в Хотспоте. Это очень правильная архитектурная идея, в которую я верю. Надеюсь, у Oracle Labs всё получится, и мы будем иметь zero cost интероп между JavaScript, Python, R, Java, шаря весь код наших полиглотных проектов.

Категории: Программирование