GraalVM (1): Введение в GaalVM

JVM

Что такое GraalVM

GraalVM, также разработанный Oracle, представляет собой полнофункциональную виртуальную машину с несколькими языками, улучшенную для HotSpot. Виртуальная машина с полным стеком означает, что ее можно использовать в качестве работающей платформы для большинства языков (включая Java, Scala, Groovy, Kotlin, JavaScript, Ruby, Python, C, C++ и т. д.). Он также может компилировать многоязычные смешанные программы разработки (интерфейсы или методы на разных языках смешиваются с другими языками и т. д.). Для Java, поскольку он разработан на базе HotSpot, его можно использовать как виртуальную машину, полностью соответствующую стандартам Java. Разница только в компиляторе «точно в срок»: замените встроенный C2 HotSpot на Graal (изучите знания о компиляции «точно в срок» самостоятельно).

Компилятор Graal

Ядром GraalVM является компилятор Graal, превосходный JIT-компилятор. Его можно использовать либо как JIT-компилятор, либо как опережающий статический компилятор.

Graal также написан на языке Java (JVMCI).Он поддерживает все распространенные оптимизации компилятора, а также поддерживает более сложные оптимизации (частичный анализ экранирования, оптимизация радикального прогнозирования и т. д.) Начиная с JDK10, HotSpot также представил Graal. В основном как замена C2, по сравнению с C2, он использует преимущества C2, отказывается от недостатков C2 и превосходит C2 с точки зрения ремонтопригодности и масштабируемости (C2 настолько сложен, что даже первоначальный автор Клифф неохотно поддерживает его). снова). Однако Graal все еще находится в экспериментальной стадии, по умолчанию он не включен, и его необходимо активировать с помощью параметров.

Truffle

Truffle — еще один ключевой компонент GraalVM. Это среда реализации языка программирования. Он предоставляет набор API-интерфейсов, которые можно использовать для реализации интерпретатора AST для языка и оптимизировать с помощью компилятора Graal. В настоящее время большинство языковых интерпретаторов реализованы Oracle, как видно из рисунка выше: JS, Ruby, R, Python, Sulong (Sulong — интерпретатор для LLVM IR). Также есть много людей, которые реализовали интерпретаторы для других языков и выложили их на Github.

Суть Truffle в том, что все языки используют единый протокол для разработки соответствующих интерпретаторов, а это значит, что все интерпретаторы могут оперировать объектами на разных языках программирования через единый протокол во время выполнения. Весь код, написанный на разных языках или в миксе, одинаков во время выполнения. Программы, написанные на разных языках или на нескольких языках, можно оптимизировать так же, как и обычный код, без каких-либо дополнительных затрат.

Это означает, что при разработке на Java вы обнаружите, что Python имеет очень полезную библиотеку, а Java — нет. В настоящее время вам не нужно снова использовать Java для реализации библиотеки Pyhton, вы можете напрямую вызывать библиотеку Python в коде Java.

Еще одним преимуществом является то, что, поскольку все языки кажутся одинаковыми во время выполнения, это означает, что инструменты также могут быть многоязычными, например, использовать VisualVM для анализа использования памяти JavaScript и т. д.

Substrate VM

SubstrateVM — это среда компиляции AOT (Ahead-Of-Time) для GraalVM. AOT означает предварительную компиляцию.В отличие от JIT-компиляции, AOT преобразует байт-код в машинный код перед запуском программы, который может быть напрямую скомпилирован в исполняемые файлы (локальные образы) или общие библиотеки, которые могут работать независимо.

SubstrateVM предназначен для обеспечения среды выполнения Java с высокой производительностью при запуске, низкими затратами памяти и полной интеграцией с кодом C. SubtrateVM полностью находится вне виртуальной машины HotSpot и имеет независимую среду выполнения, включая обработку исключений, синхронизацию, управление потоками, управление памятью (сборку мусора) и компоненты JNI.

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

native image generator

Содержит логику компиляции AOT. Это сама программа Java, которая будет использовать компилятор Graal для компиляции файлов классов Java в исполняемые файлы или библиотеки динамической компоновки.

Перед компиляцией собственный генератор изображений будет использовать анализ указателей (анализ точек на), начиная с записи программы, предоставленной пользователем, для изучения всего доступного кода. Во время исследования он также выполнит код инициализации и сохранит инициализированную кучу в моментальный снимок кучи, когда исполняемый файл будет окончательно сгенерирован. Таким образом, SubstrateVM запустится прямо из целевой программы, не повторяя инициализацию виртуальной машины Java.

