I agree it doesn’t make much sense to compare blocking and non-blocking implementations, so I’ve tried my best to create my own benchmark comparing Go (using gin) and Kotlin (using Ktor with Netty).
Both servers implement a /static
route which serves a static string and a /file/<name>
route which serves the file with the given name from the data
directory.
I’ve used bombardier with default settings for the tests. Because the JVM needs some time to get “hot” I’ve done multiple tests on both servers, waiting a few seconds between each of them, and took the best results for both, respectively.
The /static
route:
== Kotlin
Statistics Avg Stdev Max
Reqs/sec 118952.59 9837.47 137048.63
Latency 1.05ms 748.43us 78.00ms
Throughput: 19.28MB/s
== Go
Statistics Avg Stdev Max
Reqs/sec 155828.78 12136.14 184001.84
Latency 799.99us 97.91us 26.00ms
Throughput: 30.77MB/s
The /file/<name>
route with the test.txt
file:
== Kotlin
Statistics Avg Stdev Max
Reqs/sec 13226.78 849.23 16523.10
Latency 9.44ms 291.74us 30.00ms
Throughput: 2.32MB/s
== Go
Statistics Avg Stdev Max
Reqs/sec 22838.06 1152.13 24500.61
Latency 5.47ms 1.93ms 95.12ms
Throughput: 5.92MB/s
I’m not an expert on Ktor nor gin (or benchmarking in general), so please tell me if I made any mistakes here. You can find the source code here.