Skip to content

[Routing] Significant performance regression when using a simple MapControllerRoute instead of MapGet on a bare-bones/starter .net 6 app (running on Azure App Service) #39250

Closed
@samcic

Description

@samcic

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

Consider this bare-bones .net 6 app (Github repo linked below):

// Program.cs

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var app = builder.Build();

// Option 1: "Fast"
// app.MapGet("/home/content", () => "Hello World!");

// Option 2: "Slow"
// app.MapControllerRoute("default", "{controller}/{action}");

app.Run();

// HomeController.cs

using Microsoft.AspNetCore.Mvc;
namespace WebApplication27.Controllers;

public class HomeController : Controller
{
    public ContentResult Content()
    {
        return Content("hello world");
    }
}

If I deploy this app to Azure App Service with "Option 1 (fast)" uncommented (i.e. using MapGet) and use the App Service Metrics blade to measure the average response time for sequential requests to /home/content (with a 100ms wait between each request) over a time span of many minutes, the average response time is of the order of just a few milliseconds 👍 .

image

If I then redeploy with nothing changed except for uncommenting "Option 2 (slow)" instead (i.e. using MapControllerRoute), the average response time becomes of the order of 20 milliseconds ☹️ .

image

Is this "by design"? That is, is this overhead of using this standard MapControllerRoute expected? Considering how simple this app is, I was quite surprised to see how much the average response time (for every request) increased when using Option 2, i.e. when invoking the controller-routing middleware.

Is there anything that could be done for this bare-bones app to improve the performance of this MapControllerRoute option?

Some related notes for context:

  • I have a much more complex .net core app deployed to App Service that interacts with various dependencies (e.g. database) and has an average production response time of between 40-50ms. The same test based on a copy of our production app (not included here) showed the same routing performance hit. That is, this routing performance hit of ~20ms for every requested controller action seems to be responsible for a significant portion of my average production response time. If there were a way to eliminate this ~20ms routing cost (while still using controllers) we could significantly optimize our response time.

  • On my local dev machine (a high-end ThinkPad X1), the average response time was 0.750ms for the MapGet case and 1.250ms for the MapControllerRoute case (i.e. not quite as pronounced). The metrics shown above were from an App Service Plan at level S1, which is a "standard" Azure App Service plan level for production workloads.

  • Using MapDynamicControllerRoute has similar performance to MapControllerRoute.

  • I tried both 32-bit and 64-bit App Service options (same results).

  • I also tried a .net 5 app with the same configuration (same results).

Expected Behavior

Although we of course understand that controller-based routing is more sophisticated, we would expect a simple app like this (i.e. a single controller) to not have such a performance regression for every request when using MapControllerRoute instead of MapGet.

Steps To Reproduce

Minimal repo project:

https://github.com/samcic/WebApplication27

Exceptions (if any)

N/A

.NET Version

6.0.101

Anything else?

Azure App Service Test Environment:
App Service Plan Level: S1

image

image

IDE: VS2022 17.0.4

> dotnet --info

.NET SDK (reflecting any global.json):
 Version:   6.0.101
 Commit:    ef49f6213a

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19042
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\6.0.101\

Host (useful for support):
  Version: 6.0.1
  Commit:  3a25a7f1cc

.NET SDKs installed:
  2.1.701 [C:\Program Files\dotnet\sdk]
  2.1.801 [C:\Program Files\dotnet\sdk]
  2.2.207 [C:\Program Files\dotnet\sdk]
  2.2.301 [C:\Program Files\dotnet\sdk]
  2.2.401 [C:\Program Files\dotnet\sdk]
  3.0.100 [C:\Program Files\dotnet\sdk]
  3.1.403 [C:\Program Files\dotnet\sdk]
  5.0.300 [C:\Program Files\dotnet\sdk]
  6.0.101 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.All 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.15 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.1.15 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

To install additional .NET runtimes or SDKs:
  https://aka.ms/dotnet-download

Metadata

Metadata

Assignees

Labels

✔️ Resolution: AnsweredResolved because the question asked by the original author has been answered.Status: Resolvedold-area-web-frameworks-do-not-use*DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions