Repository navigation
Benchmarks
This document is short on purpose. A published number needs a gate behind it, so it only carries figures that are deterministic and checked by tests/Carom.Tests/PublishedClaimsTests.cs, plus measurements stated with their limits.
Earlier versions of this document and the README claimed speed ratios against Polly (175,000x startup, 15x hot path, 4.8x async here; 3,750x and 2x in an older revision of this file). The two documents disagreed with each other and with re-measurement, because nothing checked them. Those ratios are deleted, not corrected: they came from stopwatch loops on a non-idle laptop, which is not a measurement worth publishing.
- Apple M1 laptop, macOS, .NET 8
- Polly 8.4.2 (
PollyandPolly.Corepackages) - Single process, stopwatch loops around warmed calls, machine not idle. Not BenchmarkDotNet.
Allocation counts and file sizes from this setup are exact. Timings from it are not, so none are published.
| Call | Allocated per call |
|---|---|
Carom Carom.Shot
|
0 B |
Polly v8 ResiliencePipeline.Execute
|
24 B |
Polly v7 API Policy.Execute
|
248 B |
Allocations were read with GC.GetAllocatedBytesForCurrentThread around a warmed loop, which is exact per thread. The 0 B figure is asserted by PublishedClaimsTests.Shot_SuccessfulSyncCall_AllocatesZeroBytes on every test run.
Release builds, bytes on disk:
| Assembly | Size |
|---|---|
| Carom.dll (netstandard2.0) | 19,968 B |
| Carom.Extensions.dll (netstandard2.0) | 51,200 B |
| Polly.Core.dll (net8.0, from the 8.4.2 package) | 242,736 B |
| Polly.dll (net6.0, from the 8.4.2 package) | 297,520 B |
These figures are a snapshot from one Release build, not asserted values. PublishedClaimsTests enforces upper bounds only: Carom.dll must stay at or under 40,960 B and Carom.Extensions.dll at or under 102,400 B. A build inside those bounds passes even if it no longer matches this table, so a doubling cannot ship unnoticed but small drift can.
Carom's numbers come from its project files (no PackageReference at all, enforced by PublishedClaimsTests). Polly.Core's come from the nuspec shipped in the 8.4.2 package:
| Target | Carom | Carom.Extensions | Polly.Core 8.4.2 |
|---|---|---|---|
| net8.0 | 0 | Carom only | 0 |
| net6.0 | 0 | Carom only | 1 |
| netstandard2.0 | 0 | Carom only | 4 |
| net462 / net472 | 0 | Carom only | 5 |
On net8.0, where new projects start, Polly.Core is also dependency-free. Carom's advantage is that it stays dependency-free on netstandard2.0 and .NET Framework, the hosts most likely to care.
Earlier versions compared building a Polly pipeline (about 5 microseconds, once) against assigning a Carom Bounce struct. An application builds its pipeline once and holds it, so that comparison does not describe anything a user waits for. It is retired.
Per successful call, both libraries cost on the order of tens to hundreds of nanoseconds, which disappears next to the I/O being wrapped. No ratio is published: choosing a resilience library on nanoseconds is the wrong reason, and the setup above cannot defend one anyway.
cd benchmarks/Carom.Benchmarks
dotnet run -c ReleaseResults land in BenchmarkDotNet.Artifacts/results/. If you produce BenchmarkDotNet numbers on an idle machine and want them published here, add a gate for them first.
Written from the Carom source. The repository is the source of truth; if a page disagrees with the code, the code wins. Licensed MPL-2.0.
Core
Carom.Extensions
Integrations
Project