Compare OpenJ9 and HotSpot memory & CPU usage with Docker
Eclipse OpenJ9 is a Java Virtual Machine (JVM) that uses less container memory and therefore achieves lower cost. It’s mostly a drop-in replacement for the standard Oracle HotSpot JVM.
I demonstrated the memory savings in a lightning talk to the London Java Community (LJC) on May 1, 2020. Please read the slides first! My detailed results are in an Excel file.
You shouldn’t believe everything you read on the Internet. Granted, I’m a full-stack developer with 21 years of Java experience. And I think of myself as trustworthy. But don’t we all?!
That’s why you can run OpenJ9 against HotSpot yourselves. And you can tweak them — change the Java options or build a whole new container image!
And now for some shameless self-promotion. I write a blog about how to get better Java projects faster with JHipster and Docker. It’s been dormant since the end of 2019, but I’ll pick it up again by June 2020. Spoiler alert: I’ll also write about Flutter, Google’s cross-platform UI toolkit for native mobile, web & desktop apps. I built a mobile prototype with it last year.
You need Docker & Docker Compose. I used two different applications to test OpenJ9 vs HotSpot:
Both applications use the most recent Java 8 and 11 versions from AdoptOpenJDK, as of April 2020.
The containers are limited to 2 GB RAM and 2 CPUs. So I recommend at least 8 GB of RAM and 4 CPU cores to run these applications on your test machine.
Each application has four different Docker Compose Files in the root directory of this repository:
JVM Type | JVM Version | Web application | Benchmarks |
---|---|---|---|
HotSpot | 8 | docker-compose-web-app-hotspot-8.yml |
docker-compose-benchmark-hotspot-8.yml |
HotSpot | 11 | docker-compose-web-app-hotspot-11.yml |
docker-compose-benchmark-hotspot-11.yml |
OpenJ9 | 8 | docker-compose-web-app-openj9-8.yml |
docker-compose-benchmark-openj9-8.yml |
OpenJ9 | 11 | docker-compose-web-app-openj9-11.yml |
docker-compose-benchmark-openj9-11.yml |
So here’s how you run the web application with HotSpot 11:
docker-compose -f docker-compose-web-app-hotspot-11.yml up
And this is how you run the benchmarks with OpenJ9 8:
docker-compose -f docker-compose-benchmark-openj9-8.yml up
When the benchmarks are done, the container stops. That’s why I used the time
command on the Mac to measure how much CPU time they took:
time docker-compose -f docker-compose-benchmark-openj9-8.yml up
[...]
benchmark-openj9-8 exited with code 0
docker-compose -f docker-compose-benchmark-openj9-8.yml up 0.73s user 0.12s system 0% cpu 7:50.92 total
The web application runs until you manually stop the container. So I only took the time that Spring Boot self-reports in the log:
Started SimpleShopApp in 18.302 seconds (JVM running for 19.362)
I used the second number in my slides: JVM running for 19.362
For both applications, I monitored CPU & memory utilization with docker stats
:
docker stats --format "{{.Name}}\t{{.MemUsage}}\t{{.CPUPerc}}"
This command produces tab-separated output. You can redirect that to a file and then import into a spreadsheet. I did: The benchmark data is in this folder as data-benchmark-*.txt
. The log output of the benchmark runs is in the same folder as output-benchmark-*.txt
You can tweak both the Java options and the CPUs and memory of the container right in the Docker Compose files. For example, here’s the Docker Compose file for running the benchmark in OpenJ9:
version: '2.2'
services:
benchmark-openj9-8:
image: 'joedata/bpf-talks-openj9-memory-benchmark:openj9-8'
container_name: benchmark-openj9-8
environment:
- >-
JAVA_OPTS=-Xmx1024m -Xms256m -Xtune:virtualized
- BENCHMARKS=-r 5 gauss-mix,movie-lens,akka-uct,fj-kmeans,mnemonics,scala-doku,finagle-chirper
cpus: 2.0
mem_limit: 2147483648
You can change the Java options in the JAVA_OPTS
line. Which Java options can you use?
The number of CPUs is in the cpus:
line, and the memory in the mem_limit
one (in Bytes).
For the benchmark only, you can tweak the BENCHMARKS
line. The number of repetitions is 5 here (-r 5
). The comma-separated list of benchmarks follows right afterwards. The complete list of benchmarks is on the Rennaissance Suite web site. Please note that some of them actually crashed in my environment.
You can’t through the Docker Compose files. I build all the Docker images myself, so the Java version is hard-coded in there. If you want a different version of Java, you need to build the Docker images yourself.
I used the “Debian Slim JRE” images from AdoptOpenJDK as my base images. Here are their Docker Hub repositories:
You can find my Docker Images on Docker Hub, too:
src/benchmark
folder.
md5sum --check renaissance-mit-0.10.0.jar.md5
FROM adoptopenjdk/openjdk8-openj9:x86_64-debianslim-jre8u252-b09_openj9-0.20.0
docker build
in this directory. Here’s how you build the OpenJ9 8 image. Please note that I didn’t specify a Docker repository here (before the image name):
docker build -t my-memory-benchmark:openj9-8-new -f Dockerfile-openj9-8 .
image:
line in there. For the sample image that you just built in the line above, your Docker Compose file would have this image:
line:
image: 'my-memory-benchmark:openj9-8-new'
src/web-app
folder.
md5sum --check simple-shop-1.0.0.jar.md5