BenchmarkDotNet v0.13.12, Windows 10 (10.0.19045.6456/22H2/2022Update)
Intel Core i7-1065G7 CPU 1.30GHz, 1 CPU, 8 logical and 4 physical cores
.NET SDK 8.0.403
[Host] : .NET 8.0.11 (8.0.1124.51707), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
DefaultJob : .NET 8.0.11 (8.0.1124.51707), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
| Method | Mean | Error | StdDev | Ratio | RatioSD | Completed Work Items | Lock Contentions | Allocated | Alloc Ratio |
|---|---|---|---|---|---|---|---|---|---|
| IntegerDomain_Span_Small | 7.023 ns | 0.4041 ns | 1.1851 ns | 1.00 | 0.00 | - | - | - | NA |
| IntegerDomain_Span_Medium | 8.150 ns | 0.2118 ns | 0.2521 ns | 1.47 | 0.10 | - | - | - | NA |
| IntegerDomain_Span_Large | 7.989 ns | 0.1333 ns | 0.1113 ns | 1.49 | 0.07 | - | - | - | NA |
| DateTimeDomain_Span_Small | 19.872 ns | 0.4412 ns | 0.5579 ns | 3.57 | 0.21 | - | - | - | NA |
| DateTimeDomain_Span_Medium | 21.864 ns | 0.2959 ns | 0.2471 ns | 4.07 | 0.18 | - | - | - | NA |
| DateTimeDomain_Span_Large | 20.113 ns | 0.4554 ns | 0.4472 ns | 3.68 | 0.25 | - | - | - | NA |
| IntegerDomain_Shift_Small | 16.887 ns | 0.2709 ns | 0.2262 ns | 3.14 | 0.15 | - | - | - | NA |
| IntegerDomain_Shift_Medium | 17.048 ns | 0.3180 ns | 0.3905 ns | 3.06 | 0.20 | - | - | - | NA |
| IntegerDomain_Shift_Large | 17.088 ns | 0.2378 ns | 0.2108 ns | 3.16 | 0.17 | - | - | - | NA |
| DateTimeDomain_Shift | 16.985 ns | 0.2463 ns | 0.2304 ns | 3.12 | 0.20 | - | - | - | NA |
| IntegerDomain_Expand_Small | 17.560 ns | 0.2967 ns | 0.2776 ns | 3.22 | 0.19 | - | - | - | NA |
| IntegerDomain_Expand_Medium | 17.956 ns | 0.2634 ns | 0.2199 ns | 3.34 | 0.17 | - | - | - | NA |
| IntegerDomain_Expand_Large | 17.961 ns | 0.2616 ns | 0.2319 ns | 3.32 | 0.18 | - | - | - | NA |
| DateTimeDomain_Expand | 17.393 ns | 0.3220 ns | 0.3579 ns | 3.16 | 0.20 | - | - | - | NA |
| IntegerDomain_ExpandByRatio_Small | 23.665 ns | 0.2922 ns | 0.2440 ns | 4.41 | 0.20 | - | - | - | NA |
| IntegerDomain_ExpandByRatio_Medium | 23.569 ns | 0.2486 ns | 0.2076 ns | 4.39 | 0.19 | - | - | - | NA |
| IntegerDomain_ExpandByRatio_Large | 23.963 ns | 0.3390 ns | 0.3005 ns | 4.43 | 0.24 | - | - | - | NA |
| DateTimeDomain_ExpandByRatio | 48.474 ns | 0.6099 ns | 0.5406 ns | 8.96 | 0.48 | - | - | - | NA |
| IntegerDomain_ExpandByRatio_Asymmetric | 24.806 ns | 0.3612 ns | 0.3016 ns | 4.62 | 0.20 | - | - | - | NA |
| IntegerDomain_ExpandByRatio_Contraction | 24.246 ns | 0.3533 ns | 0.3304 ns | 4.45 | 0.27 | - | - | - | NA |
Fixed-step extension method performance—the high-level operations that combine domain logic with range manipulation. Tests Span, Shift, Expand, and ExpandByRatio across integer and DateTime domains with various range sizes.
📏 Span: Constant-Time Range Measurement (O(1))
- Integer domain (all sizes): 7-8 ns
- DateTime domain (all sizes): 19-22 ns
- Result: Performance independent of range size (proves O(1))
- Use case: Count discrete points in a range
- Integer domain: 16.9-17.1 ns
- DateTime domain: 17.0 ns
- Result: Consistent across range sizes and domain types
- Use case: Move a time window forward/backward by N steps
📐 Expand: Extend Boundaries (O(1))
- Integer domain: 17.6-18.0 ns
- DateTime domain: 17.4 ns
- Result: Fixed cost regardless of expansion amount
- Use case: Add margin to a range (e.g., buffer time)
🔢 ExpandByRatio: Proportional Expansion (O(1))
- Integer domain: 23.6-24.0 ns (includes Span calculation)
- DateTime domain: 48.5 ns (heavier DateTime arithmetic)
- Asymmetric expansion: 24.8 ns (same cost)
- Contraction (negative ratio): 24.2 ns (same cost)
- Use case: Zoom in/out by percentage
Operation Integer (ns) DateTime (ns) Complexity
───────────────────────────────────────────────────────────────
Span 7-8 19-22 O(1)
Shift 16.9-17.1 17.0 O(1)
Expand 17.6-18.0 17.4 O(1)
ExpandByRatio 23.6-24.8 48.5 O(1)
Critical insight: Performance is identical across small/medium/large ranges:
- Small range (10 steps): 7.0 ns
- Medium range (1000 steps): 8.2 ns
- Large range (1,000,000 steps): 8.0 ns
This proves O(1) complexity—the hallmark of fixed-step domains.
Why all operations are O(1):
- ✅ Fixed-step domains:
Distanceis arithmetic, not iteration - ✅
Addis arithmetic, not loop-based - ✅
Floor/Ceilingare alignment operations, not searches - ✅ No need to enumerate range contents
Why ExpandByRatio is slower:
- Calls
Span()first (to calculate ratio) - Then calls
Expand()with computed offsets - Combined cost: Span + Expand (~7ns + 17ns = ~24ns)
Why DateTime is sometimes slower:
- DateTime arithmetic involves tick calculations
- More complex than integer addition/subtraction
- Still O(1), just more CPU instructions
✅ All operations suitable for hot paths:
- Span: 7-22 ns (measure range size)
- Shift: ~17 ns (move time windows)
- Expand: ~18 ns (add margins)
- ExpandByRatio: 24-48 ns (proportional scaling)
✅ Use with confidence in loops:
for (int i = 0; i < 10000; i++)
{
var span = range.Span(domain); // 7-22 ns per iteration
var shifted = range.Shift(domain, 5); // 17 ns per iteration
}
// Total: 170,000-240,000 ns = 0.17-0.24 milliseconds✅ Range size doesn't matter:
- Processing [1, 10] or [1, 1000000] costs the same
- Choose range boundaries based on business logic, not performance
Maintenance Window Scheduling (1000 shifts/day):
Operation: range.Shift(dayDomain, offset)
Cost: 17 ns × 1000 = 17 microseconds/day
Negligible overhead
Analytics Dashboard (100 span calculations/second):
Operation: range.Span(intDomain)
Cost: 7 ns × 100 = 700 ns/second
Sub-microsecond impact
Dynamic Range Expansion (zoom controls, 60 FPS):
Operation: range.ExpandByRatio(domain, 0.1, 0.1)
Cost: 24-48 ns × 60 = 1.44-2.88 microseconds/second
Real-time performance guaranteed
All extension operations: 0 bytes allocated
Return value: New Range<T> struct (stack-allocated)
Domain instances: Reusable, no per-operation cost
These benchmarks show fixed-step extension performance (O(1)):
- Span: 7-22 ns
- All operations: Range-size independent
For variable-step extensions (business days, O(N)):
- See VariableStepDomainBenchmarks
- Span may require iteration: 52-3,600 ns depending on range size
- Performance scales with range duration
These benchmarks prove that fixed-step extensions have guaranteed O(1) performance:
- ✅ Process any range size in constant time
- ✅ Predictable performance for real-time systems
- ✅ Zero allocations, suitable for hot paths
- ✅ No performance penalty for domain abstraction
Choose fixed-step domains when you need guaranteed constant-time operations.