Статьи

Научиться использовать полностью GraalVM!

Вступление

В посте « Трюфель» служил в «Священном Граале: Грааль и Трюфель» для интерпретации языка полиглота на JVM , мы получили краткое введение и немного углубились в изучение Граала, Трюфеля и некоторых концепций вокруг него. Но ни одна технология не может быть увлекательной, если не углубляться в ее практичность, иначе она похожа на «Теоретическую физику» или «Чистую математику» — абстрактная для некоторых, скучная для других (извините, последняя часть была просто мной разглагольствования).

В этой статье мы рассмотрим GraalVM , установим его, сравним различия SDK и рассмотрим некоторые примеры, иллюстрирующие, как разные языки могут быть скомпилированы и запущены в GraalVM, а также как их можно запускать в тот же контекст и, наконец, изначально (более производительный).

GraalVM похож на любой Java SDK (JDK), который мы загружаем от любого поставщика, за исключением того, что у него есть JVMCI: поддержка интерфейса компилятора JVM уровня Java и Graal является компилятором JIT по умолчанию. Он может не только выполнять код Java, но и языки, такие как JS, Ruby, Python и R. Он также может позволить создавать заблаговременно (AOT) скомпилированный исполняемый файл (нативные образы) или совместно использовать библиотеку для программ Java и других поддерживаемых языков. Хотя мы не будем проходить через каждый язык, а только некоторые из них.

Просто чтобы вы знали, что все команды и действия были выполнены в среде операционной системы Ubuntu 16.04 (должна работать на MacOSX с небольшими адаптациями, в Windows потребуется немного больше изменений — рад получить обратную связь с различиями Буду обновлять пост с ними).

Практический практический

Мы можем заполучить GraalVM несколькими способами, либо создать его самостоятельно, либо загрузить предварительно собранную версию с веб-сайта поставщика:

  • создать самостоятельно: клонирование и прочую магию (мы увидим позже)
  • скачать готовый сайт загрузки JVM: OTN
  • подключить пользовательский JIT к существующему JDK с поддержкой JVMCI (мы увидим позже)

Поскольку мы используем среду Linux, лучше всего загрузить версию GraalVM для Linux (предварительная версия) на основе JDK8 (> 500 МБ, необходимо принять лицензию, выполнить вход в OTN или перейти на https://login.oracle.com/mysso/signon.jsp ) и установите его.

Следуйте инструкциям по установке на странице загрузки, после распаковки архива вы найдете папку с именем graalvm-0.30 (на момент написания этого поста) после выполнения следующей команды:

1
$ tar -xvzf graalvm-0.30-linux-amd64-jdk8.tar.gz

Взгляд орла: сравните SDK

Мы быстро проверим содержимое SDK, чтобы ознакомиться с ним, поэтому давайте проверим содержимое папки GraalVM SDK :

1
2
$ cd graalvm-0.30
$ ls

который выглядит знакомым и имеет сходство по сравнению с традиционной папкой Java SDK (т.е. JDK 1.8.0_44):

1
2
$ cd /usr/lib/jdk1.8.0_44
$ ls

За исключением того, что у нас есть немало дополнительных артефактов для изучения, например, запуска на ВМ для поддерживаемых языков, таких как FastR, JS (GraalJS), NodeJS (GraalNodeJS), Python, Ruby и Sulong (C / C ++, Fortran) .

Сравнивая папку bin между GraalVM SDK и, скажем, JDK 1.8.0_44 SDK, мы видим, что у нас там есть несколько дополнительных файлов:

(используйте инструменты вроде meld или diff для сравнения каталогов)

Точно так же мы видим, что папка jre имеет интересные отличия, хотя семантически похожа на традиционные Java SDK. Несколько пунктов, которые выглядят интересными в списке, это Rscript , lli и ployglot .

Теперь мы буквально не сравнивали два SDK, чтобы пометить элементы, которые отличаются или отсутствуют в одном или другом, но вышеизложенное дает нам представление о том, что предлагается вместе с предварительным описанием того, как использовать предоставляемые им функции — хорошо, этот SDK имеет они запекли в нем папку с examples .

1
$ tree -L 1

(используйте команду treesudo apt-get tree чтобы увидеть вышеупомянутое, доступное в MacOSX и Windows)

Каждая из подпапок содержит примеры для соответствующих языков, поддерживаемых GraalVM, включая embed и native-image которые мы также рассмотрим.

Захватывающая часть: практическое использование примеров

Давайте перейдем к graalvm-0.30 , но прежде чем мы сможем выполнить какой-либо код и посмотрим, что делают примеры, мы должны переместить graalvm-0.30 туда, где находятся другие Java SDK, скажем, в / usr/lib/jvm/ и установить переменную среды вызвал GRAAL_HOME чтобы указать на это:

1
2
3
4
$ sudo mv -f graalvm-0.30 /usr/lib/jvm
$ export GRAAL_HOME=/usr/lib/jvm/graalvm-0.30
$ echo "export GRAAL_HOME=/usr/lib/jvm/graalvm-0.30" >> ~/.bashrc
$ cd examples

R язык

Давайте выберем R и запустим несколько файлов скриптов R :

1
2
$ cd R
$ $GRAAL_HOME/bin/Rscript --help    # to get to see the usage text

Остерегайтесь того, что мы запускаем Rscript а не R , оба могут запускать R-сценарии, позже будет R REPL.

Запуск hello_world.R с использованием Rscript :

1
2
$ $GRAAL_HOME/bin/Rscript hello_world.R
[1] "Hello world!"

JavaScript

Затем мы попробуем Javascript :

1
2
$ cd ../js/
$ $GRAAL_HOME/bin/js --help         # to get to see the usage

Запуск hello_world.js с помощью js :

1
2
$ $GRAAL_HOME/bin/js hello_world.js
Hello world!

встраивать

Теперь давайте попробуем что-то другое, что если вы захотите запустить код, написанный на нескольких языках, все они находятся в одном исходном файле, на JVM — никогда раньше не делали, что и подразумевается под embed .

1
$ cd ../embed

Мы можем сделать это с org.graalvm.polyglot.context класса org.graalvm.polyglot.context . Вот фрагмент кода из HelloPolyglotWorld.java :

01
02
03
04
05
06
07
08
09
10
11
12
13
import org.graalvm.polyglot.*;
 
public class HelloPolyglotWorld {
 
public static void main(String[] args) throws Exception {
 System.out.println("Hello polyglot world Java!");
 Context context = Context.create();
 context.eval("js", "print('Hello polyglot world JavaScript!');");
 context.eval("ruby", "puts 'Hello polyglot world Ruby!'");
 context.eval("R", "print('Hello polyglot world R!');");
 context.eval("python", "print('Hello polyglot world Python!');");
 }
}

Скомпилируйте его следующим образом, чтобы получить файл .class :

1
$ $GRAAL_HOME/bin/javac HelloPolyglotWorld.java

И запустите его с помощью команды ниже, чтобы увидеть, как это работает:

1
2
3
4
5
6
$ $GRAAL_HOME/bin/java HelloPolyglotWorld
Hello polyglot world Java!
Hello polyglot world JavaScript!
Hello polyglot world Ruby!
[1] "Hello polyglot world R!"
Hello polyglot world Python!

Возможно, вы заметили некоторую медлительность при выполнении при переключении между языками и печати «Hello, polyglot world….» сообщения, надеюсь, мы узнаем, почему это происходит, и, возможно, даже сможем это исправить.

Родное изображение

Собственная функция изображения с помощью GraalVM SDK помогает сократить время запуска Java- приложений и уменьшить его площадь . Фактически это преобразование байт-кода, который выполняется на JVM (на любой платформе), в собственный код для конкретной ОС / платформы — отсюда и производительность. Он использует агрессивную опережающую оптимизацию для достижения хорошей производительности.

Посмотрим, как это работает.

1
$ cd ../native-image

Давайте возьмем фрагмент кода Java из HelloWorld.java в этой папке:

1
2
3
4
5
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}

