dotnet / dotnet/aspnetcore

App first request performance with many Minimal APIs

Open
#46,313 11 comments 0 reactions 0 assignees View on GitHub
area-minimal Needs: Design
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 5h
Merged PRs (30d)
276

Description

### Is there an existing issue for this?

- [X] I have searched the existing issues

### Describe the bug

Found while investigating https://github.com/dotnet/aspnetcore/issues/46154

The app below has 30,000 endpoints. The first request to `/` takes 0.5 seconds with 280 MB memory usage:

```cs
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Http.Metadata;
using Microsoft.AspNetCore.Mvc;

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

app.Use(async (HttpContext context, Func next) =>
{
Console.WriteLine("Start time");
Stopwatch stopwatch = Stopwatch.StartNew();

await next();

stopwatch.Stop();
Console.WriteLine(stopwatch.Elapsed.TotalSeconds);
});

app.UseRouting();

Task Plaintext(HttpContext context) => context.Response.WriteAsync("Hello, World!");
for (int i = 0; i < 30_000; i++)
{
var url = "/plaintext/nested" + i;
app.MapGet(url, Plaintext);
}

app.MapGet("/", (HttpContext context) =>
{
return context.Response.WriteAsync("Hello world");
});

Console.WriteLine("Running app");
app.Run();
```

If I change the `Plaintext` endpoint to be a minimal API (aka use `RequestDelegateFactory`) like so:

```diff
- Task Plaintext(HttpContext context) => context.Response.WriteAsync("Hello, World!");
+ string Plaintext() => "Hello, World!";
```

With 30,000 minimal APIs, it now takes 32 seconds to get the first request. And memory usage is 1,065 MB.

### Expected Behavior

I expect a fast startup time.

I think the problem is `RequestDelegateFactory` is building and compiling expressions for all minimal API endpoints when routing starts. Creating a minimal API's expression should be lazy and wait until an endpoint is first visited.

### Steps To Reproduce

_No response_

### Exceptions (if any)

_No response_

### .NET Version

_No response_

### Anything else?

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.