This dashboard visualizes the performance impact of different thread pool configurations in .NET 8.0. The tests measure how various settings affect request throughput and CPU efficiency.
By limiting worker threads to 1 and disabling semaphore spinning, we achieved 7.0x more requests per CPU core compared to the default configuration.
| Configuration | Description | Throughput (req/sec) | CPU Usage (%) * | Min-Max CPU (%) | Efficiency (req/sec/core) |
|---|---|---|---|---|---|
| 1 .NET Threads - oha 2 | 1 .NET worker threads, no semaphore spin, oha 2 threads | 112,337 | 133.0% | 122.1-145.2 | 84,447 🔥 |
| 1 .NET Thread - oha 1 | 1 .NET worker threads, no semaphore spin, oha 1 thread | 108,396 | 130.9% | 124.6-154.8 | 82,795 |
| 2 .NET Threads - oha 2 | 2 .NET worker threads, no semaphore spin, oha 2 threads | 130,484 | 240.1% | 158.8-256.4 | 54,356 |
| No Spin | Default .NET worker threads, no semaphore spin, oha 1 thread | 113,565 | 397.4% | 375.7-490.1 | 28,575 |
| Spin 10 | Default .NET worker threads, semaphore spin 10, oha 1 thread | 122,930 | 637.1% | 478.9-789.1 | 19,295 |
| Base Case | Default .NET worker threads, default semaphore spin, oha 1 thread | 112,629 | 933.6% | 833.9-970.5 | 12,064 |
| * CPU Usage shows the average usage across all samples. (est) indicates estimated values where measurement wasn't possible. | |||||
The core issue is that .NET's ThreadPool and async/await mechanics cause excessive thread context switching and CPU usage when handling HTTP requests. This is particularly problematic in high-throughput services.
Key observations: