Stress tests
Kevlar and Polly v8 run the same composed timeout, retry, and circuit-breaker workload under sustained parallel load. Alternating measurement rounds run in a single process, so they use the same GitHub runner while balancing early- and late-run conditions.
Last updated 2026-10-05 03:48 UTC (commit a78926f).
note
Shared CI runners vary. Treat one run as a sustained-load health check, not a universal capacity claim. Compare ratios and allocation behavior, then measure your own workload.
Latest result
| Scenario | Workers | Library | Throughput | CPU | Allocated | Allocated/op | GC pause | GC collections (0 / 1 / 2) | Process lock contentions |
|---|---|---|---|---|---|---|---|---|---|
| Shared timeout → retry → ratio breaker | 1 | Kevlar | 3.13M ops/s | 100% | 8.54 KiB | 0.00 B | 0.00 ms | 0 / 0 / 0 | 1 |
| Shared timeout → retry → ratio breaker | 1 | Polly | 1.81M ops/s | 100% | 7.28 GiB | 48.00 B | 127.01 ms | 466 / 8 / 0 | 1 |
| Shared timeout → retry → ratio breaker | 4 | Kevlar | 7.34M ops/s | 398% | 12.34 KiB | 0.00 B | 0.00 ms | 0 / 0 / 0 | 3 |
| Shared timeout → retry → ratio breaker | 4 | Polly | 3.61M ops/s | 397% | 14.51 GiB | 48.00 B | 327.87 ms | 932 / 8 / 0 | 2.92K |
| Shared timeout → retry | 4 | Kevlar | 12.09M ops/s | 399% | 12.23 KiB | 0.00 B | 0.00 ms | 0 / 0 / 0 | 1 |
| Shared timeout → retry | 4 | Polly | 5.24M ops/s | 398% | 10.53 GiB | 24.00 B | 227.49 ms | 675 / 8 / 0 | 378 |
| Per-worker timeout → retry → ratio breaker | 4 | Kevlar | 8.57M ops/s | 399% | 18.12 KiB | 0.00 B | 0.00 ms | 0 / 0 / 0 | 0 |
| Per-worker timeout → retry → ratio breaker | 4 | Polly | 3.63M ops/s | 398% | 14.61 GiB | 48.00 B | 326.60 ms | 937 / 8 / 0 | 282 |
| Shared open breaker — every call rejected | 4 | Kevlar | 14.69M ops/s | 390% | 177.37 GiB | 144.00 B | 2.50 s | 11577 / 8 / 0 | 0 |
| Shared open breaker — every call rejected | 4 | Polly | 5.87M ops/s | 392% | 98.47 GiB | 200.00 B | 1.64 s | 6323 / 8 / 0 | 57.23K |
Comparisons
| Scenario | Workers | Kevlar / Polly throughput |
|---|---|---|
| Shared timeout → retry → ratio breaker | 1 | 1.73× |
| Shared timeout → retry → ratio breaker | 4 | 2.04× |
| Shared timeout → retry | 4 | 2.31× |
| Per-worker timeout → retry → ratio breaker | 4 | 2.36× |
| Shared open breaker — every call rejected | 4 | 2.50× |
Method
- 1 and 4 parallel workers; 15 minutes total measured time, split equally between scenarios and libraries across 4 alternating rounds.
- Each scenario and library warmed for 2 seconds before measurement.
- Shared and per-worker ratio-breaker scenarios run Timeout(10 s) → Retry(3, no delay) → CircuitBreaker(10% over 30 s, min 100, break 5 s).
- Timeout/retry isolates pipeline overhead from circuit-breaker shared-state contention.
- The shared open-breaker scenario trips one breaker for the whole run, so every call measures contended fast-fail rejection.
- Process-wide CPU, allocation, GC pause, collection, and managed-lock contention counters are captured separately for each phase.
- Peak working set for the shared process: 82.04 MiB.
Environment
- Ubuntu 24.04.5 LTS
- .NET 10.0.12
- 4 logical processors visible to .NET
Reproduce
dotnet run -c Release --project benchmarks/Kevlar.StressTests -- --duration 00:15:00
Use --workers, --warmup, and --output to override the defaults. The stress workflow runs weekly and republishes this page.