Are you a Java developer wondering what it means to have your application running in the cloud. This session will provide a peek into how the JVM is adapting to running in the cloud and what Java developers need to be aware to ensure they get the most of running in the cloud.
The session will pick an example spring application and tune it stage by stage at the end of which we have an application that is fully optimized and takes advantage of every aspect of the running in a cloud
2. 2
About Me
●
Co-Maintain the AdoptOpenJDK Community Docker Images
●
Runtimes Cloud Optimization Architect
●
Interested in every aspect of running Java Apps in K8s including
Cloud Native as well as Legacy migration to Cloud
●
Ex Linux Kernel and glibc hacker
Dinakar Guniguntala (@dinogun)
IBM Runtime Technologies
4. 4
What is AdoptOpenJDK
●
AdoptOpenJDK provides prebuilt OpenJDK binaries from a
fully open source set of build scripts and infrastructure.
– https://adoptopenjdk.net
●
Extensive testing as part of the CI pipeline.
●
REST API for scriptable downloads.
Docker Images
Unofficial →
https://hub.docker.com/u/adoptopenjdk
Official →
https://hub.docker.com/_/adoptopenjdk
6. 6
Build Goals
●
Size Matters – Small is Better !
– Affects provisioning / deployment time
– Consider Images based on Alpine Linux (5 MB vs 80 MB for Ubuntu)
– Slim images (Cloud workloads use only a small subset)
– Use jlink to use only the required modules (Java 9 onwards)
●
Should be easy to maintain
– Consider using standard build tool docker images (Eg. maven / gradle)
– Use build tool plugins for Docker where possible
Java
Version
Latest Slim Alpine
Alpine-
Slim
8 (JDK) 338 MB 213 MB 227 MB 95 MB
11 (JDK) 423 MB 354 MB 324 MB 239 MB
8. 8
Startup Goals
Use of a Shared Class Cache helps reduce startup times by upto 40%
-Xshareclasses
java -Xshareclasses:cacheDir=/opt/shareclasses -jar /opt/app/japp.jar
docker run -it -v /path/on/host/shareclasses/dir:/opt/shareclasses japp
-Xquickstart mode
Good for very short running applications
9. 9
Serverless and Startup
Quarkus – Supersonic Subatomic Java
– Compile to Native
Checkpoint Restore in UserSpace (CRIU)
Startup time
checkpoint
restore
Time to
restore
Instance 1
Time to first
response
Time to first
response
Instance 2
Instance 3 Timeline
https://criu.org
https://openliberty.io/blog/2020/02/12/faster-startup-Java-applications-criu.html
11. 11
Optimize at Runtime
Container Aware JVM
– -XX:+UseContainerSupport to turn on this feature. (Default now
with the latest JVM)
– Use -XX:MaxRAMPercentage and -XX:InitialRAMPercentage
instead of -Xmx and -Xms.
– Runtime.availableProcessors() based on cgroup limits.
Heap = 2.4G
Container Mem = 3G
Container Mem = 2G
Heap = 1.6G
Heap = 3.2G
Container Mem = 4G
-Xmx = 2G -Xmx = 2G
-Xmx = 2G
-XX:MaxRAMPercentage=80
https://blog.openj9.org/2018/06/12/eclipse-openj9-in-containers/
14. 14
Optimize at Idle Time
OpenJ9 reduces footprint on Idle
– -XX:+IdleTuningGcOnIdle and
– -XX:+IdleTuningCompactOnIdle
https://developer.ibm.com/javasdk/2017/09/25/still-paying-unused-memory-java-app-idle/
16. 16
Get Debugging Info on the Fly !
Do you have to restart your containerized Java app to dump debugging info ?
NO !
– Use OpenJ9DiagnosticMXBean instead
17. 17
Javacore Info
1CICONTINFO Running in container : TRUE
1CICGRPINFO JVM support for cgroups enabled : TRUE
…
1CICGRPINFO Cgroup Information
NULL -------------------------------------------------
CICGRPINFO subsystem : cpu
2CICGRPINFO cgroup name : /
2CICGRPINFO CPU Period : 200000 microseconds
2CICGRPINFO CPU Quota : 100000 microseconds
2CICGRPINFO CPU Shares : 1024
2CICGRPINFO Period intervals elapsed count : 16
2CICGRPINFO Throttled count : 2
2CICGRPINFO Total throttle time : 164156409 nanoseconds
2CICGRPINFO subsystem : cpuset
2CICGRPINFO cgroup name : /
2CICGRPINFO CPU exclusive : 0
2CICGRPINFO Mem exclusive : 0
2CICGRPINFO CPUs : 0-3
2CICGRPINFO Mems : 0
2CICGRPINFO subsystem : memory
2CICGRPINFO cgroup name : /
2CICGRPINFO Memory Limit : 2147483648 bytes
2CICGRPINFO Memory + Swap Limit : 4294967296 bytes
2CICGRPINFO Memory Usage : 31182848 bytes
2CICGRPINFO Memory + Swap Usage : 31182848 bytes
2CICGRPINFO Memory Max Usage : 31277056 bytes
2CICGRPINFO Memory + Swap Max Usage : 31277056 bytes
2CICGRPINFO Memory limit exceeded count : 0
2CICGRPINFO Memory + Swap limit exceeded count : 0
2CICGRPINFO OOM Killer Disabled : 0
2CICGRPINFO Under OOM : 0
$ docker run -m2g --cpu-quota="100000" --cpu-
period="200000" -it openj9 java
-Xdump:java:events=vmstop App