Minimal API が「速い」と言われる理由
Minimal API は MVC / Controller に比べて起動時間もリクエスト処理も軽量です。とはいえデフォルトのまま使うだけで最速になるわけではないので、本番で効くチューニングポイントを 5 つに絞って紹介します。
1. エンドポイントメタデータを静的に宣言する
ラムダ内で毎回 DI からロガーを取るより、エンドポイントメタデータに解決結果をキャッシュする方が速いケースがあります。
app.MapGet("/orders/{id}", async (int id, OrderService svc) =>
await svc.FindAsync(id) is { } order ? Results.Ok(order) : Results.NotFound())
.WithName("GetOrder")
.CacheOutput(p => p.Expire(TimeSpan.FromSeconds(30)));
2. RequestDelegate ジェネレーターを有効化
.NET 10 では RequestDelegate ソースジェネレーターが既定で有効になり、AOT 互換コードが自動生成されます。古い SDK から移行するプロジェクトでは <EnableRequestDelegateGenerator>true</EnableRequestDelegateGenerator> が残っていないか確認し、不要になった設定は掃除しておきましょう。
3. JSON ソースジェネレーターとの併用
HTTPS / JSON で受け渡しするペイロードはソースジェネレーターに回すと、リフレクション経由より 2 倍近く速くなります。
[JsonSerializable(typeof(Order))]
[JsonSerializable(typeof(Order[]))]
internal partial class AppJsonContext : JsonSerializerContext { }
builder.Services.ConfigureHttpJsonOptions(o =>
o.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonContext.Default));
4. Output Caching を第一選択肢にする
Redis 等のキャッシュに頼らず、まず app.UseOutputCache() でエッジ直前のメモリキャッシュを効かせるだけでも、多くのエンドポイントで 10x スループットが出ます。
5. 非同期パイプラインでのスレッド使用を最小化
ValueTaskを返せるメソッドはValueTaskに。- 同期 I/O が紛れているならその場で気づくよう
AllowSynchronousIO = falseのまま運用する。 - EF Core の
AsNoTrackingを読み取り系クエリでは徹底する。
計測なくしてチューニングなし
どの改善が効くかはアプリ次第です。まず BenchmarkDotNet と dotnet-counters で基準値を取るところから始めるのが王道です。.NET 10 の dotnet-monitor 連携でコンテナ環境でも継続計測できるので、本番観測まで含めて設計しましょう。
