Skip to content

Commit 0918c16

Browse files
committed
[GR-42584] Updated GraalWasm memory overhead benchmarks.
PullRequest: graal/13240
2 parents 29a7cd1 + 255d774 commit 0918c16

File tree

18 files changed

+741
-35
lines changed

18 files changed

+741
-35
lines changed

wasm/README.md

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
# GraalWasm
32

43
GraalWasm is a WebAssembly engine implemented in GraalVM.
@@ -9,7 +8,6 @@ We are working hard towards making GraalWasm more stable and more efficient,
98
as well as to implement various WebAssembly extensions.
109
Feedback, bug reports, and open-source contributions are welcome!
1110

12-
1311
## Building GraalWasm
1412

1513
### Prerequisites
@@ -25,10 +23,12 @@ To build GraalWasm, you need to follow the standard workflow for Graal projects.
2523
We summarize the basic steps below:
2624

2725
1. Create a new folder where your repositories `mx` and `graal` should be located:
26+
2827
```bash
2928
$ mkdir graalvm
3029
$ cd graalvm
3130
```
31+
3232
2. Clone `mx` and add it to the `PATH`:
3333

3434
```bash
@@ -50,6 +50,7 @@ $ export JAVA_HOME=[path to JDK]
5050
```
5151

5252
5. Build the project:
53+
5354
```bash
5455
$ mx --dy /truffle,/compiler build
5556
```
@@ -61,7 +62,8 @@ which contains the GraalWasm implementation.
6162

6263
### Test setup
6364

64-
The `build` command will also create the `wasm-tests.jar`, which contains the main test cases. To run these tests, the WebAssembly binary toolkit is needed.
65+
The `build` command will also create the `wasm-tests.jar`, which contains the main test cases. To run these tests, the
66+
WebAssembly binary toolkit is needed.
6567

