Skip to content

Latest commit

 

History

History
175 lines (141 loc) · 8.83 KB

File metadata and controls

175 lines (141 loc) · 8.83 KB

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

Summary

What This Measures

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.

Key Performance Insights

📏 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

↔️ Shift: Move Range by Offset (O(1))

  • 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

Performance by Operation

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)

Range Size Independence

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.

Design Trade-offs (Aligned with README Philosophy)

Why all operations are O(1):

  • ✅ Fixed-step domains: Distance is arithmetic, not iteration
  • Add is arithmetic, not loop-based
  • Floor/Ceiling are 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

Practical Recommendations

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

Real-World Impact

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

Memory Behavior

All extension operations:  0 bytes allocated
Return value:              New Range<T> struct (stack-allocated)
Domain instances:          Reusable, no per-operation cost

Comparison: Fixed vs Variable-Step

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)):

Why This Matters

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.