Скомпилируйте его в байт-код:

1
$ $GRAAL_HOME/bin/javac HelloWorld.java

Скомпилируйте байт-код (HelloWorld.class) в собственный код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
$ $GRAAL_HOME/bin/native-image HelloWorld
 classlist: 740.68 ms
 (cap): 1,042.00 ms
 setup: 1,748.77 ms
 (typeflow): 3,350.82 ms
 (objects): 1,258.85 ms
 (features): 0.99 ms
 analysis: 4,702.01 ms
 universe: 288.79 ms
 (parse): 741.91 ms
 (inline): 634.63 ms
 (compile): 6,155.80 ms
 compile: 7,847.51 ms
 image: 1,113.19 ms
 write: 241.73 ms
 [total]: 16,746.19 ms

Взглянув на папку, мы можем увидеть исходный код Hello World и скомпилированные артефакты:

1
2
3
3.8M -rwxrwxr-x 1 xxxxx xxxxx 3.8M Dec 12 15:48 helloworld
 12K -rw-rw-r-- 1 xxxxx xxxxx     427 Dec 12  15:47 HelloWorld.class
 12K -rw-rw-r-- 1 xxxxx xxxxx     127 Dec 12  13:59 HelloWorld.java

Первый файл helloworld — это собственный двоичный файл, который запускается на платформе, на которой мы его скомпилировали, с помощью команды native-image , которую можно напрямую выполнить с помощью JVM:

1
2
$ helloworld
Hello, World!

Даже при том, что мы повышаем производительность, мы можем потерять другие функции, которые мы запускаем в форме байт-кода на JVM — выбор того, какой маршрут выбрать, зависит от варианта использования и того, что важно для нас.

Это завершение!

Это требует подведения итогов, довольно много, чтобы прочитать и опробовать в командной строке, но вполне стоит потратить время на изучение интересного GraalVM.

Подводя итог, мы пошли о загрузке GraalVM с веб-сайта Oracle Lab , распаковали его, взглянули на различные папки и сравнили его с нашими традиционными Java SDK, заметили и отметили различия.

Мы также рассмотрели примеры, предоставленные для различных языков, поддерживаемых Graal, и подобрали несколько функций, которые дали нам представление о том, что может предложить GraalVM. Хотя мы можем запускать на нем наши традиционные приложения Java, теперь у нас также есть возможность писать приложения, выраженные на нескольких поддерживаемых языках, в одном исходном файле или в одном и том же проекте. Это также дает нам возможность беспрепятственно взаимодействовать между различными аспектами приложения, написанными на другом языке. Возможность даже перекомпилировать наши существующие приложения для собственных сред ( native-image ) для повышения производительности и уменьшения занимаемой площади.

Смотрите оригинальную статью здесь: УЧИТЬСЯ, ЧТОБЫ ИСПОЛЬЗОВАТЬ ВЕСЬ GRAALVM!

Мнения, высказанные участниками Java Code Geeks, являются их собственными.