🕵️ SicherheitslückenWhat continuous operational resilience looks like under DORA(09.09.2026 um 17:53 Uhr)
🔧 AI Nachrichten OpenAI seeks tougher AI rules. CIOs may feel the ripple effects(10.09.2026 um 12:11 Uhr)
🔧 AI Nachrichten Mistral valued at €21bn after €3bn Series D funding round(08.09.2026 um 10:19 Uhr)
🪟 Windows TippsWindows XP's Cursor Indicator Is Getting a Windows 11 Refresh(25.08.2026 um 13:00 Uhr)
🕵️ SicherheitslückenWhat continuous operational resilience looks like under DORA(09.09.2026 um 17:53 Uhr)
🔧 AI Nachrichten OpenAI seeks tougher AI rules. CIOs may feel the ripple effects(10.09.2026 um 12:11 Uhr)
🔧 AI Nachrichten Mistral valued at €21bn after €3bn Series D funding round(08.09.2026 um 10:19 Uhr)
🪟 Windows TippsWindows XP's Cursor Indicator Is Getting a Windows 11 Refresh(25.08.2026 um 13:00 Uhr)

🔧 Programmierung 🕛 vor 2 Monaten 8 Min Lesezeit
0

The People v. ASP.NET Core: A C#-Only HTTP Benchmark Trial

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

All rise. The Honorable HttpArena presiding.



Today's docket is exclusively C# versus C#. No Rust defendants smirking from the gallery, no Go gophers passing notes. Just .NET frameworks, their press releases, and a 64-core AMD Threadripper PRO 3995WX that does not care about your README. Every entry was run through 27 scored profiles in an identical Dockerized harness — server pinned to one half of the chip, the gcannon load generator pinned to the symmetric other half, so the prosecution literally cannot steal cycles from the witness.



The court's motto, etched above the bench: "Don't just say you're fast, prove it."



Before any number is admitted into evidence, the defendant must pass an 18-point validation suite with randomized anti-cheat probes — random query sums, two different random POST bodies (to catch response caching), empty-range DB queries that must return zero rows, and a TCP fragmentation test that splits the request across multiple writes with 30ms pauses. You cannot hardcode your way to an acquittal. Correctness is a precondition for a score.



Let's hear the cases.






Count One: GenHTTP v. ASP.NET Core, the headline rivalry



The prosecution alleges that GenHTTP — a community project by Kaliumhexacyanoferrat — claims to outrun Microsoft's flagship. Bold. The kind of claim that usually gets a framework held in contempt.



Except the evidence holds up. Taking the best variant of each camp per profile, the tally is GenHTTP 14, ASP.NET 4.



Exhibit A: the CRUD podium. A clean C# sweep, top to bottom, in requests per second:
















































Rank Framework RPS
1 genhttp-11 518,433
2 genhttp 464,774
3 genhttp-kestrel 452,652
4 simplew 430,132
5 simplew-tuned 417,396
6 aspnet-minimal 396,825
7 aspnet-iouring 357,713


The defense for Microsoft objects: "Minimal API is production-hardened, Your Honor." Sustained, and irrelevant. On this count, genhttp-11 beat aspnet-minimal by 1.31x.



The court asks: how? The answer is architectural, not magical. GenHTTP is a server and a framework in one library — your app is a tree of composable handler modules, not middleware on someone else's pipeline. On genhttp-11's native HTTP/1.1 engine, a request goes from a tight 1.1 parser straight into a precompiled handler tree with no ASP.NET middleware chain in the way. When the work per request is trivial — a baseline sum, a small JSON body — framework overhead dominates, and the leaner server wins.




CODE
// Wired once at startup, not per request:
Layout.Create()
.Add("pipeline", Content.From(Resource.FromString("ok")))
.AddService<Baseline>("baseline11")
.AddService<Json>("json")
.AddStaticFiles()
.AddWebsocket();






The allocation discipline is admitted into the record too: ArrayPool<byte>.Shared for the 16KB upload buffer, Websocket.Imperative().DoNotAllocateFrameData() for zero-copy echo frames, server GC, and an Npgsql multiplexing pool. This is not a framework that says it's careful. The bytes don't lie.



The full spread of GenHTTP's 14 wins, for the record: baseline 1.20x (2,075,459 vs 1,733,724), pipelined 1.40x (17,885,664 vs 12,807,538), limited-conn a brutal 2.24x, json 1.38x, json-comp 1.28x, json-tls 1.30x, upload 1.91x, static 1.47x, crud 1.31x, api-4 1.11x, api-16 1.29x, echo-ws 1.26x, and echo-ws-pipeline 1.45x (28.6M vs 19.7M frames). The fourteenth is baseline-h3 at 1.02x — the framework equivalent of winning an argument by a single word and then refusing to make eye contact. On plaintext HTTP/1.1 and WebSockets, the verdict is not close.






Count Two: ASP.NET's airtight alibi



Now the defense gets its moment, and it's a strong one. ASP.NET's 4 wins span HTTP/2 (baseline-h2, static-h2), HTTP/3 (static-h3), and async-db.

































Profile Winner Margin
baseline-h2 aspnet-minimal 1.48x (2,648,217 vs 1,792,309)
static-h2 aspnet-minimal 2.33x (375,583 vs 161,502)
static-h3 aspnet-minimal 1.20x
async-db aspnet-minimal 1.15x (225,491 vs 196,599)


