full-api-approx-perf-estimation-net7.md

May 30, 2022 ยท View on GitHub

Preface

This data was gathered with ShortRunJob and is subject to high variance. The benchmark was run to estimate approximate cost for the most probable params combinations. It is planned to further research and, if possible, provide much more optimized composite keys code paths. As of now, composite keys use ValueTuple`2 and its implementations of Equals and GetHashCode. It appears those perform better than just readonly record structs. As mentioned above, it is necessary to investigate if hand-rolled specialized implementations per each key combination perform better than ValueTuples to produce better results.

Rationale

Despite the drawbacks described above, it is an advantage to keep compsite keys impl. under the hood. This way, the users don't have to worry about correct implementation when combining keys on their end (is string + bool.ToString() correct? what about other types?), and aggregating reference types such as strings produces allocations on reading cache values which is undesirable. Since it is common knowledge that types must implement proper GetHashCode() and Equals() to work as keys, no further constrains were placed on methods. Doing otherwise would work against the goal of having as little ceremony as possible when using the library. This will be reconsidered with the arrival of "roles" and "extensions" (hopefully in .NET 7?).

In addition, other alternatives would force users to explicitly specify type signatures and would significantly clutter user code (especially GetOrCompute).

Conclusion

Current approach is deemed appropriate to provide best balance between performance, usability and being foolproof while allowing for improvements in the future without breaking existing code.

Data

See code here: src/FastCache.Benchmarks/Defaults.cs

BenchmarkDotNet=v0.13.1, OS=Windows 10.0.22000
AMD Ryzen 7 5800X, 1 CPU, 16 logical and 8 physical cores
.NET SDK=7.0.100-preview.5.22274.1
  [Host]   : .NET 7.0.0 (7.0.22.27203), X64 RyuJIT
  ShortRun : .NET 7.0.0 (7.0.22.27203), X64 RyuJIT

Job=ShortRun  IterationCount=3  LaunchCount=1  
WarmupCount=3  
MethodMeanErrorStdDevRatioRatioSDGen 0Allocated
TryGetSingle11.961 ns13.2702 ns0.7274 ns1.000.00--
TryGetTwo46.261 ns26.8011 ns1.4691 ns3.880.28--
TryGetThree58.493 ns0.7789 ns0.0427 ns4.900.30--
TryGetFour73.868 ns51.6578 ns2.8315 ns6.190.47--
TryGetSeven109.558 ns1.1329 ns0.0621 ns9.180.56--
TryGetSingleInt4.213 ns0.4754 ns0.0261 ns0.350.02--
TryGetTwoInt27.104 ns39.1513 ns2.1460 ns2.280.30--
TryGetThreeInt37.473 ns0.1914 ns0.0105 ns3.140.19--
TryGetFourInt31.386 ns0.3837 ns0.0210 ns2.630.16--
TryGetSevenInt38.469 ns0.5389 ns0.0295 ns3.220.20--
TryGetTwoMixed40.162 ns0.3690 ns0.0202 ns3.370.20--
TryGetThreeMixed55.149 ns1.5484 ns0.0849 ns4.620.29--
TryGetFourMixed53.275 ns0.1605 ns0.0088 ns4.470.27--
TryGetSevenMixed80.585 ns22.8580 ns1.2529 ns6.750.43--
GetAndSaveSingle40.910 ns1.7615 ns0.0966 ns3.430.220.002440 B
GetAndSaveTwo104.097 ns11.0926 ns0.6080 ns8.720.530.002440 B
GetAndSaveThree126.292 ns0.5798 ns0.0318 ns10.580.650.002440 B
GetAndSaveFour155.695 ns112.9211 ns6.1896 ns13.040.720.002440 B
GetAndSaveSeven230.388 ns5.9681 ns0.3271 ns19.311.190.002440 B
GetAndSaveSingleInt26.982 ns61.3053 ns3.3603 ns2.270.400.002440 B
GetAndSaveTwoInt65.446 ns12.8807 ns0.7060 ns5.480.340.002440 B
GetAndSaveThreeInt77.114 ns68.9372 ns3.7787 ns6.460.500.002440 B
GetAndSaveFourInt73.675 ns54.6800 ns2.9972 ns6.180.590.002440 B
GetAndSaveSevenInt89.547 ns2.7708 ns0.1519 ns7.500.450.002440 B
GetAndSaveTwoMixed88.153 ns24.6049 ns1.3487 ns7.390.480.002440 B
GetAndSaveThreeMixed107.246 ns2.1456 ns0.1176 ns8.990.540.002440 B
GetAndSaveFourMixed129.123 ns7.8736 ns0.4316 ns10.820.660.002440 B
GetAndSaveSevenMixed184.798 ns153.6914 ns8.4243 ns15.491.250.002440 B
CacheSingle30.262 ns0.1975 ns0.0108 ns2.540.160.002440 B
CacheTwo67.272 ns3.5551 ns0.1949 ns5.640.360.002440 B
CacheThree71.230 ns115.6780 ns6.3407 ns5.950.300.002440 B
CacheFour93.204 ns90.9898 ns4.9875 ns7.810.550.002440 B
CacheSeven124.537 ns22.0922 ns1.2109 ns10.430.540.002440 B
CacheSingleInt25.161 ns1.0411 ns0.0571 ns2.110.130.002440 B
CacheTwoInt41.423 ns105.6855 ns5.7930 ns3.470.550.002440 B
CacheThreeInt53.303 ns1.1685 ns0.0640 ns4.470.280.002440 B
CacheFourInt56.734 ns1.3267 ns0.0727 ns4.750.290.002440 B
CacheSevenInt62.051 ns0.9014 ns0.0494 ns5.200.320.002440 B
CacheTwoMixed58.261 ns2.4349 ns0.1335 ns4.880.290.002440 B
CacheThreeMixed60.176 ns7.4671 ns0.4093 ns5.040.340.002440 B
CacheFourMixed71.743 ns86.2051 ns4.7252 ns6.000.060.002440 B
CacheSevenMixed106.937 ns1.8773 ns0.1029 ns8.960.540.002440 B
GetOrCompute18.764 ns0.5802 ns0.0318 ns1.570.10--
GetOrComputeValueTask73.659 ns33.0612 ns1.8122 ns6.170.42--
GetOrComputeTask62.821 ns31.0126 ns1.6999 ns5.260.180.004372 B