翻訳者から:GraalVMは新しい興味深いテクノロジーですが、HabréにはGraalの機能の例を示すことができる多くの記事がありません。 以下の記事は、GraalVMでできることのリストだけでなく、Chris SeatonとOleg ShelaevがOracle CodeOne 2018で行ったものに似た小さなマスタークラスでもあります。面白い。
GraalVMにはさまざまなものがあります。以前にこの名前を聞いたことがある、またはレポートを見たことがあったとしても、おそらくまだ知らないことはたくさんありますが、GraalVMでできることはたくさんあります。 この記事では、GraalVMが提供するさまざまな機能を見て、それらで何ができるかを示します。
- Java高速実行
- Javaの開始時間とメモリ使用量を減らす
- JavaScript、Java、Ruby、およびRの組み合わせ
- プラットフォーム固有の言語で書かれたプログラムの実行
- すべてのプログラミング言語に共通のツール
- JVMアプリケーションの補足
- プラットフォーム依存のアプリケーション
- プラットフォーム固有のライブラリとしてのJavaコード
- データベースでの複数のプログラミング言語のサポート
- GraalVM用のプログラミング言語の作成
GraalVM Webサイトのリンクから入手できるGraalVM 1.0.0 RC1を使用して、この記事に示されているすべてのことができます。 MacOS Enterprise Editionを使用しましたが、ここで記述されているコードはLinuxおよびGraalVM Community Editionで動作します。
記事を読んだら、その記事に記載されているプログラムを実行してください! コードはGitHubからダウンロードできます 。
設置
http://graalvm.org/downloadsからダウンロードした後、 $PATH
にGraalVM実行可能ファイルへのパスを追加しました。 デフォルトでは、これによりJavaおよびJavaScript実行のサポートが追加されます。
$ git clone https://github.com/chrisseaton/graalvm-ten-things.git $ cd foo $ tar -zxf graalvm-ee-1.0.0-rc1-macos-amd64.tar.gz # or graalvm-ee-1.0.0-rc1-linux-amd64.tar.gz on Linux $ export PATH=graalvm-1.0.0-rc1/Contents/Home/bin:$PATH # or PATH=graalvm-1.0.0-rc1/bin:$PATH on Linux
GraalVMにはJavaScriptサポートが組み込まれており、 gu
というパッケージマネージャーが含まれています。これは、JavaおよびJavaScript以外の言語のサポートをインストールする機能を追加します。 さらに、Ruby、Python、Rをインストールしました。これらはGitHubからダウンロードされます。
$ gu install -c org.graalvm.ruby $ gu install -c org.graalvm.python $ gu install -c org.graalvm.R
これで、 java
またはjs
コマンドを実行すると、これらのエンジンのGraalVMバージョンが表示されます。
$ java -version java version "1.8.0_161" Java(TM) SE Runtime Environment (build 1.8.0_161-b12) GraalVM 1.0.0-rc1 (build 25.71-b01-internal-jvmci-0.42, mixed mode) $ js --version Graal JavaScript 1.0 (GraalVM 1.0.0-rc1)
1.高速Java実行
GraalVMの「Graal」はコンパイラの名前です。 彼だけがすべてを支配するために創造された ! これは、これが多くのさまざまなことに使用できるライブラリの形式で記述された1つのコンパイラ実装であることを意味します。 たとえば、Graalを使用して事前処理とジャストイン タイムの両方をコンパイルし、さまざまなプロセッサアーキテクチャを含むさまざまなプログラミング言語で記述されたコードをコンパイルします。
Graalを使用する最初の最も簡単な方法は、GraalをJava JITコンパイラとして使用することです。
例として、ドキュメント内で最も頻繁に使用される10個の単語を表示するプログラムを使用します。 このプログラムは、ストリームやコレクションなどの最新のJava言語の機能を使用します。
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; public class TopTen { public static void main(String[] args) { Arrays.stream(args) .flatMap(TopTen::fileLines) .flatMap(line -> Arrays.stream(line.split("\\b"))) .map(word -> word.replaceAll("[^a-zA-Z]", "")) .filter(word -> word.length() > 0) .map(word -> word.toLowerCase()) .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())) .entrySet().stream() .sorted((a, b) -> -a.getValue().compareTo(b.getValue())) .limit(10) .forEach(e -> System.out.format("%s = %d%n", e.getKey(), e.getValue())); } private static Stream<String> fileLines(String path) { try { return Files.lines(Paths.get(path)); } catch (IOException e) { throw new RuntimeException(e); } } }
GraalVMにはjavac
コンパイラが含まれていますが、このデモを使用するか標準コンパイラを使用するかに違いはありません。 したがって、必要に応じて標準のjavac
コンパイラを使用できます。
$ javac TopTen.java
GraalVMに含まれているjava
コマンドを実行すると、Grait JITコンパイラーが自動的に使用されます。追加の手順は必要ありません。 複雑なマイクロベンチマークを展開する代わりに、プログラムを最初から最後まで実行するのにかかった時間に関する実際のデータを取得するために、 time
コマンドを使用します。 また、大量の入力データが使用されるため、保存された数秒間のあちこちにほのめかしがありません。 large.txt
ファイルのサイズは150 MBです。
$ make large.txt $ time java TopTen large.txt sed = 502701 ut = 392657 in = 377651 et = 352641 id = 317627 eu = 317627 eget = 302621 vel = 300120 a = 287615 sit = 282613 real 0m17.367s user 0m32.355s sys 0m1.456s
Graalは、他のほとんどのJava用JITコンパイラのように、C ++ではなくJavaで記述されています。 これにより、HotSpotの標準JITコンパイラでは利用できない強力な新しい最適化(部分的なエスケープ解析など)で補完することで、既存のコンパイラよりも高速に改善できると考えています。
そして、それはあなたのJavaプログラムをずっと速くすることができます。
比較のために、Grait JITコンパイラーなしでプログラムを実行するには、 -XX:-UseJVMCICompiler
を使用し-XX:-UseJVMCICompiler
。 JVMCIはGraalとJVMの間のインターフェースです。 標準のJVMで例を実行して、結果を比較することもできます。
$ time java -XX:-UseJVMCICompiler TopTen large.txt sed = 502701 ut = 392657 in = 377651 et = 352641 id = 317627 eu = 317627 eget = 302621 vel = 300120 a = 287615 sit = 282613 real 0m23.511s user 0m24.293s sys 0m0.579s
このテストは、GraalがJavaプログラムを標準のHotSpotコンパイラで実行するのにかかる時間の約4分の3で実行することを示しています。 生産性をパーセント単位で改善することが重要な成果であると考える場合、25%が大したことです。
今日、Twitterは「戦闘」サーバーでGraalを使用している唯一の企業であり、実際のお金を節約するという点で、彼らにとって正当だと言います。 TwitterはGraalを使用してScalaで記述されたアプリケーションを実行します-GraalはJVMバイトコードレベルで動作します。 すべてのJVM言語に適用可能。
これはGraalVMの最初のユースケースです。JITコンパイラーを既存のJavaアプリケーションのより良いバージョンに置き換えるだけです。
2. Javaの開始時間とメモリ使用量を減らす
Javaプラットフォームの長所は、長時間実行されるプロセスとピーク負荷で作業する場合に特に顕著です。 対照的に、短命のプロセスは、起動時間が長く、メモリ使用量が比較的多いという問題があります。
たとえば、前のセクションからアプリケーションを実行し、150MBではなく約1Kbのはるかに少ない入力データを入力すると、このような小さなファイルを処理するには、不当に長い時間とかなりのメモリが必要になります(約60MB) 。 -l
オプションを使用して、実行時間に加えて使用メモリ量を出力します。
$ make small.txt $ /usr/bin/time -l java TopTen small.txt # -v on Linux instead of -l sed = 6 sit = 6 amet = 6 mauris = 3 volutpat = 3 vitae = 3 dolor = 3 libero = 3 tempor = 2 suscipit = 2 0.32 real 0.49 user 0.05 sys 59846656 maximum resident set size
GraalVMは、この問題を解決するツールを提供します。 Graalはコンパイラライブラリであり、さまざまな方法で使用できると述べました。 その1つは、実行時にジャストインタイムでコンパイルするのではなく、プラットフォーム固有の実行可能イメージに事前にコンパイルすることです。 これは、 gcc
などの通常のコンパイラーの動作に似ています。
$ native-image --no-server TopTen classlist: 1,513.82 ms (cap): 2,333.95 ms setup: 3,584.09 ms (typeflow): 4,642.13 ms (objects): 3,073.58 ms (features): 156.34 ms analysis: 8,059.94 ms universe: 353.02 ms (parse): 1,277.02 ms (inline): 1,412.08 ms (compile): 10,337.76 ms compile: 13,776.23 ms image: 2,526.63 ms write: 1,525.03 ms [total]: 31,439.47 ms
このコマンドは、 topten
というプラットフォームtopten
作成します。 このファイルはJVMを起動せず、JVMにリンクされず、JVMを一切含みません。 native-image
コマンドは、Javaコードと使用するJavaライブラリを完全なマシンコードに完全にコンパイルします。 ガベージコレクターなどのランタイムコンポーネントの場合は、Gradeと同様にJavaで記述されたSubstrateVMと呼ばれる独自の新しいVMを起動します。
topten
使用する依存関係を見ると、これらは標準のシステムライブラリにすぎないことがわかります。 この1つのファイルは、JVMがインストールされたことのないシステムにのみ転送し、そこで実行して、JVMまたは他のファイルを使用していないことを確認できます。 Topten
も非常に小さく、実行可能コードのTopten
6 MB未満です。
$ otool -L topten # ldd topten on Linux topten: .../CoreFoundation.framework ... .../libz.1.dylib ... .../libSystem.B.dylib ... $ du -h topten 5.7M topten
この実行可能ファイルを実行すると、JVMの下で実行されている同じプログラムよりも、1桁速く起動し、1桁少ないメモリを使用することがわかります。 起動は非常に高速なので、どれだけ時間がかかったか気付かないでしょう。 コマンドラインを使用する場合、JVMの下で小さな短命のプログラムを実行するときに通常存在する一時停止を感じることはありません。
$ /usr/bin/time -l ./topten small.txt sed = 6 sit = 6 amet = 6 mauris = 3 volutpat = 3 vitae = 3 dolor = 3 libero = 3 tempor = 2 suscipit = 2 0.02 real 0.00 user 0.00 sys 4702208 maximum resident set size
native-image
ユーティリティにはいくつかの制限があります。 そのため、コンパイル時にはすべてのクラスが存在する必要があります。また、Reflection APIの使用には制限があります。 ただし、コンパイル時の静的初期化子の実行など、基本的なコンパイルに比べていくつかの追加の利点があります。 したがって、アプリケーションがダウンロードされるたびに実行される作業量が削減されます。
これは、GraalVMの2番目のアプリケーションです。既存のJavaプログラムの配布と実行であり、クイックスタートとメモリ消費量の削減を実現します。 この方法は、実行時に適切なjarを見つけるなどの構成の問題を修正し、小さなドッカーイメージを作成することもできます。
3. JavaScript、Java、Ruby、およびRの組み合わせ
GraalVMには、Javaとともに、JavaScript、Ruby、R、およびPythonエンジンの新しい実装が含まれています。 それらはTruffleと呼ばれる新しいフレームワークを使用して書かれています。 このフレームワークにより、シンプルで高性能な言語インタープリターを作成できます。 Truffleを使用して言語インタープリターを作成すると、Graalが自動的に使用され、言語のJITコンパイルが提供されます。 したがって、Graalは、Java用のJITコンパイラーおよびAOTコンパイラーであるだけでなく、JavaScript、Ruby、R、およびPython用のJITコンパイラーでもあります。
GraalVMでのサードパーティ言語のサポートは、さまざまな言語を実行するための既存のエンジンの透過的な置き換えを目的としています。 たとえば、Node.jsの「カラー」モジュールをインストールできます。
$ npm install --global color ... + color@3.0.0 added 6 packages in 14.156s
次に、このモジュールを使用してRGB HTMLカラーをHSLに変換するプログラムを作成します。
var Color = require('color'); process.argv.slice(2).forEach(function (val) { print(Color(val).hsl().string()); });
そして通常の方法で実行します:
$ node color.js '#42aaf4' hsl(204.89999999999998, 89%, 60.8%)
GraalVMの異なる言語の実行エンジンは連携して動作します-別の言語で書かれたプログラムのある言語からコードを実行できるAPIがあります。 これにより、複数言語のプログラム、つまり複数のプログラミング言語で書かれたプログラムを作成できます。
これは、プログラムの大部分を1つの言語で記述するが、別のプログラミング言語で記述されたライブラリを使用したい場合に必要になることがあります。 たとえば、色名をCSSからNode.jsの数値表現に変換するアプリケーションを作成する必要があるが、変換を自分で作成するのではなく、Rubyカラーライブラリを使用するとします。
var express = require('express'); var app = express(); color_rgb = Polyglot.eval('ruby', ` require 'color' Color::RGB `); app.get('/css/:name', function (req, res) { color = color_rgb.by_name(req.params.name).html() res.send('<h1 style="color: ' + color + '" >' + color + '</h1>'); }); app.listen(8080, function () { console.log('serving at http://localhost:8080') });
このコードでは、Rubyコードを文字列として実行する必要があると書きましたが、ここでは多くのことをしなかったことに注意してください。ライブラリを接続してからRubyオブジェクトを返しただけです。 Rubyでは、 Color::RGB.by_name (name).html
ように使用します。 後でJavaScriptでcolor_rgb
どのように使用されるかを見ると、実際にはJavaScriptから同じメソッドを呼び出していることがわかりますが、これらはRubyオブジェクトとメソッドです。 そして、それらをJavaScript文字列として渡し、Ruby文字列である結果をJavaScript文字列と組み合わせます。
RubyとJavaScriptの両方の依存関係をインストールします。
$ gem install color Fetching: color-1.8.gem (100%) Successfully installed color-1.8 1 gem installed $ npm install express + express@4.16.2 updated 1 package in 10.393s
次に、いくつかの追加オプションでnode
を開始する必要があります:-- --polyglot
、他の言語と--jvm
アクセスする必要があることを示すため、デフォルトではnode
実行可能イメージにはJavaScript以外が含まれていないためです。
$ node --polyglot --jvm color-server.js serving at http://localhost:8080
そして、通常どおり、ブラウザでURL http:// localhost:8080 / css / orange (または他の色)に移動します。
より多くの言語とモジュールを使用する、より深刻な例を作成してみましょう。
JavaScriptは非常に大きな整数をサポートしていません。 big-integerなどのモジュールをいくつか見つけましたが、それらはすべて非効率的です。 数値のコンポーネントをJavaScript浮動小数点数として保存します。 JavaのBigInteger
クラスはより効率的です。それを使用して、大きな整数でいくつかの算術演算を行いましょう。
JavaScriptはグラフの描画をサポートしていませんが、Rは優れたグラフを作成します。 Rのsvg
モジュールを使用して、3D空間で三角関数の散布図を描画しましょう。
どちらの場合も、APIを使用してGraalVMの多言語をサポートし(以降、Polyglot APIと呼びます)、他の言語のプログラムの実行結果をJavaScriptに単純に挿入できます。
const express = require('express') const app = express() const BigInteger = Java.type('java.math.BigInteger') app.get('/', function (req, res) { var text = 'Hello World from Graal.js!<br> ' // Using Java standard library classes text += BigInteger.valueOf(10).pow(100) .add(BigInteger.valueOf(43)).toString() + '<br>' // Using R interoperability to create graphs text += Polyglot.eval('R', `svg(); require(lattice); x <- 1:100 y <- sin(x/10) z <- cos(x^1.3/(runif(1)*5+10)) print(cloud(x~y*z, main="cloud plot")) grDevices:::svg.off() `); res.send(text) }) app.listen(3000, function () { console.log('Example app listening on port 3000!') })
ブラウザでhttp:// localhost:3000 /を開き、結果を確認します。
これがGraalVMでできる3番目のことです。複数の言語で書かれたプログラムを実行し、これらの言語のモジュールを1つのプログラムで一緒に使用します。 これは、ランタイム環境とライブラリを統合する方法として提示します-プログラミング言語に関係なく、現在のタスクと必要なライブラリを解決するのに最適と思われるプログラミング言語を使用できます。
4.プラットフォーム固有の言語で書かれたプログラムの実行
GraalVMがサポートする別の言語はCです。GraalVMは、JavaScriptおよびRubyで作成されたプログラムを実行するのと同じ方法でCコードを実行できます。
GraalVMが実際にサポートしているのは、LLVMユーティリティの実行から生じるコードの実行です。 Cの直接サポートではなく、ビットコード。これは、C ++、Fortran、将来的にはより多くの言語など、LLVMをサポートするC言語およびその他の既存のツールを使用できることを意味します。 デモンストレーションを簡単にするために、特別なバージョンのgzipを実行します。これは1つのファイルにコンパイルされています(このバージョンはStephen McCamantによってサポートされています )。 これはgzip
ソースコードとautoconf
設定を1つのファイルにまとめたもので、単純化しています。 macOSおよびclangで動作させるには、いくつかのパッチを適用する必要がありましたが、GraalVMをサポートするために特に何もしませんでした。
標準のclang
(C用のLLVMコンパイラ)を使用してgzipをコンパイルし、GraalVMが起動しないため、プラットフォーム固有のビルドではなく、LLVMビットコードにすることを望んでいます。 clang
4.0.1を使用しています。
$ clang -c -emit-llvm gzip.c
そして、GraalVMのlliコマンド(LLVMビットコードインタープリター)を直接使用して、結果を実行します。 gzipシステムアーカイバを使用してファイルを圧縮し、GraalVMで実行されているgzipを使用してファイルを解凍してみましょう。
$ cat small.txt Lorem ipsum dolor sit amet... $ gzip small.txt $ lli gzip.bc -d small.txt.gz $ cat small.txt Lorem ipsum dolor sit amet...
GraalVMのRubyおよびPython実装は、同じ手法を使用して、これらの言語のCで記述された拡張機能を実行します。 これは、VM内でこれらの拡張機能を実行できることを意味し、これにより、古いプラットフォーム固有の拡張機能インターフェイスを使用している場合でも、実行の高速性を維持できます。
これはGraalVMを使用する4番目の方法です-CやC ++などのプラットフォーム固有の言語で記述されたプログラムを実行し、JRubyなどのこれらの言語のJVM実装を作成できないPythonやRubyなどの言語の拡張機能を実行します。
5.すべてのプログラミング言語用の一般的なツール
Javaでプログラミングする場合、おそらくIDE、デバッガー、プロファイラーなどの非常に高品質のツールを使用していることになります。 すべての言語にこのようなツールのセットがあるわけではありませんが、GraalVMでサポートされている言語を使用すれば、そのようなセットを入手できます。
GraalVMのすべての言語(現時点ではJavaを除く)のサポートは、共通のフレームワーク-Truffleを使用して実装されます。 これにより、デバッガーなどの機能を一度作成して、すべての言語で使用できます。
これを試すために、最も単純なプログラムFizzBuzzを作成します。これは視覚的で(画面に何かを印刷する)、一部の反復でのみ使用される明確なブランチがあるためです。 したがって、ブレークポイントを設定する方が簡単です。 JavaScriptの実装から始めましょう。
function fizzbuzz(n) { if ((n % 3 == 0) && (n % 5 == 0)) { return 'FizzBuzz'; } else if (n % 3 == 0) { return 'Fizz'; } else if (n % 5 == 0) { return 'Buzz'; } else { return n; } } for (var n = 1; n <= 20; n++) { print(fizzbuzz(n)); }
GraalVMの下で、 js
ユーティリティを使用して通常どおりプログラムを開始します。
$ js fizzbuzz.js 1 2 Fizz 4 Buzz Fizz
--inspect
フラグを使用してプログラムを実行することもできます。 これにより、Chromeで開いてデバッガーでプログラムを停止できるリンクが提供されます。
$ js --inspect fizzbuzz.js Debugger listening on port 9229. To start debugging, open the following URL in Chrome: chrome-devtools://devtools/bundled/inspector.html?ws=127.0.0.1:9229/6c478d4e-1350b196b409
FizzBuzzコードにブレークポイントを設定して、実行を継続できます。 プログラムが実行を中断すると、デバッガーで変数n
値が表示され、プログラムの実行を続行するか、デバッガーインターフェイスを調べることができます。
Chromeのデバッガーは通常JavaScriptに使用されますが、JavaScriptのGraalVMには他の言語と何の違いもありません。 --inspect
フラグも利用可能で、Python、Ruby、Rの実装で動作します。各プログラムのソースは表示しませんが、同じ方法で実行され、それぞれのChromeで同じデバッガーを取得します。
$ graalpython --jvm --inspect fizzbuzz.py
$ ruby --inspect fizzbuzz.rb
$ Rscript --inspect fizzbuzz.r
Javaでおなじみのもう1つのツールはVisualVMです。 ローカルマシン上またはネットワーク経由で実行中のJVMに参加して、メモリ使用量やスレッド実行などのプログラム実行のさまざまな側面を検査できるユーザーインターフェイスを提供します。
GraalVMには、標準のjvisualvm
ユーティリティとしてVisualVMが含まれています。
$ jvisualvm &> /dev/null &
TopTen
Javaプログラムの実行中にVisualVMを実行すると、メモリ使用量を確認したり、メモリの内容のスナップショットを取得して、ヒープでメモリを使用するオブジェクトの種類を確認したりできます。
$ java TopTen large.txt
このプログラムをRubyで記述して、実行時にメモリにゴミを生成しました。
require 'erb' x = 42 template = ERB.new <<-EOF The value of x is: <%= x %> EOF loop do puts template.result(binding) end
JVM(JRuby)で標準のRuby実装を実行すると、言語のオブジェクトではなく内部Javaオブジェクトのみが表示されるため、VisualVMに失望します。
GraalVMにRubyのバージョンを使用すると、VisualVMはRubyオブジェクトを認識します。 VisualVMを使用するには、 --jvm
オプションを使用する必要があります。 Rubyのネイティブバージョンはサポートしていません。
$ ruby --jvm render.rb
, , Java , , , Summary, Ruby Heap Ruby .
Truffle — - Nexus . Truffle , , API Truffle' , , Truffle, .
, GraalVM — , . Truffle GraalVM , VisualVM.
6. JVM
, , , Java . API org.graalvm.polyglot
, .
import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Value; public class ExtendJava { public static void main(String[] args) { String language = "js"; try (Context context = Context.newBuilder().allowNativeAccess(true).build()) { for (String arg: args) { if (arg.startsWith("-")) { language = arg.substring(1); } else { Value v = context.eval(language, arg); System.out.println(v); } } } } }
javac
java
GraalVM, org.graalvm.*
classpath
, .. .
$ javac ExtendJava.java $ java ExtendJava '14 + 2' 16 $ java ExtendJava -js 'Math.sqrt(14)' 3.7416573867739413 $ java ExtendJava -python '[2**n for n in range(0, 8)]' [1, 2, 4, 8, 16, 32, 64, 128] $ java ExtendJava -ruby '[4, 2, 3].sort' [2, 3, 4]
, — , node
ruby
, GraalVM.
GraalVM — Java . Polyglot API “” Java , .
7. -
GraalVM , , — , , GraalVM, - . , JavaScript , V8, Python — CPython , .. . GraalVM — Polyglot .
GraalVM, , JavaScript. Polyglot , , :
$ graalvm-1.0.0-rc1/Contents/Home/jre/lib/svm/bin/rebuild-images libpolyglot
C, , , GraalVM, . ExtendJava
, , .
#include <stdlib.h> #include <stdio.h> #include <polyglot_api.h> int main(int argc, char **argv) { graal_isolate_t *isolate = NULL; graal_isolatethread_t *thread = NULL; if (graal_create_isolate(NULL, &isolate) != 0 || (thread = graal_current_thread(isolate)) == NULL) { fprintf(stderr, "initialization error\n"); return 1; } poly_context context = NULL; if (poly_create_context(thread, NULL, 0, &context) != poly_ok) { fprintf(stderr, "initialization error\n"); return 1; } char* language = "js"; for (int n = 1; n < argc; n++) { if (argv[n][0] == '-') { language = &argv[n][1]; } else { poly_value result = NULL; if (poly_context_eval(thread, context, language, "unicalc", argv[n], &result) != poly_ok) { fprintf(stderr, "eval error\n"); return 1; } char buffer[1024]; size_t length; if (poly_value_to_string_utf8(thread, result, buffer, sizeof(buffer), &length) != poly_ok) { fprintf(stderr, "to string error\n"); return 1; } buffer[length] = '\0'; printf("%s\n", buffer); poly_destroy_handle(thread, result); } } return 0; }
, polyglot GraalVM. , , JVM.
$ clang -Igraalvm-1.0.0-rc1/Contents/Home/jre/lib/polyglot / -rpath graalvm-1.0.0-rc1/Contents/Home / -Lgraalvm-1.0.0-rc1/Contents/Home/jre/lib/polyglot / -lpolyglot extendc.c -o extendc $ otool -L extendc extendc: .../libpolyglot.dylib ... .../libSystem.B.dylib ...
$ ./extendc '14 + 2' 16 $ ./extendc -js 'Math.sqrt(14)' 3.7416573867739413 $ ./extendc -python '[2**n for n in range(0, 8)]' [1, 2, 4, 8, 16, 32, 64, 128]
, GraalVM — - , , GraalVM.
8. Java -
Java , , , , - , . Java - , JVM , .
GraalVM Java , , - , . , , Java JVM.
, Apache SIS , ( ) . SIS 0.8, http://sis.apache.org/ jar.
import org.apache.sis.distance.DistanceUtils; public class Distance { public static void main(String[] args) { final double aLat = Double.parseDouble(args[0]); final double aLong = Double.parseDouble(args[1]); final double bLat = Double.parseDouble(args[2]); final double bLong = Double.parseDouble(args[3]); System.out.printf("%.2f km%n", DistanceUtils.getHaversineDistance(aLat, aLong, bLat, bLong)); } public static double distance(IsolateThread thread, double aLat, double aLong, double bLat, double bLong) { return DistanceUtils.getHaversineDistance(aLat, aLong, bLat, bLong); } }
, -
$ javac -cp sis.jar -parameters Distance.java $ java -cp sis.jar:. Distance 51.507222 -0.1275 40.7127 -74.0059 5570.25 km
, topten
.
$ native-image --no-server -cp sis.jar:. Distance ... $ ./distance 51.507222 -0.1275 40.7127 -74.0059 5570.25 km
, . , @CEntryPoint
... import org.graalvm.nativeimage.IsolateThread; import org.graalvm.nativeimage.c.function.CEntryPoint; public class Distance { ... @CEntryPoint(name = "distance") public static double distance(IsolateThread thread, double a_lat, double a_long, double b_lat, double b_long) { return DistanceUtils.getHaversineDistance(a_lat, a_long, b_lat, b_long); } ... }
javac
, GraalVM API classpath
. C .
$ native-image --no-server -cp sis.jar:. -H:Kind=SHARED_LIBRARY \ -H:Name=libdistance $ otool -L libdistance.dylib # .so on Linux libdistance.dylib: .../libdistance.dylib ... .../CoreFoundation.framework ... .../libz.1.dylib ... .../libSystem.B.dylib ... $ du -h libdistance.dylib 4.8M libdistance.dylib
, . , : VM , , .
#include <stdlib.h> #include <stdio.h> #include <libdistance.h> int main(int argc, char **argv) { graal_isolate_t *isolate = NULL; graal_isolatethread_t *thread = NULL; if (graal_create_isolate(NULL, &isolate) != 0 || (thread = graal_current_thread(isolate)) == NULL) { fprintf(stderr, "initialization error\n"); return 1; } double a_lat = strtod(argv[1], NULL); double a_long = strtod(argv[2], NULL); double b_lat = strtod(argv[3], NULL); double b_long = strtod(argv[4], NULL); printf("%.2f km\n", distance(thread, a_lat, a_long, b_lat, b_long)); return 0; }
, ( LD_LIBRARY_PARTH=.
Linux)
$ clang -I. -L. -ldistance distance.c -o distance $ otool -L distance distance: .../libdistance.dylib ... .../libSystem.B.dylib ... $ ./distance 51.507222 -0.1275 40.7127 -74.0059 5570.25 km
GraalVM — java - , JVM
9.
Polyglot — Oracle. Oracle Database Multilingual Engine (MLE), GraalVM SQL.
, front-end, JavaScript email , JavaScript validator
. - , SQL PL/SQL. , .
MLE Docker :
https://oracle.github.io/oracle-db-mle/releases/0.2.7/docker/
Docker Daemon.
$ docker load --input mle-docker-0.2.7.tar.gz
, Docker, , ( ), Bash .
$ docker run mle-docker-0.2.7 $ docker ps $ docker exec -ti <container_id> bash -li
sqlplus
( SQL ), Bash, , , .
$ sqlplus scott/tiger@localhost:1521/ORCLCDB
, sqlplus
. , Bash Docker, dbjs
, . sqlplus
.
$ npm install validator $ npm install @types/validator $ dbjs deploy -u scott -p tiger -c localhost:1521/ORCLCDB validator $ sqlplus scott/tiger@localhost:1521/ORCLCDB
validator
SQL .
SQL> select validator.isEmail('hello.world@oracle.com') from dual; VALIDATOR.ISEMAIL('HELLO.WORLD@ORACLE.COM') ------------------------------------------- 1 SQL> select validator.isEmail('hello.world') from dual; VALIDATOR.ISEMAIL('HELLO.WORLD') -------------------------------- 0
, GraalVM — , GraalVM, Oracle. , front-end back-end, , , .
10. GraalVM
Oracle Labs JavaScript, R, Ruby, Python C , Truffle, GraalVM.
Truffle — java , (AST). AST — , , , , , . , , Truffle Graal JIT , AST .
Truffle, GraalVM , , DSL. Truffle Graal , , Truffle — GraalVM. , , , , . , , . Oracle labs Ruby , , .
, , , SimpleLanguage — Truffle, JavaScript. , , , , , if .
, Truffle Oracle Labs, SmallTalk , Newspeak Lisp . Lisp , .
おわりに
GraalVM — , , . , , , , .
GraalVM, http://www.graalvm.org/ . , , .
, , . , GraalVM @ChrisGSeaton @shelajev .
: Oleg Šelajev , Olya Gupalo Doug Simon