Here's the twist the jury needs to understand: GenHTTP's native engine is HTTP/1.1-only. No HPACK, no stream multiplexing, no QUIC. So for HTTP/2 and HTTP/3, GenHTTP must borrow Kestrel — the genhttp-kestrel variant ships libmsquic and binds 8443 over TCP and UDP. And once both sides are standing on Kestrel, Microsoft's years-hardened h2 stack — tuned here to 256 streams per connection, a 2MB connection window, 1MB stream windows — wins decisively. The 2.33x static-h2 margin isn't an upset. It's the incumbent defending its own courthouse.



That "Kestrel owns h2" story covers exactly two of these rows — baseline-h2 and static-h2. The other two wins are different animals. async-db is a database-bound profile; that one rides Npgsql and async query handling, not the maturity of an h2 stack. And static-h3 is HTTP/3 — where ASP.NET does not sweep, because GenHTTP took baseline-h3 by 1.02x. Call QUIC a split decision, not a shutout.



Engine/handler separation is the whole trick, and it cuts both ways: the same handler tree drops onto GenHTTP's engine or onto Kestrel unchanged. GenHTTP wins where its lean engine runs; it concedes where it has to rent Microsoft's.






Count Three: the witness who built their own runtime



aspnet-minimal-iouring takes the stand wearing the most elaborate alibi in the building. To swap Kestrel's socket transport from epoll to io_uring, it ships a hand-built fork of the .NET runtime (Ben Adams' branch, dotnet/runtime#124374) via a 3-stage Docker build that clones, patches socket internals with a Python script, and overlays System.Net.Sockets.dll onto the stock framework.



That's not a fighter, that's a fighter who reforged his own gloves in the locker room. The patch exists because the branch wouldn't even compile — it had to rewrite a &result taken on an out int param and clamp io_uring's 128-byte accept sockaddr into a family-sized buffer. The court admires the dedication. It also notes that io_uring with SQPOLL pays off on cheap pipelined h1, not CPU-bound h2/TLS — and on CRUD it landed 7th. Effort is not throughput.






Count Four: the marketing department, on trial



Some claims did not survive cross-examination.



ServiceStack, the "one framework to power them all," posted 22,976 RPS on json-4096 (dead last) and 14,268 on pipelined-512 (also dead last). The prosecution produces CPU traces: ~700–1700% utilization on a 64-core box. That is not a framework saturating its cores. That is the enterprise tax showing up on a Tuesday — a full DTO pipeline on Kestrel plus a global response-compression middleware that taxes even the plaintext ok route. Guilty of layering.



aspnet-mvc is its co-defendant. The same handlers that fly under Minimal API get bogged down behind controller dispatch, model binding, filters, content negotiation, and reflection-based JSON of anonymous objects on every single request. Minimal APIs compile each MapGet into a near-direct RequestDelegate; MVC pays the family's catering bill, request after request.



aspnet-minimal-aot pleads efficiency. True — Native AOT strips the JIT and reflection surface and wins on cold start. But under cross it concedes ~900MiB–1GiB working set, because ServerGC reserves the heap regardless. Footprint is a heap problem, not a JIT problem.



simplew-tuned is the most honest witness in the room: the entire speedup over plain simplew is four socket flags — TcpNoDelay, ReuseAddress, TcpKeepAlive, ReusePort — plus a compressed static-file cache. Same application code. No perjury, just config.






A note on the geomean defendants



The court must address an attempted mistrial. A naive geomean composite shows dogrider — the arena owner's own zerg io_uring WebSocket echo server — and fleck sitting on top. Objection sustained: they ran only 2 WebSocket profiles each. The naive composite is a geometric mean taken only over the profiles an entry actually ran — so a two-profile WebSocket specialist with monster echo numbers floats to the top on a sample size of two. The fix a fair ranking needs is coverage-weighting: average across all 27 profiles, zero-filling the ones an entry skipped. Do that and the two-trick acts sink, because every ducked profile becomes a zero dragging the mean down — which is exactly the point. A framework covering 24 profiles at 80% beats a specialist who only showed up twice. Even the platform owner's entry doesn't get to skip the work and keep the crown.



So the real findings of fact:





  • Most complete all-rounder: aspnet-minimal, 24 profiles.


  • Broadest performance leader: genhttp-11, 14 head-to-head wins.






The verdict



On plaintext, pipelining, uploads, static files, CRUD, and WebSockets, the community challenger genhttp-11 outperforms Microsoft's flagship. On HTTP/2 — and on a database-bound async route — ASP.NET Core's mature stack wins so cleanly that on h2 GenHTTP shows up borrowing it; HTTP/3 splits down the middle. Both headline claims — "the lean engine is faster" and "Kestrel owns h2" — are, on this evidence, true.



This is one published round: a snapshot, not a statute. Re-check the leaderboard, audit the raw load-generator logs, and if your C# framework thinks it can take the stand — add it. The harness is open, the same Threadripper awaits, and ./scripts/validate.sh is the bailiff. Bring a dish to the cookout. Just, you know, prove it's good first.



Court is adjourned. See the full evidence at http-arena.com.

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
Sam Altman calls GPT-6 Astra rollout ‘messy’ as enterprise users wait for access
1 Quelle
Swiss government explores replacing Microsoft 365 with open-source software
1 Quelle
What continuous operational resilience looks like under DORA
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten The People v. ASP.NET Core: A C#-Only HTTP Benchmark Trial

Thematisch verwandte Begriffe: People, ASPNET, Core, COnly · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...