6668
1. Download the binary of the [WebAssembly binary toolkit(wabt)](https://github.com/WebAssembly/wabt) and extract it.
6769
2. Set `WABT_DIR`:
@@ -73,6 +75,7 @@ $ export WABT_DIR=[path to wabt]/bin
7375
### Run basic tests
7476

7577
After building GraalWasm, the `WasmTestSuite` can be run as follows:
78+
7679
```bash
7780
$ mx --dy /truffle,/compiler --jdk jvmci unittest \
7881
-Dwasmtest.watToWasmExecutable=$WABT_DIR/wat2wasm \
@@ -81,7 +84,7 @@ $ mx --dy /truffle,/compiler --jdk jvmci unittest \
8184
```
8285

8386
To run a specific test, you can specify a regex for its name with the `testFilter` flag.
84-
Here is an example command that runs all the tests that mention `branch` in their name:
87+
Here is an example command that runs all the tests that mention `branch` in their name:
8588

8689
```bash
8790
$ mx --dy /truffle,/compiler --jdk jvmci unittest \
@@ -112,7 +115,8 @@ To compile these programs, you will need to install additional dependencies on y
112115

113116
To build these additional tests and benchmarks, you need to:
114117

115-
1. Install the [Emscripten SDK](https://emscripten.org/docs/getting_started/downloads.html). We currently test against Emscripten **1.39.13**.
118+
1. Install the [Emscripten SDK](https://emscripten.org/docs/getting_started/downloads.html). We currently test against
119+
Emscripten **1.39.13**.
116120

117121
```bash
118122
$ cd [preferred emsdk install location]
@@ -186,7 +190,6 @@ We currently have the following extra test suites:
186190
- `CSuite` -- set of programs written in the C language
187191
- `WatSuite` -- set of programs written in textual WebAssembly
188192

189-
190193
### Run benchmarks
191194

192195
The GraalWasm project includes a custom JMH-based benchmark suite,
@@ -195,7 +198,8 @@ The benchmark programs consist of several special functions,
195198
most notably `benchmarkRun`, which runs the body of the benchmark.
196199
The benchmarks are kept in the `src/com.oracle.truffle.wasm.benchcases` MX project.
197200

198-
For the benchmarks to run `NODE_DIR` has to be set. You can use the node version that is part of Emscripten, for example:
201+
For the benchmarks to run `NODE_DIR` has to be set. You can use the node version that is part of Emscripten, for
202+
example:
199203

200204
```bash
201205
$ export NODE_DIR=[path to emsdk]/node/14.15.5_64bit/bin
@@ -246,6 +250,60 @@ We currently have the following benchmark suites:
246250
- `CMicroBenchmarkSuite` -- set of programs written in C
247251
- `WatBenchmarkSuite` -- set of programs written in textual WebAssembly
248252

253+
## Extracting the internal GraalWasm Memory Layout based on a given WebAssembly program
254+
255+
GraalWasm contains a tool for extracting the internal memory layout for a given WebAssembly application. This is useful
256+
for detecting the causes of memory overhead.
257+
258+
To execute the memory layout extractor, run:
259+
260+
```bash
261+
$ mx --dy /compiler wasm-memory-layout -- [wasm-file]
262+
```
263+
264+
This prints the memory layout tree of the given file to the console. The application provides additional options:
265+
266+
* --warmup-iterations: to set the number of warmup iterations.
267+
* --entry-point: to set the entry point of the application. This is used to perform linking
268+
* --output: to extract the memory layout into a file instead of the console.
269+
270+
You can also pass all other options available in GraalWasm such as `--wasm.Builtins=wasi_snapshot_preview1`.
271+
272+
The resulting tree represents a recursive representation of the Objects alive in GraalWasm starting from
273+
the `WasmContext`. The output looks similar to this:
274+
275+
```
276+
-context: 6598280 Byte [100%]
277+
-equivalenceClasses: 1320 Byte [0%]
278+
-table: 80 Byte [0%]
279+
-table[0]: 384 Byte [0%]
280+
-key: 72 Byte [0%]
281+
-paramTypes: 24 Byte [0%]
282+
-resultTypes: 24 Byte [0%]
283+
-next: 280 Byte [0%]
284+
-key: 64 Byte [0%]
285+
-paramTypes: 24 Byte [0%]
286+
-resultTypes: 16 Byte [0%]
287+
-next: 184 Byte [0%]
288+
-key: 56 Byte [0%]
289+
-paramTypes: 16 Byte [0%]
290+
-resultTypes: 16 Byte [0%]
291+
-next: 96 Byte [0%]
292+
-key: 64 Byte [0%]
293+
-paramTypes: 24 Byte [0%]
294+
-resultTypes: 16 Byte [0%]
295+
-table[2]: 208 Byte [0%]
296+
-key: 72 Byte [0%]
297+
-paramTypes: 24 Byte [0%]
298+
-resultTypes: 24 Byte [0%]
299+
-next: 104 Byte [0%]
300+
...
301+
```
302+
303+
The **names** represent the names of fields in classes. For example `equivalenceClasses` is a field in `WasmContext`.
304+
The **values** next to the names represent the absolute amount of memory in bytes while the number in brackets represent
305+
the relative contribution to the overall memory overhead.
306+
**Names** with indices represent array entries such as `table[0]`.
249307

250308
## Running WebAssembly programs using a launcher
251309

@@ -287,7 +345,6 @@ $ graalvm/bin/wasm --Builtins=memory,env:emscripten floyd.wasm
287345
In this example, the flag `--Builtins` specifies built-in modules
288346
that the Emscripten toolchain assumes.
289347

290-
291348
## Embedding GraalWasm inside other programs
292349

293350
GraalWasm can be accessed programmatically with the Polyglot API,
@@ -300,16 +357,16 @@ from a Java application:
300357
import org.graalvm.polyglot.*;
301358
import org.graalvm.polyglot.io.ByteSequence;
302359

303-
byte[] binary = readBytes("example.wasm"); // You need to load the .wasm contents into a byte array.
304-
Context.Builder contextBuilder = Context.newBuilder("wasm");
305-
Source.Builder sourceBuilder = Source.newBuilder("wasm", ByteSequence.create(binary), "example");
306-
Source source = sourceBuilder.build();
307-
Context context = contextBuilder.build();
360+
byte[]binary=readBytes("example.wasm"); // You need to load the .wasm contents into a byte array.
361+
Context.Builder contextBuilder=Context.newBuilder("wasm");
362+
Source.Builder sourceBuilder=Source.newBuilder("wasm",ByteSequence.create(binary),"example");
363+
Source source=sourceBuilder.build();
364+
Context context=contextBuilder.build();
308365

309-
context.eval(source);
366+
context.eval(source);
310367

311-
Value mainFunction = context.getBindings("wasm").getMember("example").getMember("_main");
312-
mainFunction.execute();
368+
Value mainFunction=context.getBindings("wasm").getMember("example").getMember("_main");
369+
mainFunction.execute();
313370
```
314371

315372
For more polyglot-related examples, consult the documentation at the

wasm/mx.wasm/mx_wasm.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,3 +577,14 @@ def wasm(args, **kwargs):
577577
"org.graalvm.wasm.launcher",
578578
] + (['tools:CHROMEINSPECTOR', 'tools:TRUFFLE_PROFILER', 'tools:INSIGHT'] if mx.suite('tools', fatalIfMissing=False) is not None else []))
579579
return mx.run_java(vmArgs + path_args + ["org.graalvm.wasm.launcher.WasmLauncher"] + wasmArgs, **kwargs)
580+
581+
@mx.command(_suite.name, "wasm-memory-layout")
582+
def wasm_memory_layout(args, **kwargs):
583+
"""Run WebAssembly memory layout extractor."""
584+
mx.get_opts().jdk = "jvmci"
585+
vmArgs, wasmArgs = mx.extract_VM_args(args, True)
586+
path_args = mx.get_runtime_jvm_args([
587+
"org.graalvm.wasm",
588+
"org.graalvm.wasm.memory",
589+
])
590+
return mx.run_java(vmArgs + path_args + ["org.graalvm.wasm.memory.MemoryLayoutRunner"] + wasmArgs, **kwargs)

