We’re really happy to announce that the 20.1.0 release of GraalVM is available and ready to make your applications run faster.
GraalVM 20.1 is a feature release from the master branch and includes a number of improvements across all the components of the distribution. We’re grateful for all the support from various teams and individual contributors for helping make this release of GraalVM the best it can be. Thanks for raising issues if something doesn’t work the way you expect, suggesting useful features, spreading the word about GraalVM, and contributing to the project on GitHub.
One new feature is improved Kotlin coroutine support in the GraalVM compiler. In the past the GraalVM compiler didn’t know how to process irreducible loops in Java bytecode. This is a particularly rare pattern in the bytecode where you can jump in the middle of the loop code without visiting the loop entrance. This pattern doesn’t occur when you compile Java or Scala, Groovy or Clojure (and I’m sure other languages), but it might happen if you run a bytecode obfuscator or use Kotlin coroutines inside loops.
Not being able to process code like that meant that the compiler has to bail on compiling the whole unit if it encountered this pattern, relying on the interpreter to run the code there. The GraalVM compiler in 20.1 can process code like that and it both speeds it up considerably compared to previous versions and enables processing code like that in the native images!
If we look at some of the benchmarks from the kotlinx.coroutines project we can see significant improvements. Clone the project, run it with
gradle — no-daemon cleanJmhJar jmh -Pjmh="scrabble", and see for yourself (the numbers are time per operation, so lower is better):
# GraalVM Enterprise 20.0
Benchmark Mode Cnt Score Error Units
FlowPlaysScrabbleBase.play avgt 7 256.648 ± 3.574 ms/op
FlowPlaysScrabbleOpt.play avgt 7 114.249 ± 1.465 ms/op
RxJava2PlaysScrabble.play avgt 7 121.020 ± 3.820 ms/op
RxJava2PlaysScrabbleOpt.play avgt 7 35.641 ± 6.984 ms/op
SaneFlowPlaysScrabble.play avgt 7 75.944 ± 8.367 ms/op
SequencePlaysScrabble.play avgt 7 16.180 ± 4.012 ms/op
# GraalVM Enterprise 20.1
Benchmark Mode Cnt Score Error Units
FlowPlaysScrabbleBase.play avgt 7 85.204 ± 14.663 ms/op
FlowPlaysScrabbleOpt.play avgt 7 21.275 ± 6.202 ms/op
RxJava2PlaysScrabble.play avgt 7 121.277 ± 24.748 ms/op
RxJava2PlaysScrabbleOpt.play avgt 7 37.277 ± 8.069 ms/op
SaneFlowPlaysScrabble.play avgt 7 16.945 ± 3.285 ms/op
SequencePlaysScrabble.play avgt 7 15.811 ± 4.544 ms/op
The benchmarks that don’t use coroutines in loops didn’t change much, but on the ones which do (e.g.,
FlowPlaysScrabbleOpt) GraalVM 20.1 is about 4 times faster!
There are more improvements to the GraalVM compiler. One notable example is a major improvement on JDK 11 based GraalVM when fast locking is in use. GraalVM 20.1 improves its score on many benchmarks, sometimes as dramatically as making it almost 40% faster than before. For example, on the
log-regression benchmark from the Renaissance benchmark suite:
Better user experience for native image
The GraalVM native image utility got a lot of attention in this release. One of the most notable pieces of feedback we get about GraalVM native image is that the compilation times aren’t great. Indeed, the native image utility needs to analyze all the classes in your application and figure out which ones need to be included in the executable, which takes quite a bit of time and memory.
To address this issue in 20.1 we added a new mechanism, called “saturated type flows”, to make the analysis faster. It is not enabled by default yet, so you need to turn it on manually with the
-H:+RemoveSaturatedTypeFlows command line option.
The build process with it enabled can be significantly faster. For example, if we look at compiling the Spring Petclinic example to a native image using spring-graalvm-native, the build process is now approximately 25% faster and uses 25% less memory than before.
Speaking of Spring, the work on being able to run Spring applications as GraalVM native images progresses nicely and there are a number of issues related to it which got fixed in 20.1. You can find them on GitHub.
Another excellent quality of life improvement for native images that landed in 20.1 is the ability to include signal handlers in the executable. You can now specify the
--install-exit-handlers option and the application will register a default
SIGTERM handler. This helps the most when you’re running native images as entrypoints in Docker, where the native image now won’t prevent Docker container being stopped with
Ctrl + C like before.
Improvements in languages and tools
Python was updated to 3.8.2 and includes a lot of performance improvements for the Python primitives — Lists, Dicts, tuples. Also NumPy should now work on MacOS now using the same
ginstall setup as on Linux.
TruffleRuby now has nightly builds, a much faster
bundle install, and better compatibility with C extensions thanks to using the same C type as CRuby for
Our R implementation now includes GCC runtime libraries on both Linux and MacOS. And it also removes GFortran as the requirement for running, which simplifies installation of CRAN packages a lot.
VisualVM now has the ability to show memory consumption by
libgraal, which can help discover issues with misconfiguring it.
— GraalVM team