This is a simple demo of Spring Native subsystem, compiling Spring applications to native executables using the GraalVM native-image compiler.
Arch. | Spring | CPU | Compile T. | Build Size | Docker Size | App Start | RSS Memory |
---|---|---|---|---|---|---|---|
amd64 | classic | AMD Ryzen 9 5950X | 7 s | 17 M * | 218.98 MB | 0.84 s | 484.332 MB |
amd64 | native | AMD Ryzen 9 5950X | 48 s | 68 M | 68.35 MB | 0.032 s | 49.824 MB |
amd64 | classic | i7-3632QM | 21 s | 17 M * | 218.98 MB | 3.298 s | 461.360 MB |
amd64 | native | i7-3632QM | 214 s | 68 M | 68.35 MB | 0.098 s | 50.004 MB |
arm64v8 | classic | Raspberry PI 4 | NA * | 17 M * | NA | 10.997 s | 169.416 MB |
arm64v8 | native | Raspberry PI 4 | NA * | 67 M | NA | 0.161 s | 71.820 MB |
- Compilation Time - in case of classic spring build, the compilation time is to build classic springboot fat jar.
- Compilation Time * - springboot graal native compilation requires a LOT OF memory, ~20G is recommended. It is possible to emulate ARMv64 VM on x86_64 hardware in case memory on ARMv64 system is not enough. Compilation on Raspberry PI4 8G was failing because of memory shortage, so this example was compiled on qemu ARM64 VM.
- Build Size - in case of classic build the build size is size of fat jar (only demo and dependencies) which does not include JVM and JVM libraries. JVM typically takes extra ~250MB.
- Build Size * - in case of native build the resulting binary contains this demo, optimized java library stack and 'Substrate VM' as described here.
- App Start - start time measured by SpringBoot framework printed in the log file.
- RSS Memory - allocated measured after start and after REST APIS was exercised
cat /proc/<pid>/status | grep VmRSS
.
Check also this GraalVM native-image plain java application demo.
- GET Message
curl --request GET --url http://localhost:8080/api/v1/data/message
- POST Message
curl --request POST \ --url http://localhost:8080/api/v1/data/message \ --header 'Content-Type: application/json' \ --data '{ "message": "Hi !" }'
This procedure is valid for Ubuntu 20.04 amd64 and arm64v8 build servers.
sudo apt install zip unzip curl
sudo apt install build-essential libz-dev zlib1g-dev
curl -s "https://get.sdkman.io" | bash
sdk install java 21.3.0.r17-grl
sdk install gradle 7.3.3
gu install native-image
- Build classic springboot fat jar.
gradle clean build test jar
- Build docker with springboot fat jar.
export VERSION=0.0.1-SNAPSHOT
export ARCH=arm64v8
export ARCH=amd64
docker build -t jurajveverka/spring-native-classic:${VERSION}-${ARCH} \
--build-arg ARCH=${ARCH} \
-f Dockerfile.classic .
docker push jurajveverka/spring-native-classic:${VERSION}-${ARCH}
docker run -p 8080:8080 jurajveverka/spring-native-classic:${VERSION}-${ARCH}
gradle clean build test bootBuildImage
docker run --rm -p 8080:8080 spring-native:0.0.1-SNAPSHOT
- Build native binary.
sdk use java 21.3.0.r17-grl
sdk use gradle 7.3.3
gradle clean build test nativeCompile
./build/native/nativeCompile/spring-native
- Build docker with native binary.
export VERSION=0.0.1-SNAPSHOT
export ARCH=arm64v8
export ARCH=amd64
docker build -t jurajveverka/spring-native-native:${VERSION}-${ARCH} \
--build-arg ARCH=${ARCH} \
-f Dockerfile.native .
docker push jurajveverka/spring-native-native:${VERSION}-${ARCH}
docker run -p 8080:8080 jurajveverka/spring-native-native:${VERSION}-${ARCH}