Skip to content

Commit

Permalink
Kestrel vs Iris new benchmarks, as you asked for 👍
Browse files Browse the repository at this point in the history
  • Loading branch information
kataras committed Aug 21, 2017
1 parent f31aae9 commit d003e91
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 50 deletions.
115 changes: 82 additions & 33 deletions _benchmarks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
* **.NET Core**: https://www.microsoft.com/net/core, latest version **2.0**
* **Iris**: https://github.com/kataras/iris, latest version **8.3** built with [go1.8.3](https://golang.org)

## Results
# .NET Core MVC vs Iris MVC

The first test will contain a simple application with a text response and the second will render templates + a layout.

## Simple

We will compare two identical things here, in terms of application, the expected response and the stability of their run times, so we will not try to put more things in the game like `JSON` or `XML` encoders and decoders, just a simple text message. To achieve a fair comparison we will use the MVC architecture pattern on both sides, Go and .NET Core.

Expand Down Expand Up @@ -60,31 +64,10 @@ Statistics Avg Stdev Max
Throughput: 19.65MB/s
```

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

```bash
$ bombardier -c 125 -n 5000000 http://localhost:5000/api/values/5
Bombarding http://localhost:5000/api/values/5 with 5000000 requests using 125 connections
5000000 / 5000000 [======================================================================================] 100.00% 45s
Done!
Statistics Avg Stdev Max
Reqs/sec 110809.98 8209.87 128212
Latency 1.13ms 307.86us 18.02ms
HTTP codes:
1xx - 0, 2xx - 5000000, 3xx - 0, 4xx - 0, 5xx - 0
others - 0
Throughput: 20.61MB/s
```

Click [here](screens) to navigate to the screenshots.

#### Summary
### Summary

* Time to complete the `5000000 requests` - smaller is better.
* Reqs/sec - bigger is better.
Expand All @@ -97,8 +80,6 @@ Click [here](screens) to navigate to the screenshots.

Iris MVC Application, written using 27 lines of code, ran for **47 seconds** serving **105643.71** requests per second within **1.18ms** latency in average and **22.01ms** max, the memory usage of all these was ~12MB.

Iris Application, written using 22 lines of code, ran for **45 seconds** serving **110809.98** requests per second within **1.13ms** latency in average and **18.02ms** max, the memory usage of all these was ~11MB.

#### Update: 20 August 2017

As [Josh Clark](https://twitter.com/clarkis117) and [Scott Hanselman‏](https://twitter.com/shanselman)‏ pointed out [on this status](https://twitter.com/shanselman/status/899005786826788865), on .NET Core MVC `Startup.cs` file the line with `services.AddMvc();` can be replaced with `services.AddMvcCore();`. I followed their helpful instructions and re-run the benchmarks. The article now contains the latest benchmark output for the .NET Core application with the change both Josh and Scott noted.
Expand All @@ -107,7 +88,7 @@ The twitter conversion: https://twitter.com/MakisMaropoulos/status/8991132158959

For those who want to compare with the standard services.AddMvc(); you can see the old output by pressing [here](screens/5m_requests_netcore-mvc.png).

## Results with Templates
## MVC + Templates

Let’s run one more benchmark, spawn `1000000 requests` but this time we expect HTML generated by templates via the view engine.

Expand Down Expand Up @@ -157,7 +138,7 @@ Statistics Avg Stdev Max
Throughput: 192.51MB/s
```

#### Summary
### Summary

* Time to complete the `1000000 requests` - smaller is better.
* Reqs/sec - bigger is better.
Expand All @@ -169,14 +150,79 @@ Statistics Avg Stdev Max

Iris MVC with Templates Application ran for **37 seconds** serving **26656.76** requests per second with **192.51MB/s** within **1.18ms** latency in average and **22.52ms** max, the memory usage of all these was ~17MB.

## Results with Sessions
# .NET Core (Kestrel) vs Iris

_Monday, 21 August 2017_

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 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).

Here we will check the sessions performance, this time
we wanna use the .NET Core raw, **not MVC** and Iris raw, not MVC respectfully.
## Simple

Spawn `5000000 requests` with 125 different "threads" that sets and gets a session with name `key` and string value `"value"` to the same static request path.
Spawn `1000000 requests` with 125 different "threads", tagrget to a dynamic registered route path, responds with a simple "value" text.

### .NET Core with Sessions
### .NET Core (Kestrel)

```bash
$ 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.
```

```bash
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

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

```bash
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.

## Sessions

Spawn `5000000 requests` with 125 different "threads" target a static request path, sets and gets a session with name `key` and string value `"value"` and write session value that to the response stream.

### .NET Core (Kestrel) with Sessions

```bash
$ cd netcore-sessions
Expand Down Expand Up @@ -222,7 +268,7 @@ Statistics Avg Stdev Max
Throughput: 20.65MB/s
```

#### Summary
### Summary

* Time to complete the `5000000 requests` - smaller is better.
* Reqs/sec - bigger is better.
Expand All @@ -233,6 +279,9 @@ Statistics Avg Stdev 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.

> A new article based on the latest, Kestrel and Iris, benchmarks is coming. Stay tuned!
> Click [here](screens) to navigate to the screenshots.
**Thank you all** for the 100% green feedback, have fun!

Expand Down
20 changes: 3 additions & 17 deletions _benchmarks/iris/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,8 @@ import (

func main() {
app := iris.New()
// These handlers are serving the same routes as
// `ValuesController`s of netcore-mvc and iris-mvc applications do.
app.Get("/api/values/{id}", getHandler)
app.Put("/api/values/{id}", putHandler)
app.Delete("/api/values/{id}", delHandler)
app.Get("/api/values/{id}", func(ctx context.Context) {
ctx.WriteString("value")
})
app.Run(iris.Addr(":5000"))
}

// getHandler handles "GET" requests to "api/values/{id}".
func getHandler(ctx context.Context) {
// id,_ := vc.Params.GetInt("id")
ctx.WriteString("value")
}

// putHandler handles "PUT" requests to "api/values/{id}".
func putHandler(ctx context.Context) {}

// delHandler handles "DELETE" requests to "api/values/{id}".
func delHandler(ctx context.Context) {}
25 changes: 25 additions & 0 deletions _benchmarks/netcore/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace netcore
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}

public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
}
38 changes: 38 additions & 0 deletions _benchmarks/netcore/Startup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Http;

namespace netcore
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)
{
services.AddRouting();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
var routeBuilder = new RouteBuilder(app);
routeBuilder.MapGet("api/values/{id}", context =>{
return context.Response.WriteAsync("value");
});
var routes = routeBuilder.Build();
app.UseRouter(routes);
}
}
}
8 changes: 8 additions & 0 deletions _benchmarks/netcore/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Error"
}
}
}
15 changes: 15 additions & 0 deletions _benchmarks/netcore/netcore.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
</ItemGroup>

<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
</ItemGroup>

</Project>
Binary file added _benchmarks/screens/1m_requests_iris.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _benchmarks/screens/1m_requests_netcore.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit d003e91

Please sign in to comment.