benchmarks.md

December 16, 2021 ยท View on GitHub

Some Mostly-Pointless Benchmarks

There is an extremely basic set of benchmarks using BenchmarkDotNet that I have begun to use in order to track performance and perform optimizations as things progress. You can check the code out to run the benchmarks locally if you want, e.g.:

$ dotnet run --configuration Release --project .\test\H3.Benchmarks\H3.Benchmarks.csproj --filter *Uncompact* --join --framework net5.0

All numbers here are from my primary Windows development VM:

BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042
AMD Ryzen 9 3900X, 1 CPU, 12 logical and 6 physical cores
.NET Core SDK=5.0.201
  [Host]        : .NET Core 5.0.4 (CoreCLR 5.0.421.11614, CoreFX 5.0.421.11614), X64 RyuJIT
  .NET Core 5.0 : .NET Core 5.0.4 (CoreCLR 5.0.421.11614, CoreFX 5.0.421.11614), X64 RyuJIT

Job=.NET Core 5.0  Runtime=.NET Core 5.0

While there are some comparisons here against H3Lib, I still need to work on getting some benchmarks for the other H3 package which wraps the native library; if anyone is interested in assisting PRs are welcome!

Hierarchy Ops

GetParentForResolution

Using 89283080dcbffff (Uber's SF Test index @ resolution 9) to get parent at resolution 0 (a silly microbenchmark):

MethodMeanErrorStdDevGen 0Allocated
pocketken.H3.GetParentForResolution4.918 ns0.0838 ns0.0784 ns0.002924 B
H3Lib.ToParent21.087 ns0.1255 ns0.1174 ns--

GetChildrenForResolution

Using 89283080dcbffff (Uber's SF Test index @ resolution 9) to get all children at resolution 15.

MethodMeanErrorStdDevGen 0Gen 1Gen 2Allocated
pocketken.H3.GetChildrenForResolution9.639 ms0.1317 ms0.1099 ms796.8750781.2500484.37505 MB
H3Lib.ToChildren10.660 ms0.2096 ms0.3072 ms3453.12501671.8750984.375024 MB

GetDirectNeighbour

Using 89283080dcbffff (Uber's SF Test index @ resolution 9) and 8e0800000000007 (first pentagon @ resolution 14) to get neighbours at Direction.I and Direction.IJ:

MethodMeanErrorStdDevGen 0Allocated
'pocketken.H3.GetDirectNeighbour(hex, I)'16.68 ns0.140 ns0.124 ns0.002924 B
'H3Lib.NeighborRotations(hex, I)'16.70 ns0.187 ns0.166 ns--
'pocketken.H3.GetDirectNeighbour(hex, IJ)'24.47 ns0.223 ns0.198 ns0.002924 B
'H3Lib.NeighborRotations(hex, IJ)'27.64 ns0.226 ns0.189 ns--
'pocketken.H3.GetDirectNeighbour(pent, I)'27.50 ns0.307 ns0.287 ns0.002924 B
'H3Lib.NeighborRotations(pent, I)'33.15 ns0.415 ns0.388 ns--
'pocketken.H3.GetDirectNeighbour(pent, IJ)'27.34 ns0.367 ns0.343 ns0.002924 B
'H3Lib.NeighborRotations(pent, IJ)'32.86 ns0.250 ns0.234 ns--

Algorithms

Fill (Polyfill)

Filling world and Uber SF Test polygons at varied resolutions:

  • world, res 4: 288,122 cells
  • world, res 5: 2,016,842 cells
  • SF test, res 10: 8,794 cells
  • SF test, res 11: 61,569 cells
  • SF test, res 12: 430,832 cells
  • SF test, res 13: 3,015,836 cells
  • SF test, res 14: 21,111,191 cells
  • SF test, res 15: 147,778,335 cells
MethodMeanErrorStdDevGen 0Gen 1Gen 2Allocated
'pocketken.H3.Fill(worldPolygon, 4)'196.743 ms1.8058 ms1.6008 ms10000.00002000.00001000.000090 MB
'pocketken.H3.Fill(worldPolygon, 5)'1,413.311 ms11.3172 ms10.5861 ms71000.000013000.00004000.0000648 MB
'pocketken.H3.Fill(sfPolygon, 10)'7.319 ms0.0241 ms0.0202 ms367.1875226.5625117.18753 MB
'H3Lib.Polyfill(sfPolygon, 10)'494.078 ms1.2105 ms0.9450 ms3000.0000--27 MB
'pocketken.H3.Fill(sfPolygon, 11)'48.994 ms0.8197 ms0.7667 ms2727.27271090.9091636.363620 MB
'H3Lib.Polyfill(sfPolygon, 11)'3,319.726 ms3.1163 ms2.9150 ms21000.00003000.00001000.0000168 MB
'pocketken.H3.Fill(sfPolygon, 12)'361.273 ms6.7138 ms6.2801 ms16000.00003000.00002000.0000145 MB
'H3Lib.Polyfill(sfPolygon, 12)'20,111.706 ms269.9403 ms239.2950 ms137000.000019000.00002000.00001,119 MB
'pocketken.H3.Fill(sfPolygon, 13)'2,692.485 ms14.1803 ms13.2643 ms109000.000030000.00009000.00001,046 MB
'pocketken.H3.Fill(sfPolygon, 14)'18,216.525 ms22.5448 ms18.8259 ms719000.0000119000.000010000.00006,702 MB
'pocketken.H3.Fill(sfPolygon, 15)'128,363.156 ms501.3173 ms444.4047 ms4991000.0000791000.000046000.000047,576 MB

Lines

Line from 8e283080dc80007 to 8e48e1d7038d527 (DistanceTo of 554,625 cells).

MethodMeanErrorStdDevGen 0Gen 1Gen 2Allocated
pocketken.H3.LineTo725.4 ms9.40 ms8.79 ms34000.000010000.00001000.0000283 MB
H3Lib.LineTo4,683.3 ms14.94 ms13.25 ms1057000.00003000.00001000.00008,449 MB

Rings

hex is a hexagon index (8f48e1d7038d520).

MethodMeanErrorStdDevGen 0Gen 1Gen 2Allocated
'pocketken.H3.GetKRing(hex, k = 50)'419.5 us1.79 us1.59 us73.730536.6211-608 KB
'pocketken.H3.GetKRingFast(hex, k = 50)'422.6 us1.40 us1.09 us66.406333.2031-548 KB
'pocketken.H3.GetKRingSlow(hex, k = 50)'3,080.5 us7.55 us6.31 us269.5313179.687589.84382,113 KB
'H3Lib.KRingDistances(hex, k = 50)'463.7 us3.11 us2.76 us99.609499.609499.6094487 KB

pent is a pentagon index (8e0800000000007) which forces the use of the iterative (recursive in the case of H3Lib) method of generating the ring due to the fast method's inability to handle pentagons.

MethodMeanErrorStdDevGen 0Gen 1Gen 2Allocated
'pocketken.H3.GetKRing(pent, k = 50)'3,295.9 us24.51 us21.73 us269.5313179.687589.84382,113 KB
'pocketken.H3.GetKRingSlow(pent, k = 50)'3,097.6 us23.57 us22.05 us269.5313179.687589.84382,113 KB
'H3Lib.KRingDistances(pent, k = 50)'79,416,403.4 us594,028.76 us555,654.87 us7644000.00006050000.00005015000.000073,068,645 KB

Sets

  • Compact: Result of compacting all cells at resolution 5.
  • Uncompact: Result of uncompacting all base cells to resolution of 5.
MethodMeanErrorStdDevGen 0Gen 1Gen 2Allocated
pocketken.H3.Compact330.3 ms5.50 ms5.14 ms11000.00003000.0000-243.51 MB
H3Lib.Compact381.0 ms5.83 ms5.45 ms9000.00004000.00002000.0000305.24 MB
pocketken.H3.Uncompact136.6 ms0.36 ms0.32 ms6500.00003500.00001000.000078.18 MB
H3Lib.Uncompact203.3 ms4.05 ms4.16 ms43000.00007333.3333666.6667493.02 MB