Среда выполнения SubstrateVM

Упрощенная среда выполнения HotSpot, в которой запускаются целевые программы, скомпилированные с помощью AOT.

У SubstrateVM очень мало времени запуска и накладных расходов на память, а поскольку он компилируется заранее, программа может получить хорошую производительность сразу после запуска (пик производительности может быть хуже, чем у JIT, но стабильность будет лучше).

Но у него также есть много проблем в настоящее время:

  • Очевидно, что он больше не может работать по принципу «Напиши один раз, беги везде».
  • Механизм отражения Java динамически вызывает API во время выполнения, но очевидно, что невозможно узнать, какие интерфейсы вызываются во время компиляции, когда программа не запущена. Он требует, чтобы разработчики явно сообщали GaalVM, какой код может быть вызван отражением (в виде конфигурационных файлов JSON), что отвратительно и в принципе невозможно.
  • Поскольку локальный образ не запускается на HotSpot, все внутренние интерфейсы самой виртуальной машины HotSpot (JVMTI, JVMCI и т. д.) больше не существуют. Многие средства отладки Агента недоступны, кошмар!

В нашей текущей микросервисной архитектуре локальное зеркалирование намного проще в использовании, чем полная среда JVM + приложение, со стабильной производительностью, чрезвычайно быстрым временем запуска и меньшим потреблением ресурсов. Но предпосылка состоит в том, чтобы быть в состоянии решить вышеупомянутый камень преткновения.

Spring Graal Native

Как мы упоминали выше, ядром GraalVM также является функция, наиболее подходящая для нашей текущей микросервисной архитектуры: локальное зеркалирование имеет множество проблем, самая главная из которых — различные отражения и отражения, используемые в большом количестве сторонних библиотек. Генерация и модификация байт-кодов во время работы, как только программы, использующие эти фреймворки, будут отделены от виртуальной машины Java, обязательно вызовут различные проблемы, сделав локальный образ зеркальным. Команда GraalVM четко заявила, что для устойчивого развития и ремонтопригодности GraalVM она не будет совместима с существующей экосистемой JVM, которая требует большого количества сторонних библиотек для адаптации к GraalVM.

3rd party libraries
Graal VM native support needs to be sustainable and maintainable, that's why we do not want to maintain fragile pathches for the whole JVM ecosystem. The ecosystem of libraries needs to support it natively.
—Себастьян Делёз, DEVOXX 2019

Поэтому, чтобы способствовать совместимости экосистемы Java с GraalVM, GraalVM привлекла одну из лучших фракций в экосистеме Java: Spring, поэтому существует проект Spring Graal Native. Проект Spring Graal Native в основном используется для решения проблемы адаптации корзины семейства Spring, работающей на GraalVM.

В настоящее время проект все еще находится в экспериментальном состоянии на Github, и проект SpringBoot можно скомпилировать в локальный образ GraalVM.GitHub.com/spring-pro — это…

Сравнение производительности

Следующие данные основаны на образце, предоставленном Spring Graal Native, с использованием конфигурации машины: i7-9700/32G.

Проект SpringMVC

Встроенный контейнер tomcat, включая простой restApi

/ HotSpot Graal VM (локальное зеркало)
Начальное время 1.648s 0.075s
Занимает ресурсы после запуска 591M 52M
время упаковки/компиляции 12s 90s

Видно, что время запуска и занимаемые ресурсы локального образа намного меньше, чем у HotSpot (разница более чем в 10 раз), но из-за необходимости предварительной компиляции время упаковки также увеличится в несколько раз.

Скриншот времени запуска:

Скриншот во время выполнения:

Локальный эксперимент по трансформации проекта

Даже если Spring поддерживает нативные образы, сложно преобразовать исторический проект для поддержки локальных образов.В следующей части потребуется время, чтобы поговорить о практике преобразования.

Ссылаться на

oracle/graal: GraalVM: Run Programs Faster Anywhere
GraalVM Reference Manual
JVM Polyglot следующего поколения: GraalVM | Сеть параллельного программирования — ifeve.com
GraalVM и его экосистема — InfoQ

【Важно】Перепечатка, пожалуйста, укажите источник:Наггетс.Талант/пост/685512…