This article describes the results of a small (and not very serious) comparative study between three hello world projects on OpenShift. There’s no real research question or method; .
What is this about?
I will use a couple of technical terms which you’re probably already familiar with. The table below lists my definition of each term. Go to Wikipedia if you need a real definition.
|AOT||Ahead-of-time compilation. Source code needs to be compiled before you can run your program. A bit waterfally, but very fast (in theory).|
|JIT||An agile version of AOT where code is (re)compiled right before it’s used. Enables interesting optimisations (in theory).|
|Interpreted code||When code is translated in real time into something that can be executed by a computer. Slow as shit (in theory).|
|PHP||Shitty scripting language for WordPress, badly secured online shops, and some systems that are part of critical infrastructure. Usually interpreted. Not to be confused with the equally uncool Philippine peso (PHP).|
|Java||Programming language for boomers. Also very popular among people who are bad at programming. Usually works with JIT.|
|JVM||A virtual machine for Java applications. Well known for its JIT compilation. Faster boot times than VirtualBox, most of the time.|
|HotSpot||OG JVM for normies. Keeps consuming memory until it explodes (like Mr. Creosote in Monty Python’s The Meaning of Life).|
|GraalVM||The Jonny Kim of JVMs, an overachieving VM that also supports a plethora of other languages and can compile things ahead of time|
|Oracle||Satanic sales and legal organisation that also happens to produce useful software. Make sure you read the small print before using any of it.|
|Red Hat||The company that made things like |
|Slim||A micro-framework for PHP that’s so small that you might as well use plain PHP.|
|Quarkus||A Java framework for people who hate Spring. Its website would make you believe it is the best thing since microserviced sliced bread blockchain.|
|Kubernetes||A steaming pile of shit that is mostly useful because everyone else also uses it (like English).|
|OpenShift||Multi-tenant Kubernetes that tries to do too much for its own good (like |
Our first project is a small PHP 7.4 application that is built using Slim. It’s deployed using a YAML template which creates a pod with two containers for PHP-FPM and nginx.
The second and third projects are technically the same Quarkus application, but compiled differently: one uses OpenJDK (a “normal” JVM), the other uses GraalVM (for AOT compilation).
All three projects come with a simple HTTP route that responds to requests with a simple pre-defined text.
Tests were done on an externally managed OpenShift 4 cluster that saw very little actual usage, which means that the numbers you see here are not likely to be negatively affected by external factors.
Kubernetes is a platform that lets you run and manage containers in all kinds of fancy ways, but .
OpenShift is a Kubernetes distribution that can also handle the building part for you out of the box, so that’s what we’ll use for this first test. All that we have to do is tell OpenShift where it can find our source code, and it’ll start the build and deployment processes using Docker or something that’s called source-to-image.
|Application||Time (mm:ss)||CPUs (#)||Memory (MiB)|
|PHP 7.4 🎉||01:37||0.2||256|
|Quarkus (AOT) 💩||06:26||1.0||3,072|
It should not come as a surprise that the PHP application is , as it doesn’t require a compilation step: its build process simply consists of copying some files to the right directories, downloading dependencies off the Internet, and setting up some caches.
The two Quarkus builds are more expensive and require at least one CPU if you want the builds to complete before Christmas. The GraalVM build is especially expensive: give it anything less than 3GiB of memory and it’ll die on you!
Fortunately, building containers is a one-time process that can also be done outside of the cluster.
Idle resource usage
Things look very different once the application containers have been built and the applications just sit there idly, because we haven’t told anyone that they exist.
|Application||CPUs (#)||Memory (MiB)|
|PHP 7.4 💩||0.004000||72|
|Quarkus (AOT) 🎉||0.000013||20|
The idle resource usage for our AOT-compiled Quarkus application is much, much lower than that of the other two.
Having said that, idle resource usage isn’t a terribly useful metric when you have the ability to scale applications up and down whenever you want. It might be better to think about these numbers as a “base cost” or “tax” per container.
Speaking of scaling, it would be really nice if our applications could scale up rapidly if we see a sudden rise in demand for computing resources.
Normally I would test this by quickly spinning up something like 100 pods, but since I didn’t want to piss off my OpenShift cluster administrator I measured the time to go from 0 to fully operational pods that are ready to accept HTTP requests.
|Application||μ (s)||σ (s)|
|Quarkus (JIT) 💩||14.4||0.24|
|Quarkus (AOT) 🎉||3.0||0.00|
The AOT-compiled Quarkus application starts consistently fast, while the JVM-based Quarkus container is consistently slow. Startup times of the PHP pod are anything but consistent (and also quite slow).