スキップしてメイン コンテンツに移動

QuarkusのNative Buildイメージ

久しぶりにQuarkusを触ったので少しやる気が出てきた、ということもあり、今だとNativeイメージはどれくらい速いのか、ビルドにはどれくらい時間がかかるのか、と言ったあたりを、環境最新化も兼ねて軽く動かして見てみた。

環境はこんな感じ。(咄嗟にUSキーボードになってしまった時でもハイフンは扱いやすかったので、箇条書きの点をハイフンに置き換えてみたけどどうだろう)

- OS: macOS 11.2
- メモリ: 8GB
- CPU: 2.7GHz Dual core i5
- Java: openjdk version "11.0.7" OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.7+10)
- GraalVM: GraalVM CE 21.0.0 (build 11.0.10+8-jvmci-21.0-b06)
- Docker: Docker version 20.10.2, build 2291f61
- Quarkus: 1.11.1.Final

動かしていたサンプルはこの内容。(GraphQLならApolloを使えって話なんだけど......Java育ちなので)
Quarkus - GraphQL https://quarkus.io/guides/microprofile-graphql

比較したのは次のそれぞれの実行時間と、そこから生成された実行ファイルやコンテナイメージを実行した時の起動時間。
ダウンロード時間の差分を入り込ませないようにするため、各コマンドは一度実行し、その後に ./mvnw clean した。(けど、もしかしたらそれだと比較のためのクリアには不十分だったかもしれないがどうだろう)

Jar:

./mvnw package -DskipTests
java -jar target/microprofile-graphql-quickstart-1.0.0-SNAPSHOT-runner.jar 

Native:

./mvnw package -Pnative -DskipTests
./target/microprofile-graphql-quickstart-1.0.0-SNAPSHOT-runner

Docker Native:

./mvnw package -Pnative -Dquarkus.native.container-build=true -DskipTests
docker build -f src/main/docker/Dockerfile.native -t quarkus/microprofile-graphql-quickstart .
docker run -i --rm -p 8080:8080 quarkus/microprofile-graphql-quickstart


ビルド時間:

- Jar: 8.615s (2,346ms)
- Native: 5:41min (333,685ms)
- Docker Native: 5:14min (306,721ms)


実行時間:

- Jar: 1.591s
- Native: 0.024s
- Docker Native: 0.073s


という感じで、前回ビデオで見た結果は概ね外していない感じだった。
Nativeのビルドはやはりすごく時間がかかるので本番環境など一定の必要なタイミングに限定かな、という印象はある。

ちなみに、さりげなくつまづいたのが、Nativeイメージのビルドの箇所。
macOS上でNativeビルドしたイメージをdockerに入れてコンテナを動かしたのだけど、いざ実行してみると、次のようなエラーが出てしまった。

standard_init_linux.go:219: exec user process caused: exec format error

ざっと見ていると、使用しているCPUの問題とか、あとはDocker内に持ち込んでるファイルのシェバンなどがまずいとか、そういう話を見かける、が、決定的な回答は見つけられていない。ここはきっと知識がつきなおしたときに再訪する感じになりそう。Nativeイメージのビルドの具体的な実現方法を理解しないと、なぜこれが動かないかを理解するのは難しいだろうと思っている。
で、いずれにせよDocker上でビルドできるに越したことはないので今回はcontainer-buildを有効にして改めて確認した。

ちなみにコンテナ上でビルドする方法の場合には、初期のDockerの設定を改めて、メモリの割当量を増やす必要があった。
コンソールで動きを追っているとビルド時にNativeビルドでは3GBを超えるメモリを使用していた。
そして、自身の環境のDockerの初期設定ではDockerはメモリを最大2GBまで使える設定になっていたため、途中でメモリ不足に起因するエラーでビルドが失敗してやり直しになってしまった。


今回は最小限のサンプルでのお試しだったので、Nativeビルドで他にどのような制約が出てくるのかはもう少し追っていきたいところ。

p.s.
Mavenの例だったのでMavenで進めていたがやはり肌に合わないのでGradleに置き換えた。
Nativeビルドにかかる時間は総じて言えば大差なかったが、Docker経由にするものの場合はビルド実行時間が少し伸びたのが気になった


./gradlew build -Dquarkus.package.type=native -x test BUILD SUCCESSFUL in 5m 7s 5 actionable tasks: 5 executed ./build/microprofile-graphql-quickstart-1.0.0-SNAPSHOT-runner started in 0.022s
./gradlew build -Dquarkus.package.type=native -Dquarkus.native.container-build=true -x test
BUILD SUCCESSFUL in 6m 15s
5 actionable tasks: 5 executed

docker build -f src/main/docker/Dockerfile.native -t quarkus/microprofile-graphql-quickstart .

docker run -i --rm -p 8080:8080 quarkus/microprofile-graphql-quickstart
started in 0.031s