Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .github/workflows/graalwasm-micronaut-excelize.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Test GraalWasm Micronaut Excelize Demo

on:
push:
paths:
- 'graalwasm/graalwasm-micronaut-excelice/**'
- '.github/workflows/graalwasm-micronaut-excelice.yml'
pull_request:
paths:
- 'graalwasm/graalwasm-micronaut-excelice/**'
- '.github/workflows/graalwasm-micronaut-excelice.yml'
workflow_dispatch:

permissions:
contents: read

jobs:
run:
name: 'graalwasm-micronaut-excelice'
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4

- uses: graalvm/setup-graalvm@v1
with:
java-version: '24.0.0'
distribution: 'graalvm'
github-token: ${{ secrets.GITHUB_TOKEN }}
cache: 'maven'

- name: Package 'graalwasm-micronaut-excelice'
run: |
cd graalwasm/graalwasm-micronaut-excelice
./mvnw --no-transfer-progress clean package

- name: Run and Test Excelize App
run: |
cd graalwasm/graalwasm-micronaut-excelice
./mvnw test &
sleep 10
curl --fail-with-body --silent --dump-header - -o /dev/null http://localhost:8080
38 changes: 38 additions & 0 deletions graalwasm/graalwasm-onnx-runtime/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/

### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr

### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/

### VS Code ###
.vscode/

### Mac OS ###
.DS_Store
21 changes: 21 additions & 0 deletions graalwasm/graalwasm-onnx-runtime/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
### ONNX-WASM on GraalVM

This project is a GraalVM-based reimplementation of the [ONNX Runtime Web Quick Start Demo](https://github.com/microsoft/onnxruntime-inference-examples/blob/main/js/quick-start_onnxruntime-web-script-tag/index.html)
provided by Microsoft.

It demonstrates how to run ONNX models using the onnxruntime-web package inside a Java application via GraalVM Polyglot features. The core idea is to evaluate ONNX models entirely in the browser or on the JVM using WebAssembly (WASM) and JavaScript, tightly integrated with Java code.


### Technologies Used

GraalVM (Java + JavaScript + WASM support)
onnxruntime-web (ONNX Runtime WASM backend)
Java (with Maven or Gradle)
Polyglot Context (GraalVM)
WASM + JavaScript bridge

### How It Works

Java loads a JavaScript wrapper (ort.js) that utilizes onnxruntime-web.
ONNX model is passed as a buffer or loaded inside JS using polyglot exports.
Inference is triggered through JavaScript and results returned to Java via Polyglot.
65 changes: 65 additions & 0 deletions graalwasm/graalwasm-onnx-runtime/dependency-reduced-pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>onnx</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<source>17</source>
<target>17</target>
<annotationProcessorPaths>
<path>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.37</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer>
<mainClass>org.openjdk.jmh.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.graalvm.polyglot</groupId>
<artifactId>wasm</artifactId>
<version>24.2.0</version>
<type>pom</type>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>wasm</artifactId>
<groupId>org.graalvm.wasm</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<properties>
<maven.compiler.target>23</maven.compiler.target>
<maven.compiler.source>23</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
87 changes: 87 additions & 0 deletions graalwasm/graalwasm-onnx-runtime/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.example</groupId>
<artifactId>onnx</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.source>25</maven.compiler.source>
<maven.compiler.target>25</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<graal.languages.version>25.0.0-SNAPSHOT</graal.languages.version>
</properties>
<dependencies>
<dependency>
<groupId>org.graalvm.polyglot</groupId>
<artifactId>polyglot</artifactId>
<version>${graal.languages.version}</version>
</dependency>
<dependency>
<groupId>org.graalvm.polyglot</groupId>
<artifactId>js</artifactId>
<version>${graal.languages.version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.graalvm.polyglot</groupId>
<artifactId>wasm</artifactId>
<version>${graal.languages.version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.37</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.37</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<source>17</source>
<target>17</target>
<annotationProcessorPaths>
<path>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.37</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.1</version>
<executions>
<execution>
<phase>package</phase>
<goals><goal>shade</goal></goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.openjdk.jmh.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>

</plugins>
</build>


</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package org.example;

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


import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;

import java.util.Map;
import java.util.Objects;


public class Main {
public static Map<String, String> getLanguageOptions() {
Map<String, String> options = new HashMap<>();
options.put("engine.CompilationFailureAction", "Diagnose");
options.put("js.webassembly", "true");
options.put("js.commonjs-require", "true");
return options;
}
public static void main(String[] args) throws IOException {
Context context = Context.newBuilder("js","wasm")
.options(getLanguageOptions())
.allowAllAccess(true)
.build();
byte[] wasmBinary = Files.readAllBytes(Paths.get("src/main/resources/ort-wasm.wasm"));
context.getBindings("js").putMember("modelWasmBuffer",wasmBinary);
context.eval("js","""
if (typeof performance === 'undefined') {
globalThis.performance = {
now: () => Date.now()
};
}
globalThis.self = globalThis;
""");
context.eval(Source.newBuilder("js", Objects.requireNonNull(Main.class.getResource("/ort.js")))
.build());
byte[] modelData = Files.readAllBytes(Paths.get("src/main/resources/modeel.onnx"));

context.eval(Source.newBuilder("js", Objects.requireNonNull(Main.class.getResource("/script.js")))
.build());
int [] DataX = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
int [] DataY = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120};

GenerateFunction genratedFunction = context.getBindings("js").getMember("predict").as(GenerateFunction.class);
Prediction prediction = genratedFunction.apply(modelData, DataX , DataY);
prediction.then(result -> {

System.out.println("results from java side : "+result[0].getArrayElement(0).asInt());
return null;
});
}

@FunctionalInterface
public interface GenerateFunction {
Prediction apply(byte[] model , int [] DataX , int [] DataY);
}

public interface Prediction {
void then(ProxyExecutable callback);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.example;

public class MainBenchmark {
public static void main(String[] args) throws Exception {
org.openjdk.jmh.Main.main(args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.example;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.concurrent.TimeUnit;

@Warmup(iterations = 6, time = 10)
@Measurement(iterations = 6, time = 30)
@Fork(1)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
public class OnnxBenchmark {

private OnnxRunner runner;
private byte[] modelData;

@Setup(Level.Trial)
public void setup() throws Exception {
runner = new OnnxRunner();
modelData = Files.readAllBytes(Paths.get("src/main/resources/modeel.onnx"));
}

@Benchmark
public void benchmarkPredict(Blackhole blackhole) {
runner.predict(modelData,blackhole);
}
}
Loading