I implemented four very basic REST APIs with exactly one route each, which exposes a small, static todo list as JSON.
My machine, where the benchmark suite was executed on, has the following specifications.
=== CPU:model name : Intel(R) Core(TM) i5-3317U CPU @ 1.70GHzcpu cores : 2model name : Intel(R) Core(TM) i5-3317U CPU @ 1.70GHzcpu cores : 2model name : Intel(R) Core(TM) i5-3317U CPU @ 1.70GHzcpu cores : 2model name : Intel(R) Core(TM) i5-3317U CPU @ 1.70GHzcpu cores : 2 === RAM: total used free shared buffers cachedMem: 7.7G 6.3G 1.4G 412M 527M 2.4G-/+ buffers/cache: 3.3G 4.3GSwap: 5.6G 0B 5.6G === Java version:java version "1.8.0_101"Java(TM) SE Runtime Environment (build 1.8.0_101-b13)Java HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode) === OS:Linux ferdinand-notebook 3.16.0-4-amd64 #1 SMP Debian 3.16.36-1+deb8u2 (2016-10-19) x86_64 GNU/Linux === Node: v6.5.0 === Go: go version go1.7.3 linux/amd64
Basically there are three parameters to be varied for the benchmark.
Running my benchmark script delivered the following results.
First of all, please notice that this is definitely not a 100 % correct, scientific evaluation. Rather it should give basic insights on the order of magnitude of the performance differences between different language’s HTTP servers. As we can clearly see, Go is the fastest candidate among my test subjects. However, my implementation only utilized the plain, built-in http package without any custom ServeMux or any router or middleware on top of it. In a real-world application, one would most likely not operate on such a low level, but use frameworks like Iris on top, which add additional overhead.
Second place is Java using Grizzly as an embedded server inside a Jersey application. The reason for me picking Grizzly was that it turned out to be the fastest among the common servers in this benchmark.
Both of my Node implementations perform worst in this benchmark, whereas Express is even only as half as good as the plain http package. Evidently, it introduces quite an amount of overhead. However, one would most likely not implement an actual REST API without a higher-level framework like Express. Consequently, the Express benchmark is probably more representative.
Concluding I can say that I was pretty surprised about how large the differences between various servers are. Go is almost six times as fast as Node with Express, even though Express still has a very great performance.
The full benchmark results as well as the suite’s source code can be found at my GitHub project.
At January 1st 2017 I did some minor adjustments to my benchmark suite. A thoughtful reader has drawn my attention to the fact that my comparison was a little unfair in the way that Go’s net/http as well as Grizzly use as many threads as the host system provides CPU core by default, while Node doesn’t. Using Node’s
cluster module I made both Node-based webservers use four listener threads, too and actually the results have improved by around 45 %. Furthermore I did an adjustment to the Jersey + Grizzly server by changing the
IOStrategy from the default
SameThreadIOStrategy, which brought around 10 % in this specific case, where we don't have any blocking computations but only spit out static JSON. If you're interested in leaarning more about different io strategies, refer to this official documentation page. Here is my updated benchmark chart.
Originally published at ferdinand-muetsch.de.