graaljs icon indicating copy to clipboard operation
graaljs copied to clipboard

Documentation of -XX:+UseJVMCICompiler for running GraalVM JavaScript on a stock JDK

Open tupelo-schneck opened this issue 2 years ago • 5 comments

The documentation at https://www.graalvm.org/22.1/reference-manual/js/RunOnJDK/#graalvm-javascript-on-jdk-11 suggests to use -XX:+UseJVMCICompiler.

But the Maven example discussed at https://www.graalvm.org/22.1/reference-manual/js/RunOnJDK/#graalvm-javascript-on-maven-central does not use -XX:+UseJVMCICompiler.

Should one use it or not? The Maven project, even without it, seems to compile its GraalVM JavaScript just fine.

This issue came to our attention because we have a project which can use either Nashorn or GraalVM JavaScript. In the presence of -XX:+UseJVMCICompiler, Nashorn becomes much slower (more than 10x slower). It took us a while to figure out that leaving off -XX:+UseJVMCICompiler would help Nashorn performance without (?) affecting GraalVM JavaScript performance. What is -XX:+UseJVMCICompiler doing?

tupelo-schneck avatar Jul 02 '22 06:07 tupelo-schneck

Hi,

the option controls whether you use the traditional HotSpot compilers (C1/client, C2/server), or a compiler provided via the JVMCI (JVM Compiler Interface) - which would typically be the GraalVM Compiler.

For compatibility (correctness) of the GraalVM JavaScript engine, this flag does not matter. JavaScript will be executed just perfectly whether this flag is set or not.

What might be different is the execution performance of the JavaScript code. Only when the GraalVM Compiler is used to JIT-compile the JavaScript engine, it will execute JavaScript code with good performance. This will be the case by default when you run on GraalVM directly.

On all other platforms, I would definitely recommend to set this flag, just to make sure you have JVMCI (=GraalVM) definitely enabled.

In the presence of -XX:+UseJVMCICompiler, Nashorn becomes much slower (more than 10x slower).

That is indeed an interesting find that we do not expect. That sounds like a bug. Is that something where you can report a runnable example so we can investigate? We do performance tests around that and are not aware of that behavior - typically, GraalVM can execute Nashorn faster than HotSpot can.

Best, Christian

wirthi avatar Jul 04 '22 07:07 wirthi

This is extremely easy to reproduce using https://github.com/graalvm/graal-js-jdk11-maven-demo and running mvn package.

First, note that that project as published uses -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI and does NOT use -XX:+UseJVMCICompiler. Nonetheless running mvn package we can see that GraalVM JavaScript is faster than Nashorn.

If you edit pom.xml to remove -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI and re-run mvn package you will see

[engine] WARNING: The polyglot context is using an implementation that does not support runtime compilation.

This seems to indicate that -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI is sufficient to get compiled GraalVM JavaScript, and that -XX:+UseJVMCICompiler is NOT necessary.

If you edit pom.xml to add -XX:+UseJVMCICompiler, then re-run mvn package, you see that Nashorn is much much slower (while GraalVM JavaScript stays fast).

tupelo-schneck avatar Jul 04 '22 17:07 tupelo-schneck

Hi @tupelo-schneck,

agreed, can see what you mean on that example.

  • EnableJVMCI enables the interface, but does not enable the compiler - except for our own workloads (our Truffle-based language engines, like Graal.js).
  • UseJVMCICompiler uses the compiler provided via JVMCI (GraalVM Compiler, most likely) for all workloads.

That explains why EnableJVMCI by itself has not effect on Nashorn (the compiler provided via JVMCI is not used to compile normal Java workloads, like Nashorn).

For your claim that Nashorn gets slower: can you please double check that and interpret the output as "runtime in milliseconds", i.e. lower is better. On my machine, Graal.js is around 110, Nashorn is around 520 (JDK11.0.14). Enabling JVMCI also for Nashorn makes it move to 230 - meaning Nashorn compiled with the GraalVM compiler is twice as fast as on Stock JDK for this benchmark (but still around 2x slower than Graal.js with GraalVM Compiler). Data from my machine, YMMV.

Best, Christian

wirthi avatar Jul 06 '22 15:07 wirthi

For me it is considerably slower. I am running on an ARM-based M1 Macbook Pro, with macOS Monterey Version 12.4, and Java 11:

openjdk version "11.0.14" 2022-01-18
OpenJDK Runtime Environment Temurin-11.0.14+9 (build 11.0.14+9)
OpenJDK 64-Bit Server VM Temurin-11.0.14+9 (build 11.0.14+9, mixed mode)

Without -XX:+UseJVMCICompiler the output of mvn package begins:

=== Nashorn via javax.script.ScriptEngine ===
Warning: Nashorn engine is planned to be removed from a future JDK release
warming up ...
warmup finished, now measuring
iteration: 183
iteration: 188
iteration: 185
iteration: 179
iteration: 186
iteration: 181
iteration: 183
iteration: 183
iteration: 178
iteration: 176

With -XX:+UseJVMCICompiler the output of mvn package begins:

=== Nashorn via javax.script.ScriptEngine ===
Warning: Nashorn engine is planned to be removed from a future JDK release
warming up ...
warmup finished, now measuring
iteration: 4330
iteration: 3945
iteration: 3969
iteration: 3939
iteration: 3940
iteration: 4007
iteration: 3947
iteration: 3962
iteration: 3929
iteration: 3950

tupelo-schneck avatar Jul 06 '22 16:07 tupelo-schneck

ok, that might be an AARCH64 problem then I guess. Maybe you can try again once GraalVM 22.2 is release in a few weeks, lots of bugfixing went into that recently.

wirthi avatar Jul 06 '22 16:07 wirthi