-
Notifications
You must be signed in to change notification settings - Fork 0
Performance Benchmark
The following stress test was run on the following computer specs:
The source code of running this test is available at: HearthPortableWebServer.StressTest
Target web application in the test: Un-initialized Hearth CMS (Pageless ASP.NET Web Forms CMS)
- OS: Windows 11 Pro x64 25H2 (OS build: 26200.8655)
- CPU: Intel Core i7-4770S @ 3.10GHz (Max Turbo Boost: 3.90GHz)
- Cores: 4 Physical, 8 Logical Processors
- Cache: L1: 256 KB | L2: 1.0 MB | L3: 8.0 MB
- RAM: 24GB DDR3
- Storage: Samsung SSD 870 EVO 500GB
============================================================================================
Portable ASP.NET Web Server - Stress Test Report
============================================================================================
Generated : 2026-06-21 20:59:24
Target URL : http://localhost:8080/
Duration : 10 s measured per level (warmup 3 s)
Machine : ZEN, 8 logical CPUs, x86 test client
--------------------------------------------------------------------------------------------
Per-level results (latency in milliseconds):
Conc Requests Req/sec Req/min OK Fail Avg p50 p90 p95 p99 Max
----- ---------- ----------- ------------- -------- ------ -------- ------- ------- ------- ------- --------
1 33,458 3,345.8 200,746 33,458 0 0.30 0.3 0.3 0.3 0.4 3.9
2 60,884 6,088.2 365,293 60,884 0 0.33 0.3 0.4 0.4 0.7 5.3
4 98,468 9,846.5 590,791 98,468 0 0.41 0.4 0.4 0.5 1.0 11.1
8 134,609 13,460.4 807,624 134,609 0 0.59 0.5 0.7 0.9 1.5 83.1
16 144,943 14,493.5 869,608 144,943 0 1.10 1.0 1.5 1.9 2.6 11.3
32 147,021 14,700.0 882,001 147,021 0 2.18 2.0 3.0 3.5 4.5 17.9
64 138,550 13,849.2 830,951 138,550 0 4.62 4.2 8.3 9.7 13.5 88.3
128 149,914 14,979.9 898,796 149,914 0 8.53 8.3 13.6 15.0 20.6 58.1
256 127,077 12,695.9 761,756 127,077 0 20.14 18.6 33.1 38.8 48.5 75.2
--------------------------------------------------------------------------------------------
PEAK THROUGHPUT
Concurrency level : 128
Requests / second : 14,979.9
Requests / minute : 898,796
Avg latency : 8.53 ms
p99 latency : 20.60 ms
--------------------------------------------------------------------------------------------
Status code distribution (all levels):
200 : 1,034,924
--------------------------------------------------------------------------------------------
Total requests sent : 1,034,924
Total failures : 0
Total data received : 3,532.4 MB
============================================================================================
Windows 11 built-in IIS server, same application, and run the stress test, and here is the result (single worker process):
============================================================================================
Portable ASP.NET Web Server - Stress Test Report
============================================================================================
Generated : 2026-06-21 21:07:48
Target URL : http://localhost:8006/
Duration : 10 s measured per level (warmup 3 s)
Machine : ZEN, 8 logical CPUs, x86 test client
--------------------------------------------------------------------------------------------
Per-level results (latency in milliseconds):
Conc Requests Req/sec Req/min OK Fail Avg p50 p90 p95 p99 Max
----- ---------- ----------- ------------- -------- ------ -------- ------- ------- ------- ------- --------
1 28,251 2,825.0 169,500 28,251 0 0.35 0.3 0.4 0.4 0.5 1.6
2 46,986 4,698.4 281,907 46,986 0 0.42 0.4 0.5 0.5 0.8 3.4
4 77,771 7,777.1 466,624 77,771 0 0.51 0.5 0.6 0.6 1.2 11.3
8 107,843 10,782.7 646,962 107,843 0 0.74 0.7 0.9 1.1 1.9 25.4
16 123,504 12,348.9 740,935 123,504 0 1.29 1.2 1.7 2.1 2.8 15.6
32 124,587 12,456.1 747,366 124,587 0 2.57 2.4 3.4 3.9 4.9 17.8
64 126,916 12,683.4 761,003 126,916 0 5.04 4.9 7.1 8.0 9.2 19.2
128 128,959 12,881.1 772,866 128,959 0 9.93 10.0 14.6 15.7 17.8 71.0
256 122,203 12,208.0 732,480 122,203 0 20.95 20.6 28.5 31.3 36.6 58.7
--------------------------------------------------------------------------------------------
PEAK THROUGHPUT
Concurrency level : 128
Requests / second : 12,881.1
Requests / minute : 772,866
Avg latency : 9.93 ms
p99 latency : 17.83 ms
--------------------------------------------------------------------------------------------
Status code distribution (all levels):
200 : 887,020
--------------------------------------------------------------------------------------------
Total requests sent : 887,020
Total failures : 0
Total data received : 3,027.6 MB
============================================================================================
| Concurrency | Portable server | IIS (1 worker) | Portable advantage |
|---|---|---|---|
| 1 | 3,346 | 2,825 | +18% |
| 2 | 6,088 | 4,698 | +30% |
| 4 | 9,847 | 7,777 | +27% |
| 8 | 13,460 | 10,783 | +25% |
| 16 | 14,494 | 12,349 | +17% |
| 32 | 14,700 | 12,456 | +18% |
| 64 | 13,849 | 12,683 | +9% |
| 128 | 14,980 | 12,881 | +16% |
| 256 | 12,696 | 12,208 | +4% |
- Peak Performance: The portable server maxed out at ~14,980 req/s vs IIS at ~12,881 req/s—clocking in about 16% faster overall, and leading at every single concurrency level.
- Latency: The portable server maintained lower latency across the board (e.g., at Concurrency 8: 0.59 ms vs 0.74 ms).
- Stability: Both servers successfully processed 100% of requests with zero failures.
This does not automatically mean the Hearth portable server is inherently "better" than IIS. Rather, it indicates the portable server executes fewer instructions per request. In a CPU-bound loopback test, this minimalism translates directly into higher throughput.
-
Shorter Pipeline: Both servers share the same kernel driver (
HTTP.sys), which explains why their base numbers are in the same ballpark. However, above the kernel layer, IIS executes a heavy native module pipeline (Authentication, Request Filtering, Static/Dynamic Content, Compression, Health Monitoring, etc.). Hearth goes almost directly fromHTTP.systoHttpRuntime.ProcessRequest. Fewer modules = fewer CPU cycles per request. - No Access Logging: Stock IIS writes W3C request logs to disk by default, introducing noticeable I/O overhead at ~13K req/s. The portable server logs nothing.
- No Process Management Overhead: IIS constantly manages app-pool health pings, idle/CPU monitoring, and recycling checks. The portable worker focuses solely on serving requests.
Throughput is only one piece of the puzzle. IIS's extra overhead funds enterprise features that the portable server simply lacks:
-
Kernel-Mode Output Caching: For cacheable responses,
HTTP.syscan serve hundreds of thousands of requests per second, far bypassing these benchmarks. Because this test featured a dynamic, uncacheable page, this advantage wasn't utilized. - Resilience & Scalability: Web gardens (multiple worker processes), automatic crash recovery, app-pool recycling, and overlapped recycling.
- Security: Native request filtering, TLS/SNI management, Windows Authentication, and IP restrictions.
- Operations: Detailed logging, performance counters, Failed-Request Tracing, and dynamic compression.
Test Caveat: Both client and server shared the same 8 logical CPUs, meaning both ceilings are artificially constrained. Running this test using a separate machine over a physical network would raise the performance ceiling for both—and could either narrow or widen the gap.
Out of the box, the Hearth Portable Server is leaner and edges out a stock, single-worker IIS by ~16% on this dynamic workload. If you stripped IIS down (disabled logging, removed unused modules), it would likely close most of this gap. Conversely, if kernel output caching were enabled on a cacheable page, IIS would pull far ahead.
The most reassuring takeaway isn't the 16% speed advantage—it's that both reports show an identical traffic shape. Both saturate around concurrency 8–16, peak at 128, dip at 256, and stay completely error-free.
Hearth doesn't just run fast; it behaves like a mature server under load, demonstrating graceful saturation and textbook Little's Law latency growth.
| Concurrency (Simultaneous Users) | Performance Per Minute (Req/Min) | Health Status |
|---|---|---|
| 1 | 200,746 | 🟢 Perfect (No line) |
| 2 | 365,293 | 🟢 Perfect |
| 4 | 590,791 | 🟢 Efficiency multiplying |
| 8 | 807,624 | 🟡 CPU is working hard |
| 16 | 869,608 | 🟡 Approaching CPU limit |
| 32 | 882,001 | 🔴 CPU is Maxed Out (Throughput flattens) |
| 64 | 830,951 | 🔴 CPU is maxed (Small dip due to thread switching) |
| 128 (PEAK) | 898,796 | 🔥 Absolute Maximum Performance Ceiling |
| 256 | 761,756 | 📦 Saturated (Safe queueing active) |