この記事は、ZOZOテクノロジーズ #4 Advent Calendar 2019 4日目の記事になります。
昨日は、@ikeponsu さんの「GASでGoogleドライブ監視システムを作成」でした。
本記事では、spring-graal-nativeという実験的プロジェクトを利用しSpring BootアプリケーションのGraalVM native imegeを作成し速度を比較してみました。
#はじめに
2019年11月21日にGraalVM 19.3.0がリリースされましたね。
JavaプログラマーだけではなくJVMを利用している方々で、GraalVMの今後が非常に気になると思うのは私だけでしょうか?
さらに10/7-10に行われたSpringOne Platform 2019 のセッションでは、「Running Spring Boot Applications as GraalVM Native Images」というとても興味深いセッションの動画がYouTubeにありました。内容を簡単に説明しますとSpring BootアプリケーションをGraalVMのNative Imageにするspring-graal-nativeという実験的な取り組みの紹介でした。
本記事では、この動画で紹介されていたspring-graal-nativeでSpring BootアプリケーションをGraalVM Native Imageにし速度を比較してみましたのでご紹介します。
#Spring Framework のGraalVM native image対応について
本題に入る前にSpring FrameworkのGraalVMの対応状況について確認しておきます。
現在の最新はSpring Framework 5.2.1です。Spring Framework 5.1のときにGraalVM native imagesの初期サポートを開始しましたが問題が多くSpring Framework 5.2では問題の対応中のようです。そのためSpring FrameworkのGraalVM native image対応は、Spring framework 5.3になりそうですね。
詳細はSpring FrameworkのGraalVM native image support Wikiを参照ください。
#環境
本記事の動作確認に利用した環境はこちらです。
WSL 18.04
GraalVM CE 19.2.0.1
Spring Boot 2.2
Java8
GraalVMのWindows対応はまだGAではないので、WSLを利用して試しました。
#ダウンロード
はじめに必要なものをダウンロードします。
まずはspring-projects-experimentalのspring-graal-nativeをCloneします。
このプロジェクトはSpringの実験的なプロジェクトとなり正式版ではありません。プロダクション環境等での利用には十分ご注意ください。
$ git clone https://github.com/spring-projects-experimental/spring-graal-native.git
次にGraalVM 19.2.0.1をダウンロートし解凍します。
現時点での最新は19.3ですがGraalVM 19.2.0.1を利用します。
graalvm-ce-linux-amd64-19.2.0.1.tar.gz
$ tar -xvf graalvm-ce-linux-amd64-19.2.0.1.tar.gz
#セットアップ
GraalVMのセットアップを行います。
はじめにguコマンドが使えるようにパスを通します。
$ export PATH=/home/tkani/graalvm/graalvm-ce-19.2.0.1/bin:$PATH
$ gu
GraalVM Component Updater v2.0.0
Usage:
gu info [-clLprstuvV] <param> prints info about specific component (from file, URL or catalog)
gu available [-alvV] <expr> lists components available in catalog
gu install [-0cfiLnorvyxY] <param> installs a component package
gu list [-clv] <expression> lists installed components, or components from catalog
gu remove [-0fxv] <id> uninstalls a component
gu update [-x] [<ver>] [<param>] upgrades to recent GraalVM
gu rebuild-images rebuilds native images. Use -h for detailed usage
・・・・
guコマンドを使ってnative-imageコマンドをインストールします。
$ gu install native-image
Downloading: Component catalog from www.graalvm.org
Processing component archive: Native Image
Downloading: Component native-image: Native Image from github.com
Installing new component: Native Image (org.graalvm.native-image, version 19.2.0.1)
$ native-image --version
GraalVM Version 19.2.0.1 CE
#GraalVM native imageを作成
native-imageコマンドが使えるようになったら、CloneしたSpring BootアプリケーションをGraalVM native imageにしてみます。この手順はspring-graal-nativeのREADMEに記載されています。
$ cd /home/tkani/graalvm/spring-graal-native/spring-graal-native-feature
$ ./mvnw clean package
ここでは、commandlinerunnerディレクトリでcompile.shを実行しますが、spring-graal-native-samples配下のディレクトリには様々なプロジェクトが用意されていますね。
$ cd /home/tkani/graalvm/spring-graal-native/spring-graal-native-samples
$ ls -l
いよいよcompile.shを実行しGraalVM native imageを作成します。
$ cd /home/tkani/graalvm/spring-graal-native/spring-graal-native-samples
$ cd commandlinerunner
$ ./compile.sh
・・・エラー部分のみ抜粋・・・
Compiled app (clr)
./compile.sh: line 39: ./clr: No such file or directory
・・・
compile.shを実行するとエラーになりました。。。
調べて分かったのですが、zlib1g-devという圧縮ライブラリが必要でしたのでインストールします。
$ sudo apt install zlib1g-dev
こちらのブログが大変参考になりました。ありがとうございました。
GraalVMでRust動かしたりレイトレをネイティブコンパイルしたり
#処理時間の比較
clrというGraalVM native imageができあがりましたね。
それではSpring BootのjarとGraalVM native imageの速度を比較してみましょう。
Spring Bootアプリケーションは、1.784sですね。
$ time java -jar ./target/commandlinerunner-0.0.1-SNAPSHOT.jar
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.0.RELEASE)
2019-12-03 14:03:26.803 INFO 1061 --- [ main] c.e.c.CommandlinerunnerApplication : Starting CommandlinerunnerApplication v0.0.1-SNAPSHOT on ST180329 with PID 1061 (/home/tkani/graalvm/spring-graal-native/spring-graal-native-samples/commandlinerunner/target/commandlinerunner-0.0.1-SNAPSHOT.jar started by tkani in /home/tkani/graalvm/spring-graal-native/spring-graal-native-samples/commandlinerunner)
2019-12-03 14:03:26.808 INFO 1061 --- [ main] c.e.c.CommandlinerunnerApplication : No active profile set, falling back to default profiles: default
2019-12-03 14:03:27.298 INFO 1061 --- [ main] c.e.c.CommandlinerunnerApplication : Started CommandlinerunnerApplication in 1.12 seconds (JVM running for 1.735)
CLR running!
real 0m1.784s
user 0m3.328s
sys 0m1.156s
GraalVM native imageは、0.100sでした。
$ time ./clr
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot ::
Dec 04, 2019 12:57:58 AM org.springframework.boot.StartupInfoLogger logStarting
INFO: Starting CommandlinerunnerApplication on ST180329 with PID 1121 (/home/tkani/graalvm/spring-graal-native/spring-graal-native-samples/commandlinerunner/clr started by tkani in /home/tkani/graalvm/spring-graal-native/spring-graal-native-samples/commandlinerunner)
Dec 04, 2019 12:57:58 AM org.springframework.boot.SpringApplication logStartupProfileInfo
INFO: No active profile set, falling back to default profiles: default
Dec 04, 2019 12:57:58 AM org.springframework.boot.StartupInfoLogger logStarted
INFO: Started CommandlinerunnerApplication in 0.044 seconds (JVM running for 0.046)
CLR running!
real 0m0.100s
user 0m0.016s
sys 0m0.078s
約17倍とGraalVM native imageめっちゃ早いですね!
#おわりに
GraalVMでよく話題になることで、起動は早いけど実行時はJITより遅くなるケースもあるよねって話を聞きますが、実験的なプロジェクト( spring-graal-native)を用いた速度比較とは言え、この速度は非常に魅力的ですね。
Spring BootのGraalVM native image対応が正式リリースされた際は是非使ってみたいですね。
明日のZOZOテクノロジーズ #4 Advent Calendar 2019 5日目も@tkaniによる「Postmanで301リダイレクトをテストしてみる」の投稿になります。