Gerasimos

Go Software Engineer. Previously worked at netdata Inc, Landoop Ltd.

Iris Go vs .NET Core Kestrel in terms of HTTP performance

A Fair benchmark between Iris Golang and Kestrel .NET Core (C#).

Hello!

This article is the second in a row of the “Go vs .Net Core in terms of HTTP performance” series, you should really read the first article, if you didn’t already.

Prepare yourself a cup of coffee, or tea, whatever enjoys you the most!

About feedback

At this section I’ll try to give you a general idea about a part(the bad side) of the previous article’s reactions however you may don’t care at all or you’re not in the mood, therefore you may want to skip that and go straight to the “Benchmarking” section.

At our previous article we compared the performance of the MVC features of both Iris web framework and .NET Core by testing a simple application (to avoid arguments like “you could use a faster json encoder” and things like these).

The article got pretty amazing reactions. Most of the comments were very nice and polite either agree or disagree with them. There were some people with a smell of negativity on their comments but those were expected and welcomed as well.

I always try to be responsible so I respond to most of your questions that were relative to the article avoiding duplication. If you don’t see my respond below your comment yet then search about relative questions, I’m sure you’ll find my answer sitting there waiting for you.

Some of the .NET Developers contacted with me via twitter telling that this wasn’t real .NET Core because I used MVC and not Kestrel, does that mean that C# developers should avoid .NET Core’s MVC features? I didn’t understand. It was clear by the benchmark titles and the code itself that we were doing a comparison between the MVC versions of both Iris and .NET Core, Iris has a “lower level“ too but we didn’t use that.

Note: the IrisMVC is a foreign twitter account, it is not Iris web framework’s account.

I knew that my article will have an impact on .NET world. I’d receive a lot of rude comments lately, the funny part is that the people who posted the most unacceptable comments are working for big companies, I mean that they are in a certain age who can understand the human contact but actually they never learnt the basics of human communication, politeness.

I don’t really feel that right, I mean by publishing their (already public) comments is the right decision but one way or another we should all condemn them as soon as possible.

He insists without even reading the article…
That guy really thinks that I got paid from someone? Sadly I have just 0.67$ at my personal bank account!
Scott’s reply to that guy. Beside the fact that every Scott’s talk is beyond the best It’s a great person with ethos as well.

At the other hand I have really no problem at all, hate speech was and will never touch me at all because I don’t have that thing inside me — by-design :p . I’m not taking those as personal attacks neither terrifies me, but this doesn’t mean that I should tolerate them, tacitly.

For example that guy claims that he works at Microsoft but I can’t believe that someone with “high education” can possible write something like that:

Even if the code ran in production mode he doesn’t care about that, he just want to comment something. One more guy who didn’t actually read the article neither the code inside it.
He’s clearly promoting hate without reason, just to be said.

No, they didn’t stop there, you will be surprised about the Democratic consciousness that this comment promoting!

That guy for example, reported dev.to for sharing my article. Bad dev.to authors, don’t share my articles again, he doesn’t allow these things! “after investigating” oh boy…

Beside the fact of the miss arguments and the slanderous comments , the first guy, Ali Malekpour posted his argument nicely so I think of it seriously, he actually gave me this idea: to write benchmarks for the “low-level” web side of those two worlds, Go and .NET Core and so here we are :)

Benchmarking

This time we will compare the speed of the “low-level” .NET Core’s server implementation named Kestrel and Iris’ “low-level” handlers, we will test two simple applications, the first will be almost the same as our previous application but written using handlers and the second test will contain a single route which sets and gets a session value(string) based on a key(string) and returns that session value to the client.

Hardware

  • Processor: Intel(R) Core(TM) i7–4710HQ CPU @ 2.50GHz 2.50GHz
  • RAM: 8.00 GB

Software

First application

Spawn 1000000 requests with 125 different “threads”, targeting to a dynamic registered route path, responds with a simple “value” text.

.NET Core (Kestrel)

Source Code

Start the .NET Core Kestrel web server

$ cd netcore
$ dotnet run -c Release
Hosting environment: Production
Content root path: C:\mygopath\src\github.com\kataras\iris\_benchmarks\netcore
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

Target and run the HTTP benchmark tool

$ bombardier -c 125 -n 1000000 http://localhost:5000/api/values/5
Bombarding http://localhost:5000/api/values/5 with 1000000 requests using 125 connections
1000000 / 1000000 [======================================================================================] 100.00% 10s
Done!
Statistics Avg Stdev Max
Reqs/sec 97884.57 8699.94 110509
Latency 1.28ms 682.63us 61.04ms
HTTP codes:
1xx - 0, 2xx - 1000000, 3xx - 0, 4xx - 0, 5xx - 0
others - 0
Throughput: 17.73MB/s

