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-19 06:46 UTC (commit 57d9416).
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 | 2.66M ops/s | 100% | 8.23 KiB | 0.00 B | 0.00 ms | 0 / 0 / 0 | 0 |
| Shared timeout → retry → ratio breaker | 1 | Polly | 1.34M ops/s | 100% | 5.39 GiB | 48.00 B | 101.21 ms | 344 / 8 / 0 | 0 |
| Shared timeout → retry → ratio breaker | 4 | Kevlar | 6.17M ops/s | 397% | 13.12 KiB | 0.00 B | 0.00 ms | 0 / 0 / 0 | 2 |
| Shared timeout → retry → ratio breaker | 4 | Polly | 2.72M ops/s | 397% | 10.93 GiB | 48.00 B | 282.83 ms | 701 / 8 / 0 | 3.29K |
| Shared timeout → retry | 4 | Kevlar | 9.53M ops/s | 398% | 9.12 KiB | 0.00 B | 0.00 ms | 0 / 0 / 0 | 1 |
| Shared timeout → retry | 4 | Polly | 3.83M ops/s | 398% | 7.70 GiB | 24.00 B | 185.84 ms | 495 / 8 / 0 | 950 |
| Per-worker timeout → retry → ratio breaker | 4 | Kevlar | 6.40M ops/s | 398% | 16.93 KiB | 0.00 B | 0.00 ms | 0 / 0 / 0 | 0 |
| Per-worker timeout → retry → ratio breaker | 4 | Polly | 2.79M ops/s | 398% | 11.22 GiB | 48.00 B | 283.14 ms | 719 / 8 / 0 | 642 |
| Shared open breaker — every call rejected | 4 | Kevlar | 10.86M ops/s | 392% | 131.08 GiB | 144.00 B | 1.93 s | 8557 / 8 / 0 | 0 |
| Shared open breaker — every call rejected | 4 | Polly | 4.79M ops/s | 393% | 80.26 GiB | 200.00 B | 1.36 s | 5153 / 8 / 0 | 39.29K |
Comparisons
| Scenario | Workers | Kevlar / Polly throughput |
|---|---|---|
| Shared timeout → retry → ratio breaker | 1 | 1.99× |
| Shared timeout → retry → ratio breaker | 4 | 2.27× |
| Shared timeout → retry | 4 | 2.49× |
| Per-worker timeout → retry → ratio breaker | 4 | 2.30× |
| Shared open breaker — every call rejected | 4 | 2.27× |
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: 81.18 MiB.
Environment
- Ubuntu 24.04.5 LTS
- .NET 10.0.13
- 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.