Try using GraalVM

Preface

Since this article focuses on the performance of GraalVM, and the performance when using Graal as a JIT compiler, this article does not touch on one of the features of GraalVM, such as native image and multiple languages.

environment

What is GraalVM

It is a VM equipped with Graal, the latest JIT compiler written in Java. According to the GraalVM Official Document, Graal has the following features.

Graal itself is implemented in java, which can significantly speed up Java programs with powerful optimizations such as partial escape analysis not possible with standard JIT compilers.

How fast it will actually be will be described later.

By the way, if it is troublesome to change the VM, it seems that you can change only the JIT compiler to Graal by adding the following options. However, please note that according to Reference, it can only be used with JDK10 or later.

-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler

GraalVM architecture

It has the following architecture. Compared to the standard JVM, the C2 part has been replaced by the Graal compiler. The Graal and JVMCI parts are implemented in Java.

Graal.png

JVMCI A compiler implemented in Java that can be used in the JVM as a dynamic compiler.

https://openjdk.java.net/jeps/243

Actually use

Installation

Follow the instructions in the Official Documentation. For macOS, here

Compare speed with OpenJDK standard VM and GraalVM

A more detailed speed comparison can be found in this article.

Run a program that spits out the top 10 word types contained in the 275Mb GraalTest.txt.


$ ll
total 65368
-rw-r--r--  1 kinsho  staff   202B  5 31 14:04 FibTest.scala
-rw-r--r--  1 kinsho  staff   1.9K  5 31 17:13 GraalTest.scala
-rw-r--r--  1 kinsho  staff   275M  5 31 16:54 GraalTest.txt
drwxr-xr-x  4 kinsho  staff   128B  5 31 14:28 project
drwxr-xr-x  5 kinsho  staff   160B  5 31 14:35 target

Use GraalVM installed above as a VM.

$ java -version
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (build 1.8.0_252-b09)
OpenJDK 64-Bit Server VM GraalVM CE 20.1.0 (build 25.252-b09-jvmci-20.1-b02, mixed mode)

Below, the executable program

GraalTest.scala


import java.io.File

import scala.annotation.tailrec
import scala.io.BufferedSource

object GraalTest extends App {

  val fileName: String = "GraalTest.txt"
  val encode: String = "UTF-8"

  val source: BufferedSource = scala.io.Source.fromFile(fileName, encode)
  val lines: Iterator[String] = source.getLines()
  val sortedTextList = lines.toList.mkString(" ").split(" ").sorted.toList
  val value = createMap(sortedTextList)
  val top10Words = value.toList.sortBy(_._2).reverse.take(10)

  def createMap(wordList: List[String]): Map[String, Long] = {
    @tailrec
    def loop(list: List[String], acc: Map[String, Long]): Map[String, Long] = {
      wordList match {
        case head :: tail if acc.isEmpty => {
          loop(tail, acc + (head -> 1L))
        }
        case head :: tail => {
          acc.get(head) match {
            case Some(value) => {
              loop(tail, acc.updated(head, value + 1L))
            }
            case None => {
              loop(tail, acc + (head -> 1L))
            }
          }
        }
        case head :: Nil => {
          acc.get(head) match {
            case Some(value) => {
              acc.updated(head, value + 1L)
            }
            case None => {
              acc + (head -> 1L)
            }
          }
        }
      }
    }
    loop(wordList, Map.empty[String, Long])
  }
}

result

With OpenJDK's standard VM! ??

For comparison, let's run the program using OpenJDK's standard JIT compiler. If you specify -XX: -Use JVMCI Compiler, you can use the standard JIT compiler of OpenJDK.

.jvmopts


-XX:-UseJVMCICompiler
-Xmx8G

Run


$ /usr/bin/time sbt run GraalTest.scala

Then, the following result is obtained.

JVM results


[info] running GraalTest
List((the,3297996), (and,2198664), (of,2198664), (you,1648998), (a,1648998), (in,1648998), (about,1099332), (always,1099332), (with,1099332), (how,1099332))
[success] Total time: 64 s (01:04), completed 2020/06/04 0:38:37
       85.31 real       479.11 user         8.89 sys

With GraalVM! ??

Try running the above program on GraalVM.

.jvmopts


-Xmx8G

Run


$ /usr/bin/time sbt run GraalTest.scala

Then, the following result is obtained.

GraalVM results


[info] running GraalTest
List((the,3297996), (and,2198664), (of,2198664), (you,1648998), (a,1648998), (in,1648998), (about,1099332), (always,1099332), (with,1099332), (how,1099332))
[success] Total time: 54 s, completed 2020/06/04 0:40:02
       75.29 real       333.95 user         9.23 sys

By using GraalVM, you can see that it is 10s faster. This is much faster !!!!!

↓ Codes used for performance measurement https://github.com/kinshotomoya/loginfrastructure/tree/master/jitCompiler

Summary

If you can use Graal instead of the current JIT compiler, you should use it.

Next time, I will summarize another feature of GraalVM, native-image.

reference

Recommended Posts

Try using GraalVM
Try using libGDX
Try using Maven
Try using jmockit 1.48
Try using sql-migrate
Try using SwiftLint
Try using Log4j 2.0
Try using Axon Framework
Try using JobScheduler's REST-API
Try using java.lang.Math methods
Try using PowerMock's WhiteBox
Try using Talend Part 2
Try using Talend Part 1
Try using F # list
Try using each_with_index method
Try using Spring JDBC
Try using GloVe with Deeplearning4j
Try using view_component with rails
Try scraping using java [Notes]
Try using Cocoa from Ruby
Try using letter_opener_web for inquiries
[Swift] Try using Collection View
Try using IntelliJ IDEA once
Try using Spring Boot Security
Try using gRPC in Ruby
[Rails] Try using Faraday middleware
[Processing] Try using GT Force.
[Programming Encyclopedia] §2 Try using Ruby
People using docker Try using docker-compose
Try using Redmine on Mac docker
Try using Redis with Java (jar)
[Java] Try to implement using generics
Try using the messaging system Pulsar
Try using IBM Java method tracing
Try using Hyperledger Iroha's Java SDK
[Java] Where did you try using java?
Try using Java framework Nablarch [Web application]
Try using || instead of the ternary operator
Try HiveRunner
Try using the service on Android Oreo
Try using the Stream API in Java
Try using the Rails API (zip code)
Try Mockito
Study Java Try using Scanner or Map
Try Selenium
Try using JSON format API in Java
Try DbUnit
Try using Spring Boot with VS Code
Try using Reladomo's MT Loader (Multi-Threaded Matcher Loader)
try docker-compose
Try using JobScheduler's REST-API --Java RestClient implementation--
Try using Kong + Konga with Docker Compose.
Try using the Emotion API from Android
Try using the Wii remote with Java
Try Lombok
Try using simple_form / edit even child models
Try implementing GraphQL server using grahpql-java-tools (+ kotlin)
Try using Firebase Cloud Functions on Android (Java)
Try using JobScheduler's REST-API --Java RestClient Test class-
Try using conditional branching other than if statement
Beginners try using android studio Part 2 (event processing)