Iris

Source Code

Start the Iris Go web server

$ cd iris
$ go run main.go
Now listening on: http://localhost:5000
Application started. Press CTRL+C to shut down.

Target and run the HTTP benchmark tool

$ bombardier -c 125 -n 1000000 http://localhost:5000/api/values/5
Bombarding http://localhost:5000/api/values/5 with 1000000 requests using 125 connections
1000000 / 1000000 [=======================================================] 100.00% 8s
Done!
Statistics Avg Stdev Max
Reqs/sec 117917.79 4437.04 125614
Latency 1.06ms 278.12us 19.03ms
HTTP codes:
1xx - 0, 2xx - 1000000, 3xx - 0, 4xx - 0, 5xx - 0
others - 0
Throughput: 21.93MB/s

Summary

  • Time to complete the 1000000 requests — smaller is better.
  • Reqs/sec — bigger is better.
  • Latency — smaller is better
  • Throughput — bigger is better.
  • LOC (Lines Of Code) — smaller is better.

.NET Core (Kestrel) Application written using 63 code of lines ran for 10 seconds serving 97884.57 requests per second with 17.73MB/s within 1.28ms latency in average and 61.04ms max.

Iris Application written using 14 code of lines ran for 8 seconds serving 117917.79 requests per second with 21.93MB/s within 1.06ms latency in average and 19.03ms max.

Second Application (Sessions)

Spawn 5000000 requests with 125 different “threads” targeting a static request path, sets and gets a session based on the name “key” ,value as string”value"and write(or return, you choose) that session value to the response stream.

.NET Core (Kestrel) with Sessions

Source Code

Start the .NET Core Kestrel web server

$ cd netcore-sessions
$ dotnet run -c Release
Hosting environment: Production
Content root path: C:\mygopath\src\github.com\kataras\iris\_benchmarks\netcore-sessions
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

Target and run the HTTP benchmark tool

$ bombardier -c 125 -n 5000000 http://localhost:5000/setget
Bombarding http://localhost:5000/setget with 5000000 requests using 125 connections
5000000 / 5000000 [====================================================================================] 100.00% 2m40s
Done!
Statistics Avg Stdev Max
Reqs/sec 31844.77 13856.19 253746
Latency 4.02ms 15.57ms 0.96s
HTTP codes:
1xx - 0, 2xx - 5000000, 3xx - 0, 4xx - 0, 5xx - 0
others - 0
Throughput: 14.51MB/s

Iris with Sessions

Source Code

Start the Iris Go web server

$ cd iris-sessions
$ go run main.go
Now listening on: http://localhost:5000
Application started. Press CTRL+C to shut down.

Target and run the HTTP benchmark tool

$ bombardier -c 125 -n 5000000 http://localhost:5000/setget
Bombarding http://localhost:5000/setget with 5000000 requests using 125 connections
5000000 / 5000000 [====================================================================================] 100.00% 1m15s
Done!
Statistics Avg Stdev Max
Reqs/sec 66749.70 32110.67 110445
Latency 1.88ms 9.13ms 1.94s
HTTP codes:
1xx - 0, 2xx - 5000000, 3xx - 0, 4xx - 0, 5xx - 0
others - 0
Throughput: 20.65MB/s

Summary

  • Time to complete the 5000000 requests — smaller is better.
  • Reqs/sec — bigger is better.
  • Latency — smaller is better
  • Throughput — bigger is better.

.NET Core with Sessions Application ran for 2 minutes and 40 seconds serving 31844.77 requests per second with 14.51MB/s within 4.02ms latency in average and 0.96s max.

Iris with Sessions Application ran for 1 minute and 15 seconds serving 66749.70 requests per second with 20.65MB/s within 1.88ms latency in average and 1.94s max.

Epilogue

We really have to admit that Kestrel runs pretty fast compared to its MVC side, congrats to the open-source project’s contributors and Microsoft for started and supporting that!

Like the previous article, this one has its own screenshots taken from my computer and the same code snippets you saw here are also exist in gists and the github repository, click to the links to be navigated.

I would love to see more testers so download the source code and run the benchmarks from your machine, share the results with the rest of us.

If you want to reach me for a subject to discuss I’m always open for new opportunities and new people to meet, inside my twitter profile you’ll find all my contact information!

Thank you for the personal time you gave to read this article, spread it to the outside world as you did with the previous one.

Will see you at my next article and… as always, have fun!

I like the visual effects when I click the clap button more than once, do you? It’s simple: just click the clap button. If you feel strongly, click it more (or just hold it down).

More by Gerasimos

Topics of interest

More Related Stories