Chuniversiteit.nl
Living the Pipe Dream

Deploying apps on OpenShift: a stupid comparison between PHP, the Java Virtual Machine (JVM) and GraalVM

Spoiler alert: they’re not the same.

An OpenShift-branded hanging mobile with an orange and PHP, Java and Docker mascots
Today we’re comparing applets and oranges

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.

Term 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 systemd, OpenShift, Quarkus, and other obscure projects, like Fedora and CentOS. Nowadays part of IBM, which does not make things (that work).

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 systemd), for developers who happen to have a corporate sugar daddy with big pockets.

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.

Building containers

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 (JIT) 02:26 1.0 512
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 (JIT) 0.000440 75
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.

Scaling

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)
PHP 7.4 11.6 2.64
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).

Conclusion

🤷‍♂️