Performance Benchmarks
This page presents comprehensive benchmark results comparing Spinner v1.x with v2.0, demonstrating the significant performance improvements achieved in the new version.
Benchmark Environment
All benchmarks were executed under the following conditions:
- OS: Windows 11 (10.0.26200.7171)
- CPU: 12th Gen Intel Core i5-12500H @ 2.50GHz (1 CPU, 16 logical and 12 physical cores)
- Tool: BenchmarkDotNet v0.15.6
- SDK: .NET SDK 10.0.100
- Runtimes Tested: .NET 8.0, .NET 9.0, .NET 10.0
- Configuration: Server GC Enabled
Read Operations Performance
ReadFromString
Comparison of reading positional strings and converting them to objects.
v2.0 Results (After Optimization)
| Runtime | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|
| .NET 10.0 | 46.32 ns | 0.793 ns | 0.742 ns | 32 B |
| .NET 8.0 | 53.66 ns | 0.637 ns | 0.596 ns | 32 B |
| .NET 9.0 | 54.57 ns | 0.409 ns | 0.382 ns | 32 B |
v1.x Results (Before Optimization)
| Runtime | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|
| .NET 10.0 | 2.821 µs | 0.0098 µs | 0.0076 µs | 664 B |
| .NET 8.0 | 3.059 µs | 0.0386 µs | 0.0323 µs | 664 B |
| .NET 9.0 | 1.269 µs | 0.0223 µs | 0.0208 µs | 664 B |
Performance Improvement
| Runtime | Speed Improvement | Memory Improvement |
|---|---|---|
| .NET 10.0 | ~60x faster ⚡ | ~20x less 💾 |
| .NET 8.0 | ~57x faster ⚡ | ~20x less 💾 |
| .NET 9.0 | ~23x faster ⚡ | ~20x less 💾 |
The ReadFromString method in v2.0 is up to 60 times faster and uses 20 times less memory compared to v1.x!
ReadFromSpan
Comparison of reading from ReadOnlySpan<char> for zero-allocation parsing.
v2.0 Results (After Optimization)
| Runtime | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|
| .NET 10.0 | 44.34 ns | 0.496 ns | 0.464 ns | 32 B |
| .NET 8.0 | 51.30 ns | 0.806 ns | 0.754 ns | 32 B |
| .NET 9.0 | 55.31 ns | 0.746 ns | 0.697 ns | 0 B* |
*Near-zero allocation in .NET 9.0
v1.x Results (Before Optimization)
| Runtime | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|
| .NET 10.0 | 2.774 µs | 0.0320 µs | 0.0300 µs | 664 B |
| .NET 8.0 | 1.321 µs | 0.0253 µs | 0.0281 µs | 664 B |
| .NET 9.0 | 1.275 µs | 0.0242 µs | 0.0259 µs | 664 B |
Performance Improvement
| Runtime | Speed Improvement | Memory Improvement |
|---|---|---|
| .NET 10.0 | ~62x faster ⚡ | ~20x less 💾 |
| .NET 8.0 | ~25x faster ⚡ | ~20x less 💾 |
| .NET 9.0 | ~23x faster ⚡ | ~∞ (zero-alloc) 💾 |
ReadFromString with Interceptor
Performance when using custom interceptors for value transformation.
v2.0 Results (After Optimization)
| Runtime | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|
| .NET 10.0 | 50.25 ns | 0.355 ns | 0.297 ns | 32 B |
| .NET 8.0 | 77.14 ns | 0.805 ns | 0.753 ns | 32 B |
| .NET 9.0 | 62.20 ns | 0.752 ns | 0.667 ns | 32 B |
v1.x Results (Before Optimization)
| Runtime | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|
| .NET 10.0 | 4.014 µs | 0.0649 µs | 0.0608 µs | 848 B |
| .NET 8.0 | 1.816 µs | 0.0359 µs | 0.0336 µs | 784 B |
| .NET 9.0 | 1.697 µs | 0.0317 µs | 0.0296 µs | 840 B |
Performance Improvement
| Runtime | Speed Improvement | Memory Improvement |
|---|---|---|
| .NET 10.0 | ~79x faster ⚡ | ~26x less 💾 |
| .NET 8.0 | ~23x faster ⚡ | ~24x less 💾 |
| .NET 9.0 | ~27x faster ⚡ | ~26x less 💾 |
Even with custom interceptors, v2.0 achieves up to 79x faster execution with 26x less memory allocation!
Write Operations Performance
WriteAsString
Comparison of converting objects to positional strings.
v2.0 Results (After Optimization)
| Runtime | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|
| .NET 10.0 | 39.52 ns | 0.739 ns | 0.691 ns | 128 B |
| .NET 8.0 | 48.32 ns | 0.467 ns | 0.437 ns | 128 B |
| .NET 9.0 | 51.28 ns | 1.087 ns | 3.170 ns | 128 B |
v1.x Results (Before Optimization)
| Runtime | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|
| .NET 10.0 | 1.243 µs | 0.0245 µs | 0.0478 µs | 808 B |
| .NET 8.0 | 1.413 µs | 0.0281 µs | 0.0586 µs | 808 B |
| .NET 9.0 | 1.344 µs | 0.0266 µs | 0.0382 µs | 808 B |
Performance Improvement
| Runtime | Speed Improvement | Memory Improvement |
|---|---|---|
| .NET 10.0 | ~31x faster ⚡ | ~6x less 💾 |
| .NET 8.0 | ~29x faster ⚡ | ~6x less 💾 |
| .NET 9.0 | ~26x faster ⚡ | ~6x less 💾 |
WriteAsSpan
Comparison of converting objects to ReadOnlySpan<char>.
v2.0 Results (After Optimization)
| Runtime | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|
| .NET 10.0 | 39.79 ns | 0.714 ns | 0.633 ns | 128 B |
| .NET 8.0 | 48.28 ns | 0.384 ns | 0.321 ns | 128 B |
| .NET 9.0 | 55.05 ns | 1.113 ns | 1.282 ns | 128 B |
v1.x Results (Before Optimization)
| Runtime | Mean | Error | StdDev | Allocated |
|---|---|---|---|---|
| .NET 10.0 | 1.266 µs | 0.0251 µs | 0.0541 µs | 936 B |
| .NET 8.0 | 1.363 µs | 0.0152 µs | 0.0127 µs | 936 B |
| .NET 9.0 | 1.332 µs | 0.0176 µs | 0.0138 µs | 936 B |
Performance Improvement
| Runtime | Speed Improvement | Memory Improvement |
|---|---|---|
| .NET 10.0 | ~31x faster ⚡ | ~7x less 💾 |
| .NET 8.0 | ~28x faster ⚡ | ~7x less 💾 |
| .NET 9.0 | ~24x faster ⚡ | ~7x less 💾 |
Write operations show consistent performance improvements across all .NET versions, with speed gains of 24-31x and memory reductions of 6-7x.
Summary of Improvements
Overall Performance Gains
| Operation | Average Speed Improvement | Average Memory Reduction |
|---|---|---|
| Read Operations | ~40-60x faster ⚡ | ~20-26x less 💾 |
| Write Operations | ~25-30x faster ⚡ | ~6-7x less 💾 |
Real-World Impact
Throughput Comparison
Based on the benchmarks, here's what you can expect in real-world scenarios:
Processing 1 Million Records
| Operation | v1.x Time | v2.0 Time | Time Saved |
|---|---|---|---|
| Read | ~2,821 seconds (~47 min) | ~46 milliseconds | 99.998% faster |
| Write | ~1,243 seconds (~20 min) | ~40 milliseconds | 99.997% faster |
Memory Usage for 1 Million Records
| Operation | v1.x Memory | v2.0 Memory | Memory Saved |
|---|---|---|---|
| Read | ~664 MB | ~32 MB | ~632 MB (95%) |
| Write | ~808 MB | ~128 MB | ~680 MB (84%) |
These improvements make Spinner v2.0 suitable for high-throughput production environments where performance and memory efficiency are critical.
Best Practices for Maximum Performance
-
Reuse Spinner Instances
// Good: Single instance, reused
var spinner = new Spinner<MyClass>();
foreach (var item in items)
{
var result = spinner.WriteAsString(item);
} -
Use Span-based Methods When Possible
// Better performance with ReadFromSpan
ReadOnlySpan<char> data = GetDataAsSpan();
var obj = spinner.ReadFromSpan(data); -
Configure ObjectMapper Length
// Helps pre-allocate StringBuilder to exact size
[ObjectMapper(length: 100)]
public class MyClass { } -
Avoid Interceptors When Not Needed
- Use built-in type conversion for primitive types
- Only use interceptors for complex transformations
Benchmark Source Code
All benchmarks are available in the repository at:
- Path:
bench/Spinner.Benchmark/ - Read Benchmarks:
ReadBench.cs - Write Benchmarks:
WriterBench.cs
To run benchmarks yourself:
cd bench/Spinner.Benchmark
dotnet run -c Release
Continuous Performance Monitoring
Performance benchmarks are automatically executed in the CI/CD pipeline to ensure no performance regressions:
Conclusion
Spinner v2.0 represents a massive leap forward in performance:
✅ Up to 79x faster execution times
✅ Up to 26x less memory allocation
✅ Near-zero allocation scenarios in .NET 9.0+
✅ Production-ready for high-throughput workloads
✅ Consistent performance across all .NET versions
The architectural changes in v2.0, while introducing some breaking changes, deliver transformative performance improvements that make the migration effort worthwhile for any performance-conscious application.