たのしい
Graal/Truffle

自己紹介

  • 山名 洋平
  • Opt Technologies
  • Java, PHP, Scala
  • twitter
    @vertical_blank

話すこと

  • graal とは

  • truffle とは

  • 遊んでみる

  • もろもろ

Graal

Javaで記述されたJITコンパイラ

  • java8ベースのバイナリが配布されている
  • truffleと以下の実行エンジンを同梱
    • JavaScript( + node.js)
    • Ruby
    • R
  • ahead-of-time compile
    classから実行ファイルを生成

Truffle

インタプリタ実装フレームワーク

  • 抽象構文木を表すクラス
  • 各言語の実行エンジンは、対象言語のコードを
    上記(を継承したクラス)へ変換
  • 抽象構文木はJITの対象となる

遊んでみる

  • 入手
  • 内容物
  • NodeJS on GraalVM
  • AltJava

入手

  • Oracle Labs
    • 「otn graal」で検索
  • 対象OS
    • linux
      bash on windows でもjsは動いた
    • Mac
    • Solaris
  • バージョン
    • 5/20時点では0.22
    • 6/16時点では0.24

内容物

$ ls bin
R		aot-image	graalvm		java		javadoc		node		ruby
Rscript	g			irb			javac	js			npm

なんか色々入ってる!

REPL

$ bin/graalvm --shell
GraalVM MultiLanguage Shell 0.24
Copyright (c) 2013-7, Oracle and/or its affiliates
  JS version 0.9
  R version 0.1
  Ruby version 2.3.3
Usage: 
  Use Ctrl+L to switch language and Ctrl+D to exit.
  Enter -usage to get a list of available commands.
JS> console.log('hello js')
hello js
R> print('hello R')
[1] "hello R"
Ruby> puts 'hello Ruby'
hello Ruby
nil

NodeJS on GraalVM

node

$ bin/node
> var fs = require('fs')
undefined

> fs.read
fs.read          fs.readFile      fs.readFileSync  fs.readSync      fs.readdir       fs.readdirSync   fs.readlink      fs.readlinkSync  

> java.util.Arrays.asList(1, 2, 3, 4)
'[1, 2, 3, 4]'

node.jsのモジュールが一式使える!

Javaクラスにもアクセスできる!

ライブラリ

const lodash = require('lodash')
const FastList      = org.eclipse.collections.impl.list.mutable.FastList;
const UnifiedMap = org.eclipse.collections.impl.map.mutable.UnifiedMap;
const pair             = org.eclipse.collections.impl.tuple.Tuples.pair;

const toJsArray = (vs) => vs.injectInto([], (vs, v) => vs.concat(v));

const javaList = FastList.newListWith(1, 2, 3, 4);
const jsList = toJsArray(javaList);
console.log(jsList)

const javaMap = UnifiedMap.newMapWith(pair('a', 1), pair('b', 2));
const jsMap = lodash.zipObject(
  toJsArray(javaMap.keysView()),
  toJsArray(javaMap.valuesView()));
console.log(jsMap)

ライブラリ

  • npm modules
    一手間掛かるが、ネイティブ拡張も
    • sqlite3
    • node-sass
  • -cp でjavaライブラリも使える
  • さりげなくjsのArrowFunctionがjava8のlambdaとして書けている

NodeJSからFuture

function Task(f) {
    return new java.util.concurrent.Callable(f);
}

const atom = new AtomicInteger();
let count = 0;

const tasks = [1, 2, 3, 3, 3, 3, 3, 3, 4, 5].map(i => 
    Task(() => {
        atom.getAndIncrement();
        count++;
        sleep(i * 1000);
        return Thread.currentThread().getId();
    })
);

真の並列処理がJSに!

JS <=> Ruby

function loop(n) {
  var add = Interop.import("add");
  var i = 0;
  var sum = 0;
  while (i <= n) {
    sum = add(sum, i);
    i = add(i, 1);
  }
  return sum;
}

Interop.eval("application/x-ruby", 
  "def add(a, b) a + b; end;");
Interop.eval("application/x-ruby", 
  "Truffle::Interop.export_method(:add);");

console.log(loop(process.argv[2]));

速度比較

function fibonacci(n) {
  if (n < 2)
    return 1;
  else
    return fibonacci(n-2) + fibonacci(n-1);
}

var res;
for (var i = 30; i < 46; i++){
	var start = new Date();
	res = fibonacci(i);
	var end = new Date();
	log("Input: " + i + " Result: " + res + ", Time: " + (end - start));
}

低いほど優秀

AltJava

$ JAVA_HOME=. scala
scala> :paste
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.vm.PolyglotEngine;

val engine = PolyglotEngine.newBuilder().build();
engine.eval(Source.newBuilder("print('Hello polyglot world JavaScript!');")
  .mimeType("application/javascript").name("").build()).get();
engine.eval(Source.newBuilder("puts 'Hello polyglot world Ruby!'")
  .mimeType("application/x-ruby").name("").build()).get();
engine.eval(Source.newBuilder("print('Hello polyglot world R!');")
  .mimeType("application/x-r").name("").build()).get();

Hello polyglot world JavaScript!
Hello polyglot world Ruby!
[1] "Hello polyglot world R!"
  • GraalVM上でもちゃんとAltJavaは動く

  • groovyshとscala REPLで確認

  • Scala 2.12.1だとエラーでコケる
    2.12.2 にUpdate!

  • 動いたもの
    • websocket
    • reactのシンプルなSSR
      https://github.com/mhart/react-server-example
  • ​動かなかったもの
    • ​vue-cli

他に試したもの

もろもろ

  • GraalとJava9

  • その他言語
  • 参考にしたもの

GraalとJava9

-XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI

手元では未確認

GraalとJava9

  • まだjmod形式ではない
  • 各言語の実行エンジンは同梱されていない
  • TruffleNode, TruffleJSについてはソースも公開されていない
  • そもそもJava9が揉めてる 😇

その他言語

  • python
    https://github.com/securesystemslab/zippy
  • LLVM
    https://github.com/graalvm/sulong
  • groovyあたりがtruffleベースになる日が来るかも
  • なんだかんだ起動と最適化に時間は掛かる
    groovyservみたいな仕組みがあれば…?

参考にしたもの

宣伝

Graal

By yohei yamana