Jul 1, 2024
Jul 1, 2024
N/A Views
MD

前記事ではChicoryを使ってwasmをJava上で実行しましたが、
同じことがGraalVM (GraalWasm)でもできました。

前記事の内容をGraalWasmでやり直します。

以下の依存ライブラリを追加することでJavaアプリ上でwasmの読み込み・実行ができるようになります。

    <dependency>
        <groupId>org.graalvm.polyglot</groupId>
        <artifactId>polyglot</artifactId>
        <version>24.0.1</version>
    </dependency>
    <dependency>
        <groupId>org.graalvm.polyglot</groupId>
        <artifactId>wasm-community</artifactId>
        <version>24.0.1</version>
        <type>pom</type>
    </dependency>

サンプルのwasmファイルをWATファイルから作ります。次のファイルSumSquared.watを作ります。

二つのi32のパラメータを加算して二乗した値を返します。

(module
  (func (export "SumSquared")
    (param $value_1 i32) (param $value_2 i32)
    (result i32)
    (local $sum i32)

    (i32.add (local.get $value_1) (local.get $value_2))
    local.set $sum
    (i32.mul (local.get $sum) (local.get $sum))
  )
)

Tip

入門WebAssemblyに掲載されているサンプルコードを使いました。

入門WebAssembly

wat2wasmでwasmに変換します。

wat2wasm SumSquared.wat 

SumSquared.wasmが生成されます。このwasmをJavaで読み込んで実行します。

package org.example;

import java.io.IOException;
import java.net.URL;
import java.util.Objects;

import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Source;
import org.graalvm.polyglot.Value;

public class Main {
    public static void main(String[] args) throws IOException {
        try (Context context = Context.newBuilder().allowAllAccess(true).build()) {
            context.initialize("wasm");
            URL resource = Main.class.getClassLoader().getResource("SumSquared.wasm");
            Source source = Source.newBuilder("wasm", Objects.requireNonNull(resource)).name("main").build();
            context.eval(source);
            Value sumSquared = context.getBindings("wasm").getMember("main").getMember("SumSquared");
            Value result = sumSquared.execute(2, 3);
            System.out.println("Result: " + result.asInt()); // should print "Result: 25" (= (2 + 3)^2)
        }
    }
}

Javaアプリを実行します。

$ mvn -q compile exec:java -Dexec.mainClass=org.example.Main
Result: 25

このアプリは、RuntimeがGraalVMでなくとも動作します。 最適化の違いはこちらのドキュメントを参照してください。

RuntimeがGraalVMではない場合、次のようなWARNログが出力されます。

[To redirect Truffle log output to a file use one of the following options:
* '--log.file=<path>' if the option is passed using a guest language launcher.
* '-Dpolyglot.log.file=<path>' if the option is passed using the host Java launcher.
* Configure logging using the polyglot embedding API.]
[engine] WARNING: The polyglot engine uses a fallback runtime that does not support runtime compilation to native code.
Execution without runtime compilation will negatively impact the guest application performance.
The following cause was found: JVMCI is not enabled for this JVM. Enable JVMCI using -XX:+EnableJVMCI.
For more information see: https://www.graalvm.org/latest/reference-manual/embed-languages/#runtime-optimization-support.
To disable this warning use the '--engine.WarnInterpreterOnly=false' option or the '-Dpolyglot.engine.WarnInterpreterOnly=false' system property.

次のJVMオプションを加えることでログを抑止できます。

MAVEN_OPTS="-XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Dpolyglot.engine.WarnInterpreterOnly=false" mvn -q compile exec:java -Dexec.mainClass=org.example.Main

全ソースコードはこちらです。

Chicory、GraalWasm、wasmtime-javaでパフォーマンスの比較がしたいですね。

Found a mistake? Update the entry.
Share this article: