One, foreword

GraalVM 21.2 has been released, and in this article, we’ll highlight the most obvious, important, and exciting updates in this release.

First, GraalVM version 21.2 can be downloaded from:

  • GraalVM
  • GraalVM Enterprise

GraalVM is made up of several components, and with each release, we are working to improve them. So if you’re interested in a particular component and want a more detailed overview of the changes, see the documentation.

Second, the Native Image

Let’s start with what’s new and noteworthy in Native Image. Back in June, we released new Gradle and Maven plugins for Native Image, along with initial JUnit5 support. It simplifies the process of building your application’s Native Image and allows you to test your code in the Native Image mode in JUnit’s way.



Figure: Sample Gradle output when JUnit tests are run in Native Image mode.

Since the original release, there have been two minor releases that have fixed, improved, and cleaned up various bugs, so if you maintain an application or library that uses Native Image, consider running these two tests to verify the performance in Native Image!

Another improvement is that Native Image now automatically removes unnecessary security providers from the Image. These accessible security providers are detected by the static parser. This means that parameters like –enable-all-security-services are deprecated and will be removed in the future. Can also use the -h: – EnableSecurityServicesFeature completely disable automatic detection and manually register the provider. You can read more details in this document.

A very popular addition in 21.2 is the implementation of class pre-definition to support runtime classLoader.loadClass calls. The required classes that need to be loaded at run time must be provided to static analysis at build time in order to include them in the closed world analysis, and the code pattern that contains classes loaded at any time at run time now works in Native Images just as you would expect.

Another interesting fundamental enhancement of GraalVM 21.2 is that Native Images, built with -h :+AllowVMInspection, now supports writing JFR events in Java. To record JFR events at run time, JFR support and JFR recording must be enabled using the command line options -xx :+FlightRecorder and -xx :StartFlightRecording. There are not many events that actually need to be implemented, but an architecture to implement them or emit them from application code is available.

You can try the following example to see how custom events work in practice:

import jdk.jfr.Event;
import jdk.jfr.Description;
import jdk.jfr.Label;

public class Example {

    @Label("Hello World")
    @Description("Helps programmer getting started")
    static class HelloWorld extends Event {
       @Label("Message")
       String message;
    }

    public static void main(String... args) {
       HelloWorld event = new HelloWorld();
       event.message = "hello, world!";
       event.commit();
    }
}

Build it into the native image and run -xx :+FlightRecorder -xx :StartFlightRecording= “filename=recording.jfr” and you can see what the event looks like in VisualVM:

Compiler update

Each update brings incremental improvements and new optimizations in the compiler that add some performance. Over time, these gains add up and lead to significant performance gains. If you haven’t updated recently, now is a good time to take advantage of all these improvements. In 21.2, a number of interesting optimizations have been added to the compiler. Let’s start with the components that are available in GraalVM Enterprise as part of the Oracle Java SE subscription.

We have improved the loop limit analysis for counting loops, so the compiler also analyzes the control flow before the loop to infer the induction variables. This can result in more uncounted loops, as in the following example, which can be used for advanced optimizations

long i = 0; if (end < 1) return; do { // body i++; } while (i ! = end);

Here, the compiler can prove end > I by combining the information that I was 0 before the loop and end ≥ 1 and use that data to optimize the body of the loop.

We also added a novel strip-mining optimization for non-counting loops that breaks the loop iteration into parts, making them easier to optimize later. This is disabled by default; Use – Dgraal. StripMineNonCountedLoops = true options enable it.

We improved the compilation of code that uses StringBuilder patterns and enhanced support for these patterns by making jdK11-based GraalVM builds aware of compact strings in JDK11.

Then, for the GraalVM community version, a significant improvement in the compiler is the addition of Speculative Guard Movement optimization, which attempts to move loop invariant protection (for example: array bounds checking) from inside the loop to outside the loop. This can significantly improve performance.

In addition, we have improved the safe point elimination mechanism in the long count cycle. The compiler can now eliminate safe points in loops with long induction variables by statically proving that the scope of the induction variable is integer.max_value – integer.min_value. Consider this for loop example:

for (long i = Integer.MIN_VALUE; i< Integer.MAX_VALUE; i++) { // body }

The compiler can now statically prove that I iterates only over the integer range, even if it is a long integer. Therefore, there is no need to consider the integer overflow case, and the loop optimization is better.

In addition, there are some optimizations available in this release that are not enabled by default and are considered experimental. An experimental optimization called Write Sinking attempts to remove the Write out of the loop. You can enable it using -dgraal. OptWriteMotion=true. Another optimization provided in GraalVM Enteprise (not enabled by default) is the novel SIMD (single instruction, multiple Data) vectorization optimization for sequential code. You can experiment with the -dgraal. VectorizeSIMD=true option. If you’re not ready to experiment on your own, stay tuned for an upcoming separate article where we’ll explore in detail what it does for you and how your code can benefit from it.

Four, multilanguage and Truffle framework

Truffle is inspired by a new compile queue and is enabled by default. This new heuristic improves the warm-up time in performance for multilingual runtimes.

Here’s a quick explanation of what it does: Suppose the synthesized JavaScript code below is your application. Loop running 2 functions that have reached the JIT compilation threshold and need to be compiled:

function lowUsage() {
    for (i = 0; i < COMPILATION_THRESHOLD; i++) {
        // Do something
    }
}

function highUsage() {
    for (i = 0; i < 100 * COMPILATION_THRESHOLD; i++) {
        // Do something
    }
}

while(true) {
    lowUsage();
    highUsage();
}

In previous versions of GraalVM, the compile-first algorithms worked on a first-come, first-served basis. This results in the more advantageous order of compiling the lowUsage function first, instead of compiling highUsage first.

Now in GraalVM 21.2, the strategy is more complex than Hotness and takes into account multiple Settings, compiling the first layer faster, prioritizing code previously identified as important with compile history and unoptimize, and a weighted combination of code hotness and simultaneous use of activity. All in all, this should give all GraalVM languages a better warm-up.

There are additional configuration options to adjust the heuristic or to disable its use entirely. Learn more in the documentation.

Another change is that certain API calls when embedded in a multi-language context require a new version of JVMCI, the compiler interface used to plug the compiler into the Java HotSpot VM. All JDK versions of GraalVM distributions include the new JVMCI, but if you are using the GraalVM language with a different JDK and have the GraalVM compiler enabled on the module path, be sure to use the following JDK version that includes JDK-8264016, Ensure full compatibility.

Otherwise using forced Context cancellation (context.close (true)) or interrupt(context.interrupt (Duration)) will throw an error. For the best experience, consider running your application with the Graa lVM distribution or avoid using these apis. Other possible solutions are described in the comments.

Since we are talking about Truffle related changes, there are some exciting updates in GraalVM 21.2 for projects to implement languages and tools on GraalVM. Truffle libraries can now be prepared for precompilation without prior execution. See the ExportLibrary.useForaot and AOT tutorials for more details.

Five, JavaScript,

The JavaScript implementation continues to add and update implementations of the latest proposals, such as new Set methods, experimental operator overloading support, or RegExp matching index proposals. You can find detailed information on how to enable these features in the release notes.

Most importantly, graal.js enhances the development experience by tracking unhandled Promise Rejections options in the multi-language Context. By default, this option is set to None and will not track unhandled Promise Rejections, but you can configure it with the js.unhandled-rejections option to make your development easier.

Six, Ruby

Ruby, as always, has undergone a continuous series of compatibility and performance improvements. A very influential addition is the ability to precisely invalidate Ruby methods and constants by using a name-by-name and class-by-class assumption. When loading Ruby code, because of Ruby semantics, methods are added one by one, and a lot of code is executed when loading files. Depending on the assumptions of each class (which is how it behaves in other Ruby implementations and TruffleRuby before this change), it invalidates all call sites that call methods of that class. By precise invalidation, it only invalidates the call site where the next call actually requires another method to be called. This improves the warm-up of real-world code.

With these changes, we updated Ruby 2.7.3, except for the resolvstdlib update (resolv bug in 2.7.3). We also added a new TruffleRuby: : the ConcurrentMap data structure, used for ruby concurrency.

For many other changes and fixes, see the release notes.

Seven, Python

In this release, we implement a faster _pickle than the pure Python version, making serialization faster.

Improved interoperability support with other languages to make dict types work the way you expect them to, now implemented using Truffle hashing.

As always, a lot of work is focused on performance improvements, especially during warm-up and sharing engine configurations!

There are also compatibility improvements. See the release notes or more details.

LLVM Bitcode runtime

There are some C++ related improvements in 21.2. We fixed an issue where the LLVM toolchain did not work properly in C on MacOS 11.3. We also added support for C virtual calls through cross-language interoperability.

The management model in GraalVM Enterprise has also been improved. We updated MUSL LIBC to version 1.2.2 and improved compatibility with the existing native code base by adding support for pThreads and pThread synchronization primiples in managed mode.

Nine, FastR

FastR continues to work on compatibility, improving its support for software packages in the 2021-02-01 CRAN snapshot:

  • Test partial support for 3.0.1.
  • Supports Tibble 3.0.6, VCTRS 0.3.6, and data.table 1.13.6.
  • Support for DPLYr 1.0.3, GGplot 3.3.3, and Knitr 1.31 is in the works.

If you are interested in support for a specific package, please contact us!

Ten, WebAssembly

You can see that we have made many compatibility improvements to the WebAssembly runtime and some bug fixes to pass the tests on as many NPM modules as possible that use WebAssembly.

Java on Truffle

An important addition to GraalVM 21.2 for Java on Truffle is the new Hotswap plug-in API, which allows code to be reloaded without restarting the running application. The API is designed to allow framework developers better control over changes in the feedback application in response to source code editing in the IDE. This is done by setting up appropriate hooks, and the main design principle is that you can register the various HotSwap listeners that will be triggered on the specified HotSwap event. For example, when a service provider’s implementation changes, it can rerun static initializers, run generic post-hot swap callbacks or hooks.

The most surprising thing is that these apis consist of plain Old Java calls — easier to integrate and maintain than any solution based on bytecode operations.

Check out the plug-in API documentation for more details.

Another very popular improvement to 21.2 is better bytecode scheduling, which can make the interpreter Java uses on Truffle about 15-30% faster. Interpreter speed is a very important factor affecting the rate of application warm-up.

21.2 also improved the Java implementation on the Truffle object Map, Map. The Entry of the List, the Iterator or Iterable with other languages (including Java host code) interoperability.

Xii. Tools

VisualVM has received a number of notable improvements, including support for JDK 17 and the ability to control functionality from the command line or other external tools. The latter enables seamless integration between VisualVM and VSCode with GraalVM extensions installed. You can add IDE configuration integration with VisualVM to analyze your application.



Diagram: Notice the VisualVM TAB in the lower left corner, which contains actions that can be performed directly from VS Code.

VisualVM can now also save JFR records from live Java processes, and there is a new Lock Contention view in the Profiler TAB. So if you’re using VisualVM today for your everyday analysis needs, it’s more powerful than ever.

Xiii. Documents

Last but not least, we refactored the GraalVM documentation on our website. It can now be found in the main project on GitHub.

This means it’s easier than ever to contribute to GraalVM and improve the lives of many other developers in the ecosystem. If you notice documents that may be using clarification or incomplete descriptions of your favorite features or adjustment options, please consider sharing your expertise and help with the project through the Pull Request! If in doubt, here’s a short guide on how to do just that: Participate in document contributions.

Please note that the GraalVM Enterprise documentation is available at docs.oracle.com.

As with each release, we would like to thank the GraalVM community for all the collaboration, feedback and discussions, as well as sharing how you use GraalVM.

Please do not hesitate to let us know any and all feedback! There are multiple channels to reach the team. Choose the one that works best for you: Slack, GitHub or Twitter, or send us an email.

The translator said.

Hello, everyone. I am Rumeng Technology Spring brother (micA open source author). I would like to thank Zhang Yadong (JustAuth open source author), Wu Tiangou, Lao Ye and other students who participated in the translation and proofreading together at night. We have exported and translated several GraalVM and Spring Native articles:

List of articles:

  • GraalVM quick reference
  • T-io GraalVM native executable program combat

Translation is not easy, please help to share with more students, thank you!! For more wonderful articles, please follow me.