wasm/mx.wasm/suite.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,16 @@
6969
},
7070
],
7171
},
72-
72+
"libraries": {
73+
"JOL": {
74+
"sha1" : "553a2ba27f58b71e7efb545d7d3c657761f5b596",
75+
"maven" : {
76+
"groupId" : "org.openjdk.jol",
77+
"artifactId" : "jol-core",
78+
"version" : "0.16",
79+
},
80+
},
81+
},
7382
"projects" : {
7483
"org.graalvm.wasm" : {
7584
"subDir" : "src",
@@ -195,6 +204,17 @@
195204
"annotationProcessors" : ["mx:JMH_1_21"],
196205
"testProject" : True,
197206
},
207+
208+
"org.graalvm.wasm.memory" : {
209+
"subDir": "src",
210+
"sourceDirs" : ["src"],
211+
"dependencies": [
212+
"org.graalvm.wasm",
213+
"JOL",
214+
],
215+
"javaCompliance": "11+",
216+
"defaultBuild": False,
217+
}
198218
},
199219

200220
"externalProjects": {

wasm/src/org.graalvm.wasm.benchmark/src/org/graalvm/wasm/benchmark/MemoryFootprintBenchmarkRunner.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@
9292
public class MemoryFootprintBenchmarkRunner {
9393
// We currently hardcode the path to memory-footprint-related tests. We might in the future
9494
// generalize this to include more paths, if that turns out necessary.
95-
private static String BENCHCASES_TYPE = "bench";
96-
private static String BENCHCASES_RESOURCE = "wasm/memory";
95+
private static final String BENCHCASES_TYPE = "bench";
96+
private static final String BENCHCASES_RESOURCE = "wasm/memory";
9797

9898
public static void main(String[] args) throws IOException, InterruptedException {
9999
if (args[0].equals("--list")) {
@@ -108,11 +108,20 @@ public static void main(String[] args) throws IOException, InterruptedException
108108
final int warmup_iterations = Integer.parseInt(args[1]);
109109
final int result_iterations = Integer.parseInt(args[3]);
110110

111-
for (final String caseSpec : Arrays.copyOfRange(args, 4, args.length)) {
111+
// Support debugging
112+
int offset = 4;
113+
if (args[4].equals("Listening")) {
114+
offset = 11;
115+
}
116+
117+
for (final String caseSpec : Arrays.copyOfRange(args, offset, args.length)) {
112118
final WasmCase benchmarkCase = collectFileCase(BENCHCASES_TYPE, BENCHCASES_RESOURCE, caseSpec);
113119
assert benchmarkCase != null : String.format("Test case %s/%s not found.", BENCHCASES_RESOURCE, caseSpec);
114120

115121
final Context.Builder contextBuilder = Context.newBuilder(WasmLanguage.ID);
122+
contextBuilder.allowExperimentalOptions(true);
123+
contextBuilder.option("wasm.Builtins", "go");
124+
contextBuilder.option("wasm.MemoryOverheadMode", "true");
116125

117126
final List<Double> results = new ArrayList<>();
118127

@@ -123,6 +132,7 @@ public static void main(String[] args) throws IOException, InterruptedException
123132

124133
// The code we want to profile:
125134
benchmarkCase.getSources().forEach(context::eval);
135+
context.getBindings(WasmLanguage.ID).getMember("main").getMember("run");
126136

127137
final double heapSizeAfter = getHeapSize();
128138
final double result = heapSizeAfter - heapSizeBefore;

0 commit comments

Comments
 (0)