thesadrogue / TheSadRogue.Primitives

A collection of primitive data structures for working with a 2-dimensional grid.
MIT License
21 stars 6 forks source link

Point Hashing Improvements #111

Closed Chris3606 closed 1 year ago

Chris3606 commented 1 year ago

Overview

This builds on #100 by creating a more complete set of hashing algorithm tests, and based on those results, selecting a new hashing algorithm to use in Point.GetHashCode() (closes #57).

Changes

No breaking changes, since the only real change is the return values from Point.GetHashCode(), which best practice states users should not depend on. The implications from this change are mostly related to performance.

Performance Implications

The choice of hashing algorithm here focuses primarily on generating the best performance possible when Point is used in Dictionary or HashSet, since these are by far the primary use cases for GetHashCode in C#. Both of those data structures use a prime modulus strategy for determining what bin to place items in, which in short means that a few hash collisions are actually tolerable, and often a faster algorithm with slightly more collisions tends to perform better than a slower algorithm that more completely mitigates collisions; but it also means that collisions are generated in the hash set which are not evident based on just the hash algorithm itself.

In light of this, and in combination with the fact that there are a lot of other variables that affect hash set performance like cache locality, it is quite difficult to establish very consistent patterns which correlate a hash code to performance. However, generally speaking, a very simple hashing algorithm ended up performing quite well; one of the best was an algorithm which (in the tests) is called BareMinimum. It's basically just a summation of the x value, added to y value rotated left by 16 bits. The algorithm is fairly well-suited to the primitive library's requirements, for the following reasons:

  1. It is very fast (just an addition and a rotation which the compiler optimizes to the x86 instruction rol)
  2. It produces 0 collisions for many positive-only and negative-only coordinate ranges (at least up to range (0, 0) -> (8192, 8192)) and as a result is basically as fast as KnownSizeHasher over some positive coordinate spaces.
  3. Its max collision rate tends to be when both positive and negative coordinates are considered together; this creates approximately; 8192 collisions in the range (-4192, -4192) -> (4192, 4192), which is still quite low.

Therefore, the default GetHashCode() implementation for point now implements BareMinimum.

Analysis

As stated above, the large number of variables and internal implementation details which affect HashSet and Dictionary performance made it very difficult to establish concrete patterns based on benchmarks. In some cases, exactly why the results are the way they are is not something I fully understand; and it appears that it would take some diving into the internals of those collections to get any further.

That much said, one algorithm that performed quite well is BareMinimum. It is quite fast (though not the fastest), and generates very few collisions over the coordinate spaces typically used (but not the fewest). Despite not being the "best" in each category, it very consistently performs as good or better than OriginalGoRogue, which represents the hasher used currently by the primitives library.

The performance test results are listed in the section that follows this one; and they detail the times it takes to perform dictionary add and get operations, and the same for hash set, using a bunch of hashing algorithms, as well as the default hasher. There are a few characteristics of these results that are notable:

  1. CurrentPrimitives uses the default hash code implementation; more precisely, it passes no equality comparer at all to the dictionary/hash set; and this appears to produce different results than passing the same algorithm as a custom equality comparer. This is evident, because the results contain both. This PR switches Point.GetHashCode(), and therefore CurrentPrimitives, to use BareMinimum; but the CurrentPrimitives test case quite often performs better than the BareMinimum one does. I'm not sure exactly why this is; it could be everything from a specific optimization made by the dictionary implementation, to a semantic of the implementation that allows devirtualization in one case but not the other. It can be investigated further in the future, but for now, it means that we cannot compare CurrentPrimitives directly to the other algorithm results.
  2. The results are not incredibly consistent in terms of ratio as far as how much better or worse one algorithm does compared to others. It is expected that certain ranges (mainly, the gaussian distribution) will generate more collisions for some hash functions, and as such those hash functions may not perform as well in those test cases, and we do see that to some extent. However, there are other inconsistencies that don't line up with that assessment. This would indicate that there are likely factors other than the hashing algorithm's number of collisions and raw speed affecting the results.
  3. The test results are significantly different for the positive only ranges if you remove the Shuffle call which shuffles the input list. Namely, many algorithms perform much better. This suggests that cache locality of the buckets may be playing a significant role in the result. This may explain some instances where more collisions end up generating better performance as well.
  4. The Add tests in particular are probably at least somewhat unreliable in terms of measuring the hashing algorithms performance; this is because the tests must create a new Dictionary as part of the timed process; and even if they did not, resizing and creation of additional buckets would still definitely have to take place. Therefore, it is possible that memory allocation is a significant factor in the test results. This is not entirely independent of the hashing algorithm, since the hashes generated do play a part in this; however there are certainly more factors at play here than anywhere else and therefore all differences the hashing algorithm directly creates may not be evident in these test results.
  5. The KnownSize and KnownRange test cases are probably not to be trusted in the Gaussian distribution. Since these ranges don't meet the constraint of having coordinates that fall within the expected ranges, we're effectively violating the contract these hashers assume to be valid. Therefore it is expected that the results for KnownSize and KnownRange vary so widely in the Gaussian data sets.

The theme above is, there appear to be factors other than the direct observable characteristics of the hashing algorithm that are playing a significant role in the test results, and what these factors are is not something I entirely understand. I do have a few theories; one possibility is that the modulus being performed by the internal implementation of dictionary is generating collisions that we can't see directly by analyzing the number of collisions produced by the hash code. Another, is that the hash code is causing differences in a) the cache locality of buckets being accessed and b) the allocation of memory itself that occurs. This in particular would explain some of the inconsistencies at the 1024 size compared to others, as it would be more likely to encounter cache misses if you jump around to buckets that are not close to each other in memory.

Another common theme, however, is that BareMinimum is better than OriginalGoRogue (which is the Point.GetHashCode() implementation prior to this PR). In all but one of the test cases, it is measurably better (sometimes by only a little, sometimes by as much as about twice as fast); and in the one test case where it is not faster, the difference between the two is well within the margin of error. Therefore, regardless of what factors are affecting the outcomes, it appears that BareMinimum should nearly always produce as good or better results than the old implementation does. That combined with the fact that the old implementation on paper produces many more collisions, I think makes a fairly compelling case to switch the default implementation.

It is worthy of note that there are cases for BareMinimum that will generate much higher collision rates. The rate at which collisions will be generated significantly increases at coordinates >= 65536 X or Y, for instance. In fact, hashes start to repeat almost entirely around this range; (0, 0) -> (1023, 1023) and (65536, 65536) -> (66559, 66559) generate almost entirely the same set of 1024 * 1024 hash values. This seems like an exceedingly uncommon case to find in games, though; and should it ever occur, it seems likely custom hashing will need to be used anyway (or even a structure entirely outside of Dictionary and HashSet. I think most, if not all, use cases remain well inside the (65535, 65535) marker. In the future, it may be useful to include other hashing algorithms as equality comparers in the actual library; but I'd like to try to gain a better understanding of what is affecting these results first.

Benchmarks

Adding points to a Dictionary: Method DataSet Size Algorithm Mean Error StdDev
AddAllPoints PositiveOnly 10 CurrentPrimitives 2.227 μs 0.0086 μs 0.0080 μs
AddAllPoints PositiveOnly 10 KnownSize 2.328 μs 0.0182 μs 0.0170 μs
AddAllPoints PositiveOnly 10 KnownRange 2.338 μs 0.0132 μs 0.0123 μs
AddAllPoints PositiveOnly 10 BareMinimum8And24 2.286 μs 0.0142 μs 0.0133 μs
AddAllPoints PositiveOnly 10 BareMinimum 2.348 μs 0.0144 μs 0.0135 μs
AddAllPoints PositiveOnly 10 BareMinimumSubtract 2.352 μs 0.0105 μs 0.0098 μs
AddAllPoints PositiveOnly 10 CantorPure 2.460 μs 0.0085 μs 0.0071 μs
AddAllPoints PositiveOnly 10 HashCodeCombine 2.865 μs 0.0120 μs 0.0106 μs
AddAllPoints PositiveOnly 10 MultiplySum 2.487 μs 0.0121 μs 0.0107 μs
AddAllPoints PositiveOnly 10 OriginalGoRogue 2.545 μs 0.0088 μs 0.0074 μs
AddAllPoints PositiveOnly 10 RosenbergStrongBased 2.617 μs 0.0084 μs 0.0074 μs
AddAllPoints PositiveOnly 10 Rosen(...)tiply [33] 2.520 μs 0.0114 μs 0.0107 μs
AddAllPoints PositiveOnly 10 RosenbergStrongPure 2.237 μs 0.0125 μs 0.0111 μs
AddAllPoints PositiveOnly 10 SimpleShift 2.341 μs 0.0126 μs 0.0112 μs
AddAllPoints PositiveOnly 50 CurrentPrimitives 54.724 μs 0.2533 μs 0.2369 μs
AddAllPoints PositiveOnly 50 KnownSize 58.123 μs 0.3441 μs 0.3218 μs
AddAllPoints PositiveOnly 50 KnownRange 57.847 μs 0.1233 μs 0.1093 μs
AddAllPoints PositiveOnly 50 BareMinimum8And24 60.420 μs 0.2451 μs 0.2173 μs
AddAllPoints PositiveOnly 50 BareMinimum 57.846 μs 0.2162 μs 0.1805 μs
AddAllPoints PositiveOnly 50 BareMinimumSubtract 58.250 μs 0.2200 μs 0.1837 μs
AddAllPoints PositiveOnly 50 CantorPure 60.964 μs 0.1710 μs 0.1516 μs
AddAllPoints PositiveOnly 50 HashCodeCombine 79.230 μs 0.1673 μs 0.1565 μs
AddAllPoints PositiveOnly 50 MultiplySum 62.836 μs 0.2507 μs 0.2222 μs
AddAllPoints PositiveOnly 50 OriginalGoRogue 71.422 μs 0.2874 μs 0.2244 μs
AddAllPoints PositiveOnly 50 RosenbergStrongBased 78.446 μs 0.4704 μs 0.4400 μs
AddAllPoints PositiveOnly 50 Rosen(...)tiply [33] 74.810 μs 0.2152 μs 0.1907 μs
AddAllPoints PositiveOnly 50 RosenbergStrongPure 60.851 μs 0.2216 μs 0.1965 μs
AddAllPoints PositiveOnly 50 SimpleShift 57.824 μs 0.1767 μs 0.1476 μs
AddAllPoints PositiveOnly 100 CurrentPrimitives 290.946 μs 0.8690 μs 0.7704 μs
AddAllPoints PositiveOnly 100 KnownSize 282.414 μs 1.3932 μs 1.3032 μs
AddAllPoints PositiveOnly 100 KnownRange 280.889 μs 0.5940 μs 0.4960 μs
AddAllPoints PositiveOnly 100 BareMinimum8And24 303.699 μs 1.2590 μs 1.1777 μs
AddAllPoints PositiveOnly 100 BareMinimum 299.917 μs 1.0494 μs 0.8763 μs
AddAllPoints PositiveOnly 100 BareMinimumSubtract 301.874 μs 1.2695 μs 1.1875 μs
AddAllPoints PositiveOnly 100 CantorPure 296.019 μs 0.6618 μs 0.5167 μs
AddAllPoints PositiveOnly 100 HashCodeCombine 371.007 μs 1.2580 μs 1.0505 μs
AddAllPoints PositiveOnly 100 MultiplySum 301.802 μs 0.8443 μs 0.7050 μs
AddAllPoints PositiveOnly 100 OriginalGoRogue 341.766 μs 1.5126 μs 1.4149 μs
AddAllPoints PositiveOnly 100 RosenbergStrongBased 374.770 μs 0.9630 μs 0.8537 μs
AddAllPoints PositiveOnly 100 Rosen(...)tiply [33] 365.595 μs 0.7531 μs 0.6289 μs
AddAllPoints PositiveOnly 100 RosenbergStrongPure 304.761 μs 0.5897 μs 0.4604 μs
AddAllPoints PositiveOnly 100 SimpleShift 302.207 μs 0.9245 μs 0.8195 μs
AddAllPoints PositiveOnly 175 CurrentPrimitives 944.815 μs 12.2495 μs 11.4582 μs
AddAllPoints PositiveOnly 175 KnownSize 878.473 μs 17.3931 μs 20.0299 μs
AddAllPoints PositiveOnly 175 KnownRange 874.333 μs 16.8814 μs 20.7319 μs
AddAllPoints PositiveOnly 175 BareMinimum8And24 937.022 μs 18.2399 μs 17.9141 μs
AddAllPoints PositiveOnly 175 BareMinimum 971.030 μs 18.3239 μs 17.1402 μs
AddAllPoints PositiveOnly 175 BareMinimumSubtract 964.652 μs 19.0550 μs 26.0827 μs
AddAllPoints PositiveOnly 175 CantorPure 957.942 μs 18.6677 μs 18.3341 μs
AddAllPoints PositiveOnly 175 HashCodeCombine 1,238.086 μs 23.7454 μs 22.2114 μs
AddAllPoints PositiveOnly 175 MultiplySum 947.353 μs 18.6314 μs 20.7088 μs
AddAllPoints PositiveOnly 175 OriginalGoRogue 1,174.994 μs 23.4415 μs 24.0727 μs
AddAllPoints PositiveOnly 175 RosenbergStrongBased 1,245.923 μs 15.5939 μs 14.5865 μs
AddAllPoints PositiveOnly 175 Rosen(...)tiply [33] 1,215.248 μs 23.2641 μs 21.7613 μs
AddAllPoints PositiveOnly 175 RosenbergStrongPure 943.097 μs 18.7784 μs 17.5653 μs
AddAllPoints PositiveOnly 175 SimpleShift 963.441 μs 17.9990 μs 16.8362 μs
AddAllPoints PositiveOnly 256 CurrentPrimitives 2,535.966 μs 39.9639 μs 37.3823 μs
AddAllPoints PositiveOnly 256 KnownSize 2,306.048 μs 41.8952 μs 39.1888 μs
AddAllPoints PositiveOnly 256 KnownRange 2,327.411 μs 38.1286 μs 35.6655 μs
AddAllPoints PositiveOnly 256 BareMinimum8And24 2,289.617 μs 27.2447 μs 25.4847 μs
AddAllPoints PositiveOnly 256 BareMinimum 2,579.903 μs 37.4658 μs 35.0455 μs
AddAllPoints PositiveOnly 256 BareMinimumSubtract 2,577.921 μs 33.9381 μs 31.7457 μs
AddAllPoints PositiveOnly 256 CantorPure 2,502.386 μs 36.1080 μs 33.7754 μs
AddAllPoints PositiveOnly 256 HashCodeCombine 3,193.705 μs 39.8046 μs 37.2333 μs
AddAllPoints PositiveOnly 256 MultiplySum 2,719.877 μs 37.1182 μs 34.7204 μs
AddAllPoints PositiveOnly 256 OriginalGoRogue 3,024.087 μs 34.5248 μs 32.2945 μs
AddAllPoints PositiveOnly 256 RosenbergStrongBased 3,190.034 μs 28.6765 μs 26.8240 μs
AddAllPoints PositiveOnly 256 Rosen(...)tiply [33] 3,162.129 μs 19.2213 μs 17.0392 μs
AddAllPoints PositiveOnly 256 RosenbergStrongPure 2,466.872 μs 40.9735 μs 38.3266 μs
AddAllPoints PositiveOnly 256 SimpleShift 2,605.104 μs 34.2401 μs 32.0282 μs
AddAllPoints PositiveOnly 1024 CurrentPrimitives 85,319.815 μs 602.4561 μs 503.0781 μs
AddAllPoints PositiveOnly 1024 KnownSize 60,892.212 μs 789.0855 μs 699.5038 μs
AddAllPoints PositiveOnly 1024 KnownRange 60,591.405 μs 1,086.2332 μs 962.9174 μs
AddAllPoints PositiveOnly 1024 BareMinimum8And24 121,800.283 μs 2,105.4428 μs 1,866.4202 μs
AddAllPoints PositiveOnly 1024 BareMinimum 87,537.084 μs 1,750.0231 μs 1,636.9727 μs
AddAllPoints PositiveOnly 1024 BareMinimumSubtract 86,127.943 μs 1,158.2699 μs 1,026.7761 μs
AddAllPoints PositiveOnly 1024 CantorPure 64,350.672 μs 643.2586 μs 601.7045 μs
AddAllPoints PositiveOnly 1024 HashCodeCombine 90,712.142 μs 1,207.6743 μs 1,070.5718 μs
AddAllPoints PositiveOnly 1024 MultiplySum 77,241.571 μs 588.5557 μs 550.5354 μs
AddAllPoints PositiveOnly 1024 OriginalGoRogue 88,859.442 μs 772.2742 μs 644.8839 μs
AddAllPoints PositiveOnly 1024 RosenbergStrongBased 91,624.579 μs 845.6927 μs 749.6845 μs
AddAllPoints PositiveOnly 1024 Rosen(...)tiply [33] 88,160.551 μs 663.9225 μs 554.4054 μs
AddAllPoints PositiveOnly 1024 RosenbergStrongPure 61,855.768 μs 1,212.0517 μs 1,190.3969 μs
AddAllPoints PositiveOnly 1024 SimpleShift 85,872.995 μs 1,124.2316 μs 996.6020 μs
AddAllPoints Gaussian 10 CurrentPrimitives 2.197 μs 0.0204 μs 0.0180 μs
AddAllPoints Gaussian 10 KnownSize 2.410 μs 0.0074 μs 0.0066 μs
AddAllPoints Gaussian 10 KnownRange 2.398 μs 0.0123 μs 0.0115 μs
AddAllPoints Gaussian 10 BareMinimum8And24 2.328 μs 0.0163 μs 0.0144 μs
AddAllPoints Gaussian 10 BareMinimum 2.313 μs 0.0070 μs 0.0058 μs
AddAllPoints Gaussian 10 BareMinimumSubtract 2.302 μs 0.0218 μs 0.0204 μs
AddAllPoints Gaussian 10 CantorPure 2.477 μs 0.0210 μs 0.0197 μs
AddAllPoints Gaussian 10 HashCodeCombine 2.924 μs 0.0234 μs 0.0219 μs
AddAllPoints Gaussian 10 MultiplySum 2.390 μs 0.0091 μs 0.0080 μs
AddAllPoints Gaussian 10 OriginalGoRogue 2.448 μs 0.0099 μs 0.0088 μs
AddAllPoints Gaussian 10 RosenbergStrongBased 2.630 μs 0.0095 μs 0.0089 μs
AddAllPoints Gaussian 10 Rosen(...)tiply [33] 2.626 μs 0.0160 μs 0.0142 μs
AddAllPoints Gaussian 10 RosenbergStrongPure 2.329 μs 0.0136 μs 0.0127 μs
AddAllPoints Gaussian 10 SimpleShift 2.292 μs 0.0153 μs 0.0143 μs
AddAllPoints Gaussian 50 CurrentPrimitives 63.842 μs 0.2677 μs 0.2504 μs
AddAllPoints Gaussian 50 KnownSize 67.593 μs 0.4264 μs 0.3780 μs
AddAllPoints Gaussian 50 KnownRange 67.689 μs 0.2552 μs 0.2263 μs
AddAllPoints Gaussian 50 BareMinimum8And24 67.209 μs 0.1973 μs 0.1749 μs
AddAllPoints Gaussian 50 BareMinimum 67.279 μs 0.2429 μs 0.2153 μs
AddAllPoints Gaussian 50 BareMinimumSubtract 66.525 μs 0.3443 μs 0.3052 μs
AddAllPoints Gaussian 50 CantorPure 70.396 μs 0.3845 μs 0.3596 μs
AddAllPoints Gaussian 50 HashCodeCombine 79.295 μs 0.2910 μs 0.2722 μs
AddAllPoints Gaussian 50 MultiplySum 68.252 μs 0.2326 μs 0.2062 μs
AddAllPoints Gaussian 50 OriginalGoRogue 71.090 μs 0.2088 μs 0.1953 μs
AddAllPoints Gaussian 50 RosenbergStrongBased 79.984 μs 0.3498 μs 0.3272 μs
AddAllPoints Gaussian 50 Rosen(...)tiply [33] 78.032 μs 0.2626 μs 0.2456 μs
AddAllPoints Gaussian 50 RosenbergStrongPure 72.630 μs 0.2588 μs 0.2294 μs
AddAllPoints Gaussian 50 SimpleShift 67.692 μs 0.1473 μs 0.1150 μs
AddAllPoints Gaussian 100 CurrentPrimitives 310.748 μs 0.7517 μs 0.6663 μs
AddAllPoints Gaussian 100 KnownSize 330.940 μs 0.9831 μs 0.8715 μs
AddAllPoints Gaussian 100 KnownRange 333.159 μs 1.2139 μs 1.1355 μs
AddAllPoints Gaussian 100 BareMinimum8And24 323.678 μs 1.0612 μs 0.9926 μs
AddAllPoints Gaussian 100 BareMinimum 323.635 μs 1.3503 μs 1.1970 μs
AddAllPoints Gaussian 100 BareMinimumSubtract 320.695 μs 0.7511 μs 0.6272 μs
AddAllPoints Gaussian 100 CantorPure 346.692 μs 2.3091 μs 2.1599 μs
AddAllPoints Gaussian 100 HashCodeCombine 370.329 μs 1.6895 μs 1.4977 μs
AddAllPoints Gaussian 100 MultiplySum 326.953 μs 1.1130 μs 1.0411 μs
AddAllPoints Gaussian 100 OriginalGoRogue 342.116 μs 2.8443 μs 2.6605 μs
AddAllPoints Gaussian 100 RosenbergStrongBased 388.490 μs 1.2064 μs 1.0694 μs
AddAllPoints Gaussian 100 Rosen(...)tiply [33] 385.561 μs 0.8764 μs 0.6842 μs
AddAllPoints Gaussian 100 RosenbergStrongPure 362.984 μs 1.6656 μs 1.4765 μs
AddAllPoints Gaussian 100 SimpleShift 324.207 μs 1.0670 μs 0.9981 μs
AddAllPoints Gaussian 175 CurrentPrimitives 1,033.964 μs 20.4171 μs 20.9668 μs
AddAllPoints Gaussian 175 KnownSize 1,117.357 μs 20.1184 μs 18.8188 μs
AddAllPoints Gaussian 175 KnownRange 1,112.115 μs 21.8547 μs 23.3843 μs
AddAllPoints Gaussian 175 BareMinimum8And24 1,095.256 μs 21.5012 μs 23.8985 μs
AddAllPoints Gaussian 175 BareMinimum 1,063.027 μs 21.0897 μs 25.1058 μs
AddAllPoints Gaussian 175 BareMinimumSubtract 1,072.341 μs 20.6628 μs 21.2192 μs
AddAllPoints Gaussian 175 CantorPure 1,231.323 μs 21.6209 μs 20.2242 μs
AddAllPoints Gaussian 175 HashCodeCombine 1,224.974 μs 23.8218 μs 25.4891 μs
AddAllPoints Gaussian 175 MultiplySum 1,084.908 μs 21.1184 μs 20.7411 μs
AddAllPoints Gaussian 175 OriginalGoRogue 1,134.087 μs 21.3537 μs 23.7345 μs
AddAllPoints Gaussian 175 RosenbergStrongBased 1,414.067 μs 21.7802 μs 20.3732 μs
AddAllPoints Gaussian 175 Rosen(...)tiply [33] 1,389.827 μs 27.2126 μs 29.1172 μs
AddAllPoints Gaussian 175 RosenbergStrongPure 1,266.497 μs 18.7617 μs 17.5497 μs
AddAllPoints Gaussian 175 SimpleShift 1,087.451 μs 20.7308 μs 24.6786 μs
AddAllPoints Gaussian 256 CurrentPrimitives 2,748.185 μs 42.7570 μs 39.9949 μs
AddAllPoints Gaussian 256 KnownSize 2,909.990 μs 47.1675 μs 44.1205 μs
AddAllPoints Gaussian 256 KnownRange 2,935.546 μs 45.7875 μs 42.8296 μs
AddAllPoints Gaussian 256 BareMinimum8And24 2,908.376 μs 39.7885 μs 37.2182 μs
AddAllPoints Gaussian 256 BareMinimum 2,834.965 μs 48.2924 μs 45.1727 μs
AddAllPoints Gaussian 256 BareMinimumSubtract 2,826.224 μs 40.4971 μs 37.8810 μs
AddAllPoints Gaussian 256 CantorPure 3,456.268 μs 38.6776 μs 36.1790 μs
AddAllPoints Gaussian 256 HashCodeCombine 3,163.631 μs 27.7356 μs 24.5869 μs
AddAllPoints Gaussian 256 MultiplySum 2,846.899 μs 37.5987 μs 35.1698 μs
AddAllPoints Gaussian 256 OriginalGoRogue 2,987.968 μs 43.4976 μs 40.6877 μs
AddAllPoints Gaussian 256 RosenbergStrongBased 3,927.867 μs 40.2663 μs 35.6950 μs
AddAllPoints Gaussian 256 Rosen(...)tiply [33] 3,882.956 μs 43.3503 μs 40.5499 μs
AddAllPoints Gaussian 256 RosenbergStrongPure 3,567.681 μs 34.4146 μs 32.1915 μs
AddAllPoints Gaussian 256 SimpleShift 2,838.372 μs 44.4108 μs 41.5419 μs
AddAllPoints Gaussian 1024 CurrentPrimitives 80,550.670 μs 1,230.2917 μs 1,150.8156 μs
AddAllPoints Gaussian 1024 KnownSize 82,041.286 μs 1,132.5102 μs 945.6973 μs
AddAllPoints Gaussian 1024 KnownRange 81,590.637 μs 1,068.5368 μs 947.2300 μs
AddAllPoints Gaussian 1024 BareMinimum8And24 117,080.619 μs 2,143.2215 μs 1,899.9101 μs
AddAllPoints Gaussian 1024 BareMinimum 76,955.888 μs 476.7446 μs 372.2109 μs
AddAllPoints Gaussian 1024 BareMinimumSubtract 76,978.676 μs 814.4791 μs 680.1269 μs
AddAllPoints Gaussian 1024 CantorPure 235,699.259 μs 2,085.1293 μs 1,741.1774 μs
AddAllPoints Gaussian 1024 HashCodeCombine 88,581.723 μs 1,086.9890 μs 963.5875 μs
AddAllPoints Gaussian 1024 MultiplySum 78,467.874 μs 1,519.5396 μs 1,421.3783 μs
AddAllPoints Gaussian 1024 OriginalGoRogue 91,027.923 μs 553.1507 μs 461.9059 μs
AddAllPoints Gaussian 1024 RosenbergStrongBased 261,822.410 μs 5,009.3585 μs 5,768.7847 μs
AddAllPoints Gaussian 1024 Rosen(...)tiply [33] 267,115.122 μs 5,182.2139 μs 7,264.7401 μs
AddAllPoints Gaussian 1024 RosenbergStrongPure 224,612.600 μs 1,584.9428 μs 1,405.0105 μs
AddAllPoints Gaussian 1024 SimpleShift 77,203.082 μs 773.3973 μs 723.4364 μs
Adding points to a HashSet: Method DataSet Size Algorithm Mean Error StdDev
AddAllPoints PositiveOnly 10 CurrentPrimitives 2.174 μs 0.0211 μs 0.0198 μs
AddAllPoints PositiveOnly 10 KnownSize 2.267 μs 0.0130 μs 0.0121 μs
AddAllPoints PositiveOnly 10 KnownRange 2.340 μs 0.0154 μs 0.0144 μs
AddAllPoints PositiveOnly 10 BareMinimum8And24 2.191 μs 0.0137 μs 0.0128 μs
AddAllPoints PositiveOnly 10 BareMinimum 2.245 μs 0.0084 μs 0.0066 μs
AddAllPoints PositiveOnly 10 BareMinimumSubtract 2.298 μs 0.0100 μs 0.0083 μs
AddAllPoints PositiveOnly 10 CantorPure 2.337 μs 0.0129 μs 0.0120 μs
AddAllPoints PositiveOnly 10 HashCodeCombine 2.824 μs 0.0193 μs 0.0181 μs
AddAllPoints PositiveOnly 10 MultiplySum 2.380 μs 0.0178 μs 0.0157 μs
AddAllPoints PositiveOnly 10 OriginalGoRogue 2.431 μs 0.0096 μs 0.0080 μs
AddAllPoints PositiveOnly 10 RosenbergStrongBased 2.582 μs 0.0071 μs 0.0059 μs
AddAllPoints PositiveOnly 10 Rosen(...)tiply [33] 2.484 μs 0.0140 μs 0.0131 μs
AddAllPoints PositiveOnly 10 RosenbergStrongPure 2.205 μs 0.0184 μs 0.0172 μs
AddAllPoints PositiveOnly 10 SimpleShift 2.250 μs 0.0184 μs 0.0172 μs
AddAllPoints PositiveOnly 50 CurrentPrimitives 54.061 μs 0.2557 μs 0.2266 μs
AddAllPoints PositiveOnly 50 KnownSize 56.468 μs 0.2220 μs 0.1968 μs
AddAllPoints PositiveOnly 50 KnownRange 56.331 μs 0.2004 μs 0.1564 μs
AddAllPoints PositiveOnly 50 BareMinimum8And24 58.915 μs 0.2233 μs 0.2089 μs
AddAllPoints PositiveOnly 50 BareMinimum 55.848 μs 0.2338 μs 0.2187 μs
AddAllPoints PositiveOnly 50 BareMinimumSubtract 56.393 μs 0.2073 μs 0.1731 μs
AddAllPoints PositiveOnly 50 CantorPure 59.110 μs 0.4872 μs 0.4557 μs
AddAllPoints PositiveOnly 50 HashCodeCombine 76.960 μs 0.3070 μs 0.2722 μs
AddAllPoints PositiveOnly 50 MultiplySum 60.248 μs 0.3886 μs 0.3445 μs
AddAllPoints PositiveOnly 50 OriginalGoRogue 68.792 μs 0.3795 μs 0.3550 μs
AddAllPoints PositiveOnly 50 RosenbergStrongBased 77.491 μs 0.3745 μs 0.3503 μs
AddAllPoints PositiveOnly 50 Rosen(...)tiply [33] 74.376 μs 0.2110 μs 0.1871 μs
AddAllPoints PositiveOnly 50 RosenbergStrongPure 60.754 μs 0.1622 μs 0.1355 μs
AddAllPoints PositiveOnly 50 SimpleShift 55.925 μs 0.1712 μs 0.1601 μs
AddAllPoints PositiveOnly 100 CurrentPrimitives 273.376 μs 1.2308 μs 1.0278 μs
AddAllPoints PositiveOnly 100 KnownSize 260.023 μs 1.6463 μs 1.5399 μs
AddAllPoints PositiveOnly 100 KnownRange 260.495 μs 1.3001 μs 1.0150 μs
AddAllPoints PositiveOnly 100 BareMinimum8And24 283.571 μs 1.0586 μs 0.9384 μs
AddAllPoints PositiveOnly 100 BareMinimum 280.668 μs 1.0106 μs 0.9453 μs
AddAllPoints PositiveOnly 100 BareMinimumSubtract 282.659 μs 2.1277 μs 1.7767 μs
AddAllPoints PositiveOnly 100 CantorPure 271.255 μs 1.2024 μs 1.1247 μs
AddAllPoints PositiveOnly 100 HashCodeCombine 353.986 μs 1.1042 μs 0.9788 μs
AddAllPoints PositiveOnly 100 MultiplySum 279.182 μs 1.1151 μs 0.9311 μs
AddAllPoints PositiveOnly 100 OriginalGoRogue 323.610 μs 1.1922 μs 1.0568 μs
AddAllPoints PositiveOnly 100 RosenbergStrongBased 358.231 μs 1.1437 μs 1.0139 μs
AddAllPoints PositiveOnly 100 Rosen(...)tiply [33] 350.534 μs 1.1260 μs 0.8791 μs
AddAllPoints PositiveOnly 100 RosenbergStrongPure 281.204 μs 1.3946 μs 1.2363 μs
AddAllPoints PositiveOnly 100 SimpleShift 281.478 μs 0.6245 μs 0.5215 μs
AddAllPoints PositiveOnly 175 CurrentPrimitives 973.330 μs 13.7822 μs 12.8919 μs
AddAllPoints PositiveOnly 175 KnownSize 898.138 μs 10.3385 μs 9.6706 μs
AddAllPoints PositiveOnly 175 KnownRange 888.951 μs 16.4021 μs 15.3426 μs
AddAllPoints PositiveOnly 175 BareMinimum8And24 961.680 μs 17.9336 μs 16.7751 μs
AddAllPoints PositiveOnly 175 BareMinimum 1,000.900 μs 19.8960 μs 19.5405 μs
AddAllPoints PositiveOnly 175 BareMinimumSubtract 992.256 μs 18.4835 μs 18.1532 μs
AddAllPoints PositiveOnly 175 CantorPure 964.058 μs 13.2452 μs 12.3896 μs
AddAllPoints PositiveOnly 175 HashCodeCombine 1,265.805 μs 18.3697 μs 17.1830 μs
AddAllPoints PositiveOnly 175 MultiplySum 986.042 μs 16.6689 μs 15.5921 μs
AddAllPoints PositiveOnly 175 OriginalGoRogue 1,179.132 μs 13.4352 μs 12.5673 μs
AddAllPoints PositiveOnly 175 RosenbergStrongBased 1,273.577 μs 25.4415 μs 23.7980 μs
AddAllPoints PositiveOnly 175 Rosen(...)tiply [33] 1,240.450 μs 20.1189 μs 18.8192 μs
AddAllPoints PositiveOnly 175 RosenbergStrongPure 954.467 μs 18.6362 μs 17.4324 μs
AddAllPoints PositiveOnly 175 SimpleShift 990.945 μs 18.6211 μs 17.4181 μs
AddAllPoints PositiveOnly 256 CurrentPrimitives 2,445.770 μs 48.3884 μs 84.7484 μs
AddAllPoints PositiveOnly 256 KnownSize 2,208.446 μs 41.5708 μs 68.3019 μs
AddAllPoints PositiveOnly 256 KnownRange 2,222.405 μs 43.7508 μs 71.8839 μs
AddAllPoints PositiveOnly 256 BareMinimum8And24 2,200.610 μs 43.1696 μs 80.0177 μs
AddAllPoints PositiveOnly 256 BareMinimum 2,497.177 μs 49.8576 μs 73.0807 μs
AddAllPoints PositiveOnly 256 BareMinimumSubtract 2,515.202 μs 49.7222 μs 72.8821 μs
AddAllPoints PositiveOnly 256 CantorPure 2,409.758 μs 48.1170 μs 82.9995 μs
AddAllPoints PositiveOnly 256 HashCodeCombine 3,131.946 μs 62.6175 μs 69.5992 μs
AddAllPoints PositiveOnly 256 MultiplySum 2,661.571 μs 52.2973 μs 69.8155 μs
AddAllPoints PositiveOnly 256 OriginalGoRogue 2,985.241 μs 59.2249 μs 74.9005 μs
AddAllPoints PositiveOnly 256 RosenbergStrongBased 3,034.721 μs 59.2947 μs 79.1567 μs
AddAllPoints PositiveOnly 256 Rosen(...)tiply [33] 2,972.976 μs 50.5272 μs 49.6245 μs
AddAllPoints PositiveOnly 256 RosenbergStrongPure 2,283.321 μs 45.3713 μs 78.2632 μs
AddAllPoints PositiveOnly 256 SimpleShift 2,438.546 μs 48.5720 μs 74.1746 μs
AddAllPoints PositiveOnly 1024 CurrentPrimitives 74,190.766 μs 992.4249 μs 828.7198 μs
AddAllPoints PositiveOnly 1024 KnownSize 56,606.165 μs 633.8010 μs 561.8480 μs
AddAllPoints PositiveOnly 1024 KnownRange 57,195.434 μs 548.4286 μs 486.1677 μs
AddAllPoints PositiveOnly 1024 BareMinimum8And24 108,483.070 μs 1,075.3708 μs 953.2882 μs
AddAllPoints PositiveOnly 1024 BareMinimum 75,013.772 μs 1,257.9383 μs 1,115.1296 μs
AddAllPoints PositiveOnly 1024 BareMinimumSubtract 75,259.958 μs 850.1033 μs 753.5945 μs
AddAllPoints PositiveOnly 1024 CantorPure 63,021.641 μs 1,237.5024 μs 1,926.6421 μs
AddAllPoints PositiveOnly 1024 HashCodeCombine 87,148.906 μs 1,656.7318 μs 2,095.2353 μs
AddAllPoints PositiveOnly 1024 MultiplySum 70,955.720 μs 1,409.4155 μs 2,152.3264 μs
AddAllPoints PositiveOnly 1024 OriginalGoRogue 84,722.412 μs 1,603.7688 μs 1,782.5848 μs
AddAllPoints PositiveOnly 1024 RosenbergStrongBased 87,576.628 μs 1,699.5972 μs 2,209.9564 μs
AddAllPoints PositiveOnly 1024 Rosen(...)tiply [33] 85,101.937 μs 1,632.1959 μs 1,879.6393 μs
AddAllPoints PositiveOnly 1024 RosenbergStrongPure 58,710.978 μs 1,131.1268 μs 1,302.6073 μs
AddAllPoints PositiveOnly 1024 SimpleShift 74,900.290 μs 807.1495 μs 630.1692 μs
AddAllPoints Gaussian 10 CurrentPrimitives 2.093 μs 0.0075 μs 0.0059 μs
AddAllPoints Gaussian 10 KnownSize 2.311 μs 0.0182 μs 0.0171 μs
AddAllPoints Gaussian 10 KnownRange 2.352 μs 0.0212 μs 0.0177 μs
AddAllPoints Gaussian 10 BareMinimum8And24 2.303 μs 0.0135 μs 0.0126 μs
AddAllPoints Gaussian 10 BareMinimum 2.300 μs 0.0143 μs 0.0133 μs
AddAllPoints Gaussian 10 BareMinimumSubtract 2.276 μs 0.0278 μs 0.0247 μs
AddAllPoints Gaussian 10 CantorPure 2.322 μs 0.0147 μs 0.0138 μs
AddAllPoints Gaussian 10 HashCodeCombine 2.781 μs 0.0123 μs 0.0115 μs
AddAllPoints Gaussian 10 MultiplySum 2.294 μs 0.0167 μs 0.0156 μs
AddAllPoints Gaussian 10 OriginalGoRogue 2.385 μs 0.0143 μs 0.0127 μs
AddAllPoints Gaussian 10 RosenbergStrongBased 2.539 μs 0.0446 μs 0.0417 μs
AddAllPoints Gaussian 10 Rosen(...)tiply [33] 2.544 μs 0.0137 μs 0.0121 μs
AddAllPoints Gaussian 10 RosenbergStrongPure 2.284 μs 0.0135 μs 0.0127 μs
AddAllPoints Gaussian 10 SimpleShift 2.275 μs 0.0137 μs 0.0121 μs
AddAllPoints Gaussian 50 CurrentPrimitives 62.769 μs 0.2065 μs 0.1724 μs
AddAllPoints Gaussian 50 KnownSize 66.318 μs 0.3186 μs 0.2980 μs
AddAllPoints Gaussian 50 KnownRange 65.757 μs 0.0785 μs 0.0696 μs
AddAllPoints Gaussian 50 BareMinimum8And24 66.170 μs 0.2368 μs 0.2100 μs
AddAllPoints Gaussian 50 BareMinimum 64.528 μs 0.2793 μs 0.2333 μs
AddAllPoints Gaussian 50 BareMinimumSubtract 64.770 μs 0.4452 μs 0.3946 μs
AddAllPoints Gaussian 50 CantorPure 67.463 μs 0.3777 μs 0.3348 μs
AddAllPoints Gaussian 50 HashCodeCombine 78.077 μs 0.2147 μs 0.2008 μs
AddAllPoints Gaussian 50 MultiplySum 66.328 μs 0.1981 μs 0.1756 μs
AddAllPoints Gaussian 50 OriginalGoRogue 68.577 μs 0.2636 μs 0.2337 μs
AddAllPoints Gaussian 50 RosenbergStrongBased 79.218 μs 0.2816 μs 0.2635 μs
AddAllPoints Gaussian 50 Rosen(...)tiply [33] 77.615 μs 1.0474 μs 0.9797 μs
AddAllPoints Gaussian 50 RosenbergStrongPure 70.789 μs 0.1807 μs 0.1691 μs
AddAllPoints Gaussian 50 SimpleShift 65.484 μs 0.2394 μs 0.2239 μs
AddAllPoints Gaussian 100 CurrentPrimitives 296.902 μs 1.7110 μs 1.5167 μs
AddAllPoints Gaussian 100 KnownSize 310.881 μs 0.4040 μs 0.3154 μs
AddAllPoints Gaussian 100 KnownRange 314.588 μs 1.6645 μs 1.4755 μs
AddAllPoints Gaussian 100 BareMinimum8And24 305.539 μs 1.1640 μs 1.0888 μs
AddAllPoints Gaussian 100 BareMinimum 305.411 μs 1.0174 μs 0.8496 μs
AddAllPoints Gaussian 100 BareMinimumSubtract 304.783 μs 1.2900 μs 1.2067 μs
AddAllPoints Gaussian 100 CantorPure 325.897 μs 2.5829 μs 2.2897 μs
AddAllPoints Gaussian 100 HashCodeCombine 353.445 μs 0.7767 μs 0.6486 μs
AddAllPoints Gaussian 100 MultiplySum 309.506 μs 1.6134 μs 1.5092 μs
AddAllPoints Gaussian 100 OriginalGoRogue 321.976 μs 1.4814 μs 1.2370 μs
AddAllPoints Gaussian 100 RosenbergStrongBased 374.746 μs 1.7516 μs 1.5528 μs
AddAllPoints Gaussian 100 Rosen(...)tiply [33] 370.700 μs 1.3809 μs 1.2241 μs
AddAllPoints Gaussian 100 RosenbergStrongPure 344.170 μs 1.3093 μs 1.1606 μs
AddAllPoints Gaussian 100 SimpleShift 307.060 μs 1.5926 μs 1.4118 μs
AddAllPoints Gaussian 175 CurrentPrimitives 1,070.347 μs 20.4709 μs 24.3691 μs
AddAllPoints Gaussian 175 KnownSize 1,131.116 μs 21.9859 μs 20.5656 μs
AddAllPoints Gaussian 175 KnownRange 1,125.496 μs 21.7115 μs 26.6637 μs
AddAllPoints Gaussian 175 BareMinimum8And24 1,111.868 μs 21.3977 μs 28.5654 μs
AddAllPoints Gaussian 175 BareMinimum 1,092.570 μs 21.6422 μs 28.8918 μs
AddAllPoints Gaussian 175 BareMinimumSubtract 1,093.097 μs 21.5637 μs 27.2712 μs
AddAllPoints Gaussian 175 CantorPure 1,247.191 μs 20.6586 μs 19.3241 μs
AddAllPoints Gaussian 175 HashCodeCombine 1,251.683 μs 24.1949 μs 22.6319 μs
AddAllPoints Gaussian 175 MultiplySum 1,111.282 μs 21.6230 μs 25.7407 μs
AddAllPoints Gaussian 175 OriginalGoRogue 1,160.587 μs 23.0188 μs 28.2692 μs
AddAllPoints Gaussian 175 RosenbergStrongBased 1,431.169 μs 21.4928 μs 20.1044 μs
AddAllPoints Gaussian 175 Rosen(...)tiply [33] 1,399.246 μs 27.7650 μs 28.5126 μs
AddAllPoints Gaussian 175 RosenbergStrongPure 1,277.185 μs 22.1076 μs 20.6795 μs
AddAllPoints Gaussian 175 SimpleShift 1,107.146 μs 21.4157 μs 29.3141 μs
AddAllPoints Gaussian 256 CurrentPrimitives 2,602.201 μs 51.5828 μs 73.9785 μs
AddAllPoints Gaussian 256 KnownSize 2,784.910 μs 53.5227 μs 63.7150 μs
AddAllPoints Gaussian 256 KnownRange 2,778.855 μs 43.6619 μs 40.8413 μs
AddAllPoints Gaussian 256 BareMinimum8And24 2,714.694 μs 52.2737 μs 58.1021 μs
AddAllPoints Gaussian 256 BareMinimum 2,680.355 μs 53.1860 μs 71.0017 μs
AddAllPoints Gaussian 256 BareMinimumSubtract 2,692.202 μs 48.6702 μs 45.5262 μs
AddAllPoints Gaussian 256 CantorPure 3,306.349 μs 64.1629 μs 71.3169 μs
AddAllPoints Gaussian 256 HashCodeCombine 3,037.292 μs 48.8171 μs 43.2751 μs
AddAllPoints Gaussian 256 MultiplySum 2,703.932 μs 53.3926 μs 69.4254 μs
AddAllPoints Gaussian 256 OriginalGoRogue 2,850.512 μs 55.8178 μs 85.2396 μs
AddAllPoints Gaussian 256 RosenbergStrongBased 3,775.719 μs 64.6487 μs 60.4724 μs
AddAllPoints Gaussian 256 Rosen(...)tiply [33] 3,749.454 μs 54.4625 μs 45.4786 μs
AddAllPoints Gaussian 256 RosenbergStrongPure 3,399.807 μs 66.7847 μs 71.4589 μs
AddAllPoints Gaussian 256 SimpleShift 2,665.275 μs 52.4287 μs 64.3872 μs
AddAllPoints Gaussian 1024 CurrentPrimitives 73,458.247 μs 1,452.9639 μs 1,359.1033 μs
AddAllPoints Gaussian 1024 KnownSize 76,504.592 μs 1,449.3937 μs 1,669.1240 μs
AddAllPoints Gaussian 1024 KnownRange 76,279.557 μs 1,510.4045 μs 1,412.8333 μs
AddAllPoints Gaussian 1024 BareMinimum8And24 108,178.263 μs 1,508.0296 μs 1,336.8290 μs
AddAllPoints Gaussian 1024 BareMinimum 71,970.738 μs 1,253.9652 μs 1,111.6075 μs
AddAllPoints Gaussian 1024 BareMinimumSubtract 70,837.276 μs 1,013.9239 μs 898.8171 μs
AddAllPoints Gaussian 1024 CantorPure 202,449.544 μs 1,986.0745 μs 1,658.4621 μs
AddAllPoints Gaussian 1024 HashCodeCombine 89,106.792 μs 1,378.5074 μs 1,222.0109 μs
AddAllPoints Gaussian 1024 MultiplySum 68,009.003 μs 1,070.2500 μs 893.7072 μs
AddAllPoints Gaussian 1024 OriginalGoRogue 89,680.080 μs 1,449.5403 μs 1,284.9797 μs
AddAllPoints Gaussian 1024 RosenbergStrongBased 243,004.770 μs 4,779.2987 μs 5,312.1779 μs
AddAllPoints Gaussian 1024 Rosen(...)tiply [33] 229,852.517 μs 3,995.6923 μs 3,737.5730 μs
AddAllPoints Gaussian 1024 RosenbergStrongPure 194,624.988 μs 1,245.5747 μs 1,104.1695 μs
AddAllPoints Gaussian 1024 SimpleShift 72,086.385 μs 1,337.7200 μs 1,185.8540 μs
Getting values at Points from a Dictionary: Method DataSet Size Algorithm Mean Error StdDev Median
GetAllPoints PositiveOnly 10 CurrentPrimitives 1.641 μs 0.0106 μs 0.0099 μs 1.636 μs
GetAllPoints PositiveOnly 10 KnownSize 1.698 μs 0.0007 μs 0.0006 μs 1.698 μs
GetAllPoints PositiveOnly 10 KnownRange 1.725 μs 0.0009 μs 0.0007 μs 1.725 μs
GetAllPoints PositiveOnly 10 BareMinimum8And24 1.650 μs 0.0004 μs 0.0003 μs 1.650 μs
GetAllPoints PositiveOnly 10 BareMinimum 2.092 μs 0.0069 μs 0.0061 μs 2.091 μs
GetAllPoints PositiveOnly 10 BareMinimumSubtract 2.078 μs 0.0055 μs 0.0049 μs 2.077 μs
GetAllPoints PositiveOnly 10 CantorPure 1.774 μs 0.0012 μs 0.0009 μs 1.774 μs
GetAllPoints PositiveOnly 10 HashCodeCombine 2.346 μs 0.0070 μs 0.0066 μs 2.344 μs
GetAllPoints PositiveOnly 10 MultiplySum 2.033 μs 0.0265 μs 0.0248 μs 2.031 μs
GetAllPoints PositiveOnly 10 OriginalGoRogue 2.014 μs 0.0030 μs 0.0026 μs 2.014 μs
GetAllPoints PositiveOnly 10 RosenbergStrongBased 2.075 μs 0.0033 μs 0.0028 μs 2.075 μs
GetAllPoints PositiveOnly 10 Rosen(...)tiply [33] 2.021 μs 0.0049 μs 0.0046 μs 2.022 μs
GetAllPoints PositiveOnly 10 RosenbergStrongPure 1.812 μs 0.0021 μs 0.0018 μs 1.811 μs
GetAllPoints PositiveOnly 10 SimpleShift 2.031 μs 0.0212 μs 0.0198 μs 2.038 μs
GetAllPoints PositiveOnly 50 CurrentPrimitives 36.158 μs 0.0359 μs 0.0336 μs 36.154 μs
GetAllPoints PositiveOnly 50 KnownSize 42.443 μs 0.4917 μs 0.4599 μs 42.742 μs
GetAllPoints PositiveOnly 50 KnownRange 42.494 μs 0.2301 μs 0.2153 μs 42.473 μs
GetAllPoints PositiveOnly 50 BareMinimum8And24 42.345 μs 0.2733 μs 0.2557 μs 42.352 μs
GetAllPoints PositiveOnly 50 BareMinimum 40.655 μs 0.1944 μs 0.1623 μs 40.646 μs
GetAllPoints PositiveOnly 50 BareMinimumSubtract 41.746 μs 0.2444 μs 0.2286 μs 41.692 μs
GetAllPoints PositiveOnly 50 CantorPure 44.507 μs 0.2575 μs 0.2409 μs 44.437 μs
GetAllPoints PositiveOnly 50 HashCodeCombine 63.002 μs 0.3016 μs 0.2674 μs 63.062 μs
GetAllPoints PositiveOnly 50 MultiplySum 47.264 μs 0.3890 μs 0.3449 μs 47.225 μs
GetAllPoints PositiveOnly 50 OriginalGoRogue 55.325 μs 0.2945 μs 0.2755 μs 55.310 μs
GetAllPoints PositiveOnly 50 RosenbergStrongBased 62.484 μs 0.4771 μs 0.4463 μs 62.334 μs
GetAllPoints PositiveOnly 50 Rosen(...)tiply [33] 58.889 μs 0.2763 μs 0.2449 μs 58.793 μs
GetAllPoints PositiveOnly 50 RosenbergStrongPure 48.639 μs 0.2300 μs 0.2039 μs 48.664 μs
GetAllPoints PositiveOnly 50 SimpleShift 40.668 μs 0.1655 μs 0.1382 μs 40.641 μs
GetAllPoints PositiveOnly 100 CurrentPrimitives 189.352 μs 0.7995 μs 0.7478 μs 189.113 μs
GetAllPoints PositiveOnly 100 KnownSize 176.003 μs 1.1360 μs 1.0626 μs 175.680 μs
GetAllPoints PositiveOnly 100 KnownRange 178.401 μs 0.9411 μs 0.8343 μs 178.469 μs
GetAllPoints PositiveOnly 100 BareMinimum8And24 171.994 μs 0.6165 μs 0.5767 μs 171.814 μs
GetAllPoints PositiveOnly 100 BareMinimum 218.400 μs 1.1822 μs 1.1058 μs 218.254 μs
GetAllPoints PositiveOnly 100 BareMinimumSubtract 221.704 μs 0.9067 μs 0.8038 μs 221.727 μs
GetAllPoints PositiveOnly 100 CantorPure 184.694 μs 0.7619 μs 0.7127 μs 184.725 μs
GetAllPoints PositiveOnly 100 HashCodeCombine 266.773 μs 1.5976 μs 1.4944 μs 266.779 μs
GetAllPoints PositiveOnly 100 MultiplySum 194.377 μs 0.9000 μs 0.7978 μs 194.178 μs
GetAllPoints PositiveOnly 100 OriginalGoRogue 236.739 μs 1.9774 μs 1.8497 μs 235.917 μs
GetAllPoints PositiveOnly 100 RosenbergStrongBased 266.294 μs 1.1880 μs 0.9921 μs 266.311 μs
GetAllPoints PositiveOnly 100 Rosen(...)tiply [33] 259.645 μs 1.6438 μs 1.5376 μs 259.140 μs
GetAllPoints PositiveOnly 100 RosenbergStrongPure 203.412 μs 1.3178 μs 1.2327 μs 203.032 μs
GetAllPoints PositiveOnly 100 SimpleShift 217.587 μs 1.8074 μs 1.6023 μs 217.568 μs
GetAllPoints PositiveOnly 175 CurrentPrimitives 593.312 μs 5.0945 μs 4.7654 μs 591.817 μs
GetAllPoints PositiveOnly 175 KnownSize 575.219 μs 1.7757 μs 1.5741 μs 574.729 μs
GetAllPoints PositiveOnly 175 KnownRange 587.850 μs 2.9245 μs 2.5925 μs 586.452 μs
GetAllPoints PositiveOnly 175 BareMinimum8And24 709.151 μs 3.5549 μs 3.3253 μs 707.406 μs
GetAllPoints PositiveOnly 175 BareMinimum 688.698 μs 2.1142 μs 1.9776 μs 688.803 μs
GetAllPoints PositiveOnly 175 BareMinimumSubtract 688.838 μs 2.3413 μs 2.0755 μs 688.047 μs
GetAllPoints PositiveOnly 175 CantorPure 682.520 μs 1.9905 μs 1.7645 μs 682.433 μs
GetAllPoints PositiveOnly 175 HashCodeCombine 1,018.074 μs 4.5964 μs 4.2995 μs 1,018.881 μs
GetAllPoints PositiveOnly 175 MultiplySum 718.257 μs 3.0836 μs 2.8844 μs 718.399 μs
GetAllPoints PositiveOnly 175 OriginalGoRogue 931.878 μs 4.5210 μs 4.2290 μs 929.708 μs
GetAllPoints PositiveOnly 175 RosenbergStrongBased 1,022.979 μs 5.0095 μs 4.6859 μs 1,022.665 μs
GetAllPoints PositiveOnly 175 Rosen(...)tiply [33] 978.554 μs 6.0558 μs 5.3683 μs 975.511 μs
GetAllPoints PositiveOnly 175 RosenbergStrongPure 661.185 μs 1.6228 μs 1.5180 μs 660.849 μs
GetAllPoints PositiveOnly 175 SimpleShift 679.747 μs 2.7713 μs 2.4567 μs 678.892 μs
GetAllPoints PositiveOnly 256 CurrentPrimitives 1,661.890 μs 12.8896 μs 12.0570 μs 1,659.782 μs
GetAllPoints PositiveOnly 256 KnownSize 1,400.281 μs 9.1037 μs 8.0702 μs 1,396.781 μs
GetAllPoints PositiveOnly 256 KnownRange 1,423.611 μs 10.7464 μs 10.0522 μs 1,424.906 μs
GetAllPoints PositiveOnly 256 BareMinimum8And24 1,370.757 μs 7.6465 μs 7.1525 μs 1,370.909 μs
GetAllPoints PositiveOnly 256 BareMinimum 1,849.955 μs 11.0912 μs 10.3747 μs 1,846.185 μs
GetAllPoints PositiveOnly 256 BareMinimumSubtract 1,863.451 μs 8.1167 μs 7.1953 μs 1,863.844 μs
GetAllPoints PositiveOnly 256 CantorPure 1,659.926 μs 8.0374 μs 7.1249 μs 1,659.390 μs
GetAllPoints PositiveOnly 256 HashCodeCombine 2,420.411 μs 12.4761 μs 11.6702 μs 2,418.566 μs
GetAllPoints PositiveOnly 256 MultiplySum 2,046.710 μs 11.5165 μs 10.7726 μs 2,046.732 μs
GetAllPoints PositiveOnly 256 OriginalGoRogue 2,250.874 μs 16.4041 μs 15.3444 μs 2,242.556 μs
GetAllPoints PositiveOnly 256 RosenbergStrongBased 2,386.089 μs 20.4394 μs 18.1190 μs 2,381.532 μs
GetAllPoints PositiveOnly 256 Rosen(...)tiply [33] 2,408.643 μs 10.2652 μs 9.6021 μs 2,403.536 μs
GetAllPoints PositiveOnly 256 RosenbergStrongPure 1,571.385 μs 3.9556 μs 3.5065 μs 1,570.614 μs
GetAllPoints PositiveOnly 256 SimpleShift 1,835.288 μs 8.8131 μs 8.2438 μs 1,833.282 μs
GetAllPoints PositiveOnly 1024 CurrentPrimitives 40,506.484 μs 638.4354 μs 627.0289 μs 40,431.346 μs
GetAllPoints PositiveOnly 1024 KnownSize 28,598.665 μs 241.5417 μs 201.6983 μs 28,575.281 μs
GetAllPoints PositiveOnly 1024 KnownRange 28,840.871 μs 217.9842 μs 170.1877 μs 28,780.617 μs
GetAllPoints PositiveOnly 1024 BareMinimum8And24 105,337.655 μs 1,013.9526 μs 846.6963 μs 105,217.820 μs
GetAllPoints PositiveOnly 1024 BareMinimum 43,385.352 μs 601.2266 μs 562.3877 μs 43,521.225 μs
GetAllPoints PositiveOnly 1024 BareMinimumSubtract 43,078.904 μs 573.9273 μs 508.7716 μs 43,030.225 μs
GetAllPoints PositiveOnly 1024 CantorPure 37,385.190 μs 474.6518 μs 420.7665 μs 37,375.925 μs
GetAllPoints PositiveOnly 1024 HashCodeCombine 78,041.636 μs 582.7011 μs 516.5494 μs 77,981.907 μs
GetAllPoints PositiveOnly 1024 MultiplySum 56,504.215 μs 396.1191 μs 330.7774 μs 56,430.011 μs
GetAllPoints PositiveOnly 1024 OriginalGoRogue 76,757.789 μs 545.8088 μs 455.7751 μs 76,764.814 μs
GetAllPoints PositiveOnly 1024 RosenbergStrongBased 78,278.168 μs 486.8044 μs 406.5037 μs 78,339.671 μs
GetAllPoints PositiveOnly 1024 Rosen(...)tiply [33] 74,021.300 μs 536.4804 μs 475.5759 μs 74,020.336 μs
GetAllPoints PositiveOnly 1024 RosenbergStrongPure 31,369.020 μs 227.1836 μs 189.7086 μs 31,405.388 μs
GetAllPoints PositiveOnly 1024 SimpleShift 43,301.195 μs 821.4528 μs 1,621.4677 μs 42,599.667 μs
GetAllPoints Gaussian 10 CurrentPrimitives 1.517 μs 0.0020 μs 0.0018 μs 1.516 μs
GetAllPoints Gaussian 10 KnownSize 1.907 μs 0.0023 μs 0.0020 μs 1.907 μs
GetAllPoints Gaussian 10 KnownRange 1.906 μs 0.0058 μs 0.0054 μs 1.904 μs
GetAllPoints Gaussian 10 BareMinimum8And24 1.876 μs 0.0125 μs 0.0117 μs 1.880 μs
GetAllPoints Gaussian 10 BareMinimum 1.846 μs 0.0044 μs 0.0039 μs 1.844 μs
GetAllPoints Gaussian 10 BareMinimumSubtract 1.857 μs 0.0033 μs 0.0031 μs 1.856 μs
GetAllPoints Gaussian 10 CantorPure 1.992 μs 0.0047 μs 0.0042 μs 1.991 μs
GetAllPoints Gaussian 10 HashCodeCombine 2.419 μs 0.0025 μs 0.0022 μs 2.419 μs
GetAllPoints Gaussian 10 MultiplySum 1.888 μs 0.0012 μs 0.0010 μs 1.888 μs
GetAllPoints Gaussian 10 OriginalGoRogue 1.995 μs 0.0039 μs 0.0032 μs 1.994 μs
GetAllPoints Gaussian 10 RosenbergStrongBased 2.089 μs 0.0102 μs 0.0095 μs 2.088 μs
GetAllPoints Gaussian 10 Rosen(...)tiply [33] 2.027 μs 0.0117 μs 0.0110 μs 2.024 μs
GetAllPoints Gaussian 10 RosenbergStrongPure 1.817 μs 0.0077 μs 0.0072 μs 1.818 μs
GetAllPoints Gaussian 10 SimpleShift 1.814 μs 0.0060 μs 0.0056 μs 1.815 μs
GetAllPoints Gaussian 50 CurrentPrimitives 44.072 μs 0.0800 μs 0.0748 μs 44.035 μs
GetAllPoints Gaussian 50 KnownSize 53.003 μs 0.1897 μs 0.1584 μs 53.047 μs
GetAllPoints Gaussian 50 KnownRange 53.273 μs 0.0621 μs 0.0518 μs 53.257 μs
GetAllPoints Gaussian 50 BareMinimum8And24 52.278 μs 0.0940 μs 0.0879 μs 52.246 μs
GetAllPoints Gaussian 50 BareMinimum 51.622 μs 0.1720 μs 0.1609 μs 51.563 μs
GetAllPoints Gaussian 50 BareMinimumSubtract 53.409 μs 0.1177 μs 0.1101 μs 53.364 μs
GetAllPoints Gaussian 50 CantorPure 54.804 μs 0.1194 μs 0.1059 μs 54.798 μs
GetAllPoints Gaussian 50 HashCodeCombine 64.704 μs 0.1449 μs 0.1355 μs 64.735 μs
GetAllPoints Gaussian 50 MultiplySum 53.828 μs 0.1570 μs 0.1469 μs 53.826 μs
GetAllPoints Gaussian 50 OriginalGoRogue 56.127 μs 0.1904 μs 0.1781 μs 56.103 μs
GetAllPoints Gaussian 50 RosenbergStrongBased 63.433 μs 0.1511 μs 0.1339 μs 63.401 μs
GetAllPoints Gaussian 50 Rosen(...)tiply [33] 61.277 μs 0.1034 μs 0.0864 μs 61.260 μs
GetAllPoints Gaussian 50 RosenbergStrongPure 56.168 μs 0.1605 μs 0.1502 μs 56.134 μs
GetAllPoints Gaussian 50 SimpleShift 52.169 μs 0.1253 μs 0.1111 μs 52.199 μs
GetAllPoints Gaussian 100 CurrentPrimitives 191.786 μs 0.2816 μs 0.2352 μs 191.782 μs
GetAllPoints Gaussian 100 KnownSize 228.973 μs 0.5001 μs 0.4434 μs 228.930 μs
GetAllPoints Gaussian 100 KnownRange 232.603 μs 0.6809 μs 0.6369 μs 232.264 μs
GetAllPoints Gaussian 100 BareMinimum8And24 224.436 μs 0.5022 μs 0.4452 μs 224.453 μs
GetAllPoints Gaussian 100 BareMinimum 219.330 μs 0.4772 μs 0.4230 μs 219.244 μs
GetAllPoints Gaussian 100 BareMinimumSubtract 227.196 μs 0.8155 μs 0.7629 μs 227.144 μs
GetAllPoints Gaussian 100 CantorPure 243.127 μs 0.6012 μs 0.5623 μs 242.897 μs
GetAllPoints Gaussian 100 HashCodeCombine 271.953 μs 0.6832 μs 0.6056 μs 271.648 μs
GetAllPoints Gaussian 100 MultiplySum 228.245 μs 0.6920 μs 0.6473 μs 228.177 μs
GetAllPoints Gaussian 100 OriginalGoRogue 238.510 μs 0.7352 μs 0.6877 μs 238.351 μs
GetAllPoints Gaussian 100 RosenbergStrongBased 289.020 μs 0.3786 μs 0.2956 μs 289.021 μs
GetAllPoints Gaussian 100 Rosen(...)tiply [33] 283.313 μs 1.7464 μs 1.6336 μs 283.521 μs
GetAllPoints Gaussian 100 RosenbergStrongPure 260.774 μs 1.7559 μs 1.6425 μs 260.349 μs
GetAllPoints Gaussian 100 SimpleShift 223.936 μs 0.2838 μs 0.2516 μs 223.901 μs
GetAllPoints Gaussian 175 CurrentPrimitives 767.143 μs 4.3157 μs 4.0369 μs 767.300 μs
GetAllPoints Gaussian 175 KnownSize 889.474 μs 5.4844 μs 5.1302 μs 888.621 μs
GetAllPoints Gaussian 175 KnownRange 894.825 μs 3.4210 μs 2.8567 μs 895.958 μs
GetAllPoints Gaussian 175 BareMinimum8And24 873.893 μs 2.2995 μs 2.0385 μs 874.007 μs
GetAllPoints Gaussian 175 BareMinimum 866.027 μs 5.8355 μs 5.4585 μs 868.338 μs
GetAllPoints Gaussian 175 BareMinimumSubtract 868.696 μs 6.4858 μs 6.0668 μs 864.786 μs
GetAllPoints Gaussian 175 CantorPure 1,037.782 μs 7.9076 μs 7.3968 μs 1,036.833 μs
GetAllPoints Gaussian 175 HashCodeCombine 1,034.329 μs 5.7055 μs 5.3370 μs 1,035.947 μs
GetAllPoints Gaussian 175 MultiplySum 877.577 μs 4.3229 μs 4.0437 μs 878.406 μs
GetAllPoints Gaussian 175 OriginalGoRogue 920.135 μs 3.4626 μs 3.2389 μs 921.130 μs
GetAllPoints Gaussian 175 RosenbergStrongBased 1,211.336 μs 5.7408 μs 5.0891 μs 1,211.636 μs
GetAllPoints Gaussian 175 Rosen(...)tiply [33] 1,171.994 μs 5.4015 μs 5.0526 μs 1,169.317 μs
GetAllPoints Gaussian 175 RosenbergStrongPure 1,076.225 μs 5.4801 μs 5.1261 μs 1,076.359 μs
GetAllPoints Gaussian 175 SimpleShift 869.283 μs 3.8294 μs 3.5821 μs 868.679 μs
GetAllPoints Gaussian 256 CurrentPrimitives 1,854.279 μs 5.7059 μs 4.7647 μs 1,852.708 μs
GetAllPoints Gaussian 256 KnownSize 2,104.129 μs 14.2186 μs 13.3000 μs 2,103.343 μs
GetAllPoints Gaussian 256 KnownRange 2,157.118 μs 14.5897 μs 13.6472 μs 2,158.806 μs
GetAllPoints Gaussian 256 BareMinimum8And24 2,132.399 μs 20.0461 μs 18.7511 μs 2,131.273 μs
GetAllPoints Gaussian 256 BareMinimum 2,071.137 μs 10.9174 μs 9.6780 μs 2,066.766 μs
GetAllPoints Gaussian 256 BareMinimumSubtract 2,081.067 μs 15.3671 μs 14.3744 μs 2,071.338 μs
GetAllPoints Gaussian 256 CantorPure 2,833.809 μs 13.4098 μs 12.5435 μs 2,832.214 μs
GetAllPoints Gaussian 256 HashCodeCombine 2,427.896 μs 12.4426 μs 11.6388 μs 2,432.370 μs
GetAllPoints Gaussian 256 MultiplySum 2,082.012 μs 4.5518 μs 4.0351 μs 2,079.819 μs
GetAllPoints Gaussian 256 OriginalGoRogue 2,237.027 μs 15.0601 μs 14.0873 μs 2,233.495 μs
GetAllPoints Gaussian 256 RosenbergStrongBased 3,248.124 μs 17.4172 μs 16.2921 μs 3,246.529 μs
GetAllPoints Gaussian 256 Rosen(...)tiply [33] 3,258.961 μs 22.9750 μs 21.4908 μs 3,260.933 μs
GetAllPoints Gaussian 256 RosenbergStrongPure 2,924.240 μs 24.7192 μs 23.1223 μs 2,922.183 μs
GetAllPoints Gaussian 256 SimpleShift 2,077.327 μs 22.5966 μs 21.1368 μs 2,083.024 μs
GetAllPoints Gaussian 1024 CurrentPrimitives 47,700.915 μs 682.6227 μs 570.0208 μs 47,548.064 μs
GetAllPoints Gaussian 1024 KnownSize 65,972.578 μs 382.3692 μs 298.5287 μs 65,904.837 μs
GetAllPoints Gaussian 1024 KnownRange 66,787.012 μs 774.4478 μs 686.5278 μs 66,616.494 μs
GetAllPoints Gaussian 1024 BareMinimum8And24 105,163.503 μs 1,388.7427 μs 1,231.0843 μs 104,665.520 μs
GetAllPoints Gaussian 1024 BareMinimum 50,336.344 μs 505.6138 μs 448.2135 μs 50,301.810 μs
GetAllPoints Gaussian 1024 BareMinimumSubtract 50,720.439 μs 592.3468 μs 554.0816 μs 50,503.991 μs
GetAllPoints Gaussian 1024 CantorPure 223,322.479 μs 2,908.8531 μs 2,429.0241 μs 223,792.633 μs
GetAllPoints Gaussian 1024 HashCodeCombine 78,287.414 μs 711.5540 μs 594.1799 μs 78,238.867 μs
GetAllPoints Gaussian 1024 MultiplySum 57,860.082 μs 817.1837 μs 724.4120 μs 58,040.572 μs
GetAllPoints Gaussian 1024 OriginalGoRogue 81,242.374 μs 475.3493 μs 396.9382 μs 81,317.657 μs
GetAllPoints Gaussian 1024 RosenbergStrongBased 264,293.450 μs 2,750.5032 μs 2,296.7948 μs 264,075.650 μs
GetAllPoints Gaussian 1024 Rosen(...)tiply [33] 266,029.737 μs 3,368.0148 μs 3,150.4431 μs 264,821.600 μs
GetAllPoints Gaussian 1024 RosenbergStrongPure 212,134.595 μs 2,005.2107 μs 1,674.4417 μs 211,806.300 μs
GetAllPoints Gaussian 1024 SimpleShift 49,698.344 μs 507.7644 μs 450.1199 μs 49,634.582 μs
Checking if Points are contained within a HashSet: Method DataSet Size Algorithm Mean Error StdDev
CheckForPoints PositiveOnly 10 CurrentPrimitives 1.654 μs 0.0055 μs 0.0049 μs
CheckForPoints PositiveOnly 10 KnownSize 1.669 μs 0.0031 μs 0.0028 μs
CheckForPoints PositiveOnly 10 KnownRange 1.703 μs 0.0019 μs 0.0015 μs
CheckForPoints PositiveOnly 10 BareMinimum8And24 1.634 μs 0.0016 μs 0.0012 μs
CheckForPoints PositiveOnly 10 BareMinimum 1.891 μs 0.0066 μs 0.0055 μs
CheckForPoints PositiveOnly 10 BareMinimumSubtract 1.923 μs 0.0100 μs 0.0094 μs
CheckForPoints PositiveOnly 10 CantorPure 1.739 μs 0.0016 μs 0.0013 μs
CheckForPoints PositiveOnly 10 HashCodeCombine 2.333 μs 0.0043 μs 0.0036 μs
CheckForPoints PositiveOnly 10 MultiplySum 1.890 μs 0.0084 μs 0.0079 μs
CheckForPoints PositiveOnly 10 OriginalGoRogue 1.968 μs 0.0029 μs 0.0025 μs
CheckForPoints PositiveOnly 10 RosenbergStrongBased 2.136 μs 0.0049 μs 0.0044 μs
CheckForPoints PositiveOnly 10 Rosen(...)tiply [33] 2.029 μs 0.0087 μs 0.0082 μs
CheckForPoints PositiveOnly 10 RosenbergStrongPure 1.772 μs 0.0065 μs 0.0061 μs
CheckForPoints PositiveOnly 10 SimpleShift 1.888 μs 0.0072 μs 0.0067 μs
CheckForPoints PositiveOnly 50 CurrentPrimitives 36.091 μs 0.0770 μs 0.0721 μs
CheckForPoints PositiveOnly 50 KnownSize 42.354 μs 0.0751 μs 0.0702 μs
CheckForPoints PositiveOnly 50 KnownRange 42.927 μs 0.0609 μs 0.0540 μs
CheckForPoints PositiveOnly 50 BareMinimum8And24 42.439 μs 0.1080 μs 0.0902 μs
CheckForPoints PositiveOnly 50 BareMinimum 41.130 μs 0.0705 μs 0.0588 μs
CheckForPoints PositiveOnly 50 BareMinimumSubtract 41.975 μs 0.0426 μs 0.0356 μs
CheckForPoints PositiveOnly 50 CantorPure 44.718 μs 0.1119 μs 0.1047 μs
CheckForPoints PositiveOnly 50 HashCodeCombine 62.828 μs 0.3711 μs 0.3290 μs
CheckForPoints PositiveOnly 50 MultiplySum 46.379 μs 0.0690 μs 0.0576 μs
CheckForPoints PositiveOnly 50 OriginalGoRogue 54.574 μs 0.1012 μs 0.0897 μs
CheckForPoints PositiveOnly 50 RosenbergStrongBased 62.416 μs 0.1453 μs 0.1288 μs
CheckForPoints PositiveOnly 50 Rosen(...)tiply [33] 59.344 μs 0.1064 μs 0.0996 μs
CheckForPoints PositiveOnly 50 RosenbergStrongPure 48.584 μs 0.0758 μs 0.0672 μs
CheckForPoints PositiveOnly 50 SimpleShift 41.168 μs 0.0838 μs 0.0784 μs
CheckForPoints PositiveOnly 100 CurrentPrimitives 191.365 μs 0.5997 μs 0.5316 μs
CheckForPoints PositiveOnly 100 KnownSize 175.770 μs 0.3971 μs 0.3316 μs
CheckForPoints PositiveOnly 100 KnownRange 179.334 μs 0.3088 μs 0.2411 μs
CheckForPoints PositiveOnly 100 BareMinimum8And24 173.150 μs 0.3683 μs 0.3265 μs
CheckForPoints PositiveOnly 100 BareMinimum 212.833 μs 0.6219 μs 0.5513 μs
CheckForPoints PositiveOnly 100 BareMinimumSubtract 215.962 μs 0.2549 μs 0.1990 μs
CheckForPoints PositiveOnly 100 CantorPure 184.574 μs 0.3034 μs 0.2690 μs
CheckForPoints PositiveOnly 100 HashCodeCombine 266.436 μs 1.2422 μs 1.1012 μs
CheckForPoints PositiveOnly 100 MultiplySum 191.432 μs 0.2173 μs 0.1926 μs
CheckForPoints PositiveOnly 100 OriginalGoRogue 235.120 μs 0.6492 μs 0.6072 μs
CheckForPoints PositiveOnly 100 RosenbergStrongBased 266.042 μs 0.6329 μs 0.5611 μs
CheckForPoints PositiveOnly 100 Rosen(...)tiply [33] 259.569 μs 1.0846 μs 0.9615 μs
CheckForPoints PositiveOnly 100 RosenbergStrongPure 202.306 μs 0.4866 μs 0.4552 μs
CheckForPoints PositiveOnly 100 SimpleShift 212.559 μs 0.7316 μs 0.6109 μs
CheckForPoints PositiveOnly 175 CurrentPrimitives 606.194 μs 1.6299 μs 1.2725 μs
CheckForPoints PositiveOnly 175 KnownSize 563.789 μs 1.6889 μs 1.4972 μs
CheckForPoints PositiveOnly 175 KnownRange 574.009 μs 1.3222 μs 1.1721 μs
CheckForPoints PositiveOnly 175 BareMinimum8And24 685.073 μs 3.4632 μs 3.0701 μs
CheckForPoints PositiveOnly 175 BareMinimum 662.560 μs 2.0837 μs 1.8471 μs
CheckForPoints PositiveOnly 175 BareMinimumSubtract 671.519 μs 2.7681 μs 2.5893 μs
CheckForPoints PositiveOnly 175 CantorPure 665.439 μs 2.1631 μs 1.9176 μs
CheckForPoints PositiveOnly 175 HashCodeCombine 990.558 μs 3.8491 μs 3.2142 μs
CheckForPoints PositiveOnly 175 MultiplySum 688.865 μs 3.2311 μs 2.8643 μs
CheckForPoints PositiveOnly 175 OriginalGoRogue 902.644 μs 5.1625 μs 4.8290 μs
CheckForPoints PositiveOnly 175 RosenbergStrongBased 989.548 μs 5.1212 μs 4.2764 μs
CheckForPoints PositiveOnly 175 Rosen(...)tiply [33] 950.860 μs 4.5052 μs 4.2142 μs
CheckForPoints PositiveOnly 175 RosenbergStrongPure 646.703 μs 1.9187 μs 1.4980 μs
CheckForPoints PositiveOnly 175 SimpleShift 663.262 μs 2.4664 μs 2.0596 μs
CheckForPoints PositiveOnly 256 CurrentPrimitives 1,657.736 μs 7.4732 μs 6.9904 μs
CheckForPoints PositiveOnly 256 KnownSize 1,364.215 μs 3.4785 μs 3.2538 μs
CheckForPoints PositiveOnly 256 KnownRange 1,388.681 μs 3.8642 μs 3.6145 μs
CheckForPoints PositiveOnly 256 BareMinimum8And24 1,336.160 μs 11.3906 μs 10.6548 μs
CheckForPoints PositiveOnly 256 BareMinimum 1,793.653 μs 6.4705 μs 6.0526 μs
CheckForPoints PositiveOnly 256 BareMinimumSubtract 1,810.136 μs 6.8211 μs 6.0467 μs
CheckForPoints PositiveOnly 256 CantorPure 1,620.382 μs 6.3474 μs 5.9373 μs
CheckForPoints PositiveOnly 256 HashCodeCombine 2,375.179 μs 14.6822 μs 12.2603 μs
CheckForPoints PositiveOnly 256 MultiplySum 1,982.218 μs 10.5393 μs 8.8008 μs
CheckForPoints PositiveOnly 256 OriginalGoRogue 2,194.764 μs 7.2097 μs 6.3912 μs
CheckForPoints PositiveOnly 256 RosenbergStrongBased 2,341.064 μs 4.6354 μs 3.6190 μs
CheckForPoints PositiveOnly 256 Rosen(...)tiply [33] 2,362.555 μs 14.2540 μs 13.3332 μs
CheckForPoints PositiveOnly 256 RosenbergStrongPure 1,533.673 μs 6.2736 μs 5.2387 μs
CheckForPoints PositiveOnly 256 SimpleShift 1,794.055 μs 7.4957 μs 7.0115 μs
CheckForPoints PositiveOnly 1024 CurrentPrimitives 39,472.234 μs 595.7111 μs 557.2285 μs
CheckForPoints PositiveOnly 1024 KnownSize 28,481.091 μs 188.5333 μs 167.1299 μs
CheckForPoints PositiveOnly 1024 KnownRange 28,848.900 μs 170.6151 μs 142.4713 μs
CheckForPoints PositiveOnly 1024 BareMinimum8And24 94,604.662 μs 820.4931 μs 685.1489 μs
CheckForPoints PositiveOnly 1024 BareMinimum 41,590.301 μs 253.0654 μs 211.3210 μs
CheckForPoints PositiveOnly 1024 BareMinimumSubtract 41,884.478 μs 163.2807 μs 136.3468 μs
CheckForPoints PositiveOnly 1024 CantorPure 36,514.874 μs 381.4146 μs 318.4985 μs
CheckForPoints PositiveOnly 1024 HashCodeCombine 73,455.653 μs 683.9682 μs 571.1444 μs
CheckForPoints PositiveOnly 1024 MultiplySum 54,110.508 μs 524.2312 μs 437.7568 μs
CheckForPoints PositiveOnly 1024 OriginalGoRogue 72,343.127 μs 881.1674 μs 735.8147 μs
CheckForPoints PositiveOnly 1024 RosenbergStrongBased 74,451.414 μs 500.0461 μs 390.4031 μs
CheckForPoints PositiveOnly 1024 Rosen(...)tiply [33] 70,437.959 μs 462.2074 μs 360.8611 μs
CheckForPoints PositiveOnly 1024 RosenbergStrongPure 31,253.667 μs 158.0298 μs 140.0893 μs
CheckForPoints PositiveOnly 1024 SimpleShift 42,074.252 μs 713.4606 μs 927.7003 μs
CheckForPoints Gaussian 10 CurrentPrimitives 1.523 μs 0.0022 μs 0.0019 μs
CheckForPoints Gaussian 10 KnownSize 1.816 μs 0.0029 μs 0.0023 μs
CheckForPoints Gaussian 10 KnownRange 1.879 μs 0.0025 μs 0.0022 μs
CheckForPoints Gaussian 10 BareMinimum8And24 1.815 μs 0.0032 μs 0.0027 μs
CheckForPoints Gaussian 10 BareMinimum 1.778 μs 0.0026 μs 0.0020 μs
CheckForPoints Gaussian 10 BareMinimumSubtract 1.793 μs 0.0023 μs 0.0019 μs
CheckForPoints Gaussian 10 CantorPure 1.950 μs 0.0034 μs 0.0030 μs
CheckForPoints Gaussian 10 HashCodeCombine 2.275 μs 0.0041 μs 0.0034 μs
CheckForPoints Gaussian 10 MultiplySum 1.817 μs 0.0041 μs 0.0039 μs
CheckForPoints Gaussian 10 OriginalGoRogue 1.934 μs 0.0044 μs 0.0039 μs
CheckForPoints Gaussian 10 RosenbergStrongBased 2.110 μs 0.0099 μs 0.0093 μs
CheckForPoints Gaussian 10 Rosen(...)tiply [33] 2.053 μs 0.0108 μs 0.0101 μs
CheckForPoints Gaussian 10 RosenbergStrongPure 1.768 μs 0.0036 μs 0.0028 μs
CheckForPoints Gaussian 10 SimpleShift 1.745 μs 0.0040 μs 0.0033 μs
CheckForPoints Gaussian 50 CurrentPrimitives 44.323 μs 0.0640 μs 0.0535 μs
CheckForPoints Gaussian 50 KnownSize 50.355 μs 0.0888 μs 0.0787 μs
CheckForPoints Gaussian 50 KnownRange 51.907 μs 0.1392 μs 0.1302 μs
CheckForPoints Gaussian 50 BareMinimum8And24 49.527 μs 0.0776 μs 0.0648 μs
CheckForPoints Gaussian 50 BareMinimum 49.270 μs 0.1088 μs 0.1017 μs
CheckForPoints Gaussian 50 BareMinimumSubtract 49.984 μs 0.1015 μs 0.0900 μs
CheckForPoints Gaussian 50 CantorPure 52.743 μs 0.1042 μs 0.0975 μs
CheckForPoints Gaussian 50 HashCodeCombine 62.939 μs 0.0459 μs 0.0383 μs
CheckForPoints Gaussian 50 MultiplySum 50.827 μs 0.2768 μs 0.2311 μs
CheckForPoints Gaussian 50 OriginalGoRogue 54.274 μs 0.0505 μs 0.0448 μs
CheckForPoints Gaussian 50 RosenbergStrongBased 63.140 μs 0.1804 μs 0.1599 μs
CheckForPoints Gaussian 50 Rosen(...)tiply [33] 61.645 μs 0.1850 μs 0.1545 μs
CheckForPoints Gaussian 50 RosenbergStrongPure 56.692 μs 0.1216 μs 0.1016 μs
CheckForPoints Gaussian 50 SimpleShift 49.377 μs 0.1352 μs 0.1199 μs
CheckForPoints Gaussian 100 CurrentPrimitives 192.299 μs 0.3349 μs 0.2796 μs
CheckForPoints Gaussian 100 KnownSize 216.861 μs 0.5929 μs 0.5546 μs
CheckForPoints Gaussian 100 KnownRange 225.479 μs 0.4370 μs 0.3874 μs
CheckForPoints Gaussian 100 BareMinimum8And24 210.303 μs 0.5876 μs 0.5209 μs
CheckForPoints Gaussian 100 BareMinimum 209.579 μs 0.3227 μs 0.2695 μs
CheckForPoints Gaussian 100 BareMinimumSubtract 216.964 μs 0.5183 μs 0.4328 μs
CheckForPoints Gaussian 100 CantorPure 229.182 μs 0.4571 μs 0.3817 μs
CheckForPoints Gaussian 100 HashCodeCombine 263.423 μs 0.8386 μs 0.7434 μs
CheckForPoints Gaussian 100 MultiplySum 218.011 μs 0.4436 μs 0.3704 μs
CheckForPoints Gaussian 100 OriginalGoRogue 230.446 μs 1.0986 μs 1.0277 μs
CheckForPoints Gaussian 100 RosenbergStrongBased 280.407 μs 1.1859 μs 1.1093 μs
CheckForPoints Gaussian 100 Rosen(...)tiply [33] 266.504 μs 2.4407 μs 2.0381 μs
CheckForPoints Gaussian 100 RosenbergStrongPure 244.160 μs 1.8889 μs 1.6745 μs
CheckForPoints Gaussian 100 SimpleShift 204.481 μs 1.1799 μs 1.0460 μs
CheckForPoints Gaussian 175 CurrentPrimitives 736.474 μs 3.6802 μs 3.4425 μs
CheckForPoints Gaussian 175 KnownSize 822.350 μs 4.4494 μs 4.1619 μs
CheckForPoints Gaussian 175 KnownRange 838.229 μs 3.3001 μs 2.9255 μs
CheckForPoints Gaussian 175 BareMinimum8And24 800.436 μs 6.1842 μs 5.7847 μs
CheckForPoints Gaussian 175 BareMinimum 796.774 μs 4.8939 μs 4.0866 μs
CheckForPoints Gaussian 175 BareMinimumSubtract 812.243 μs 5.0581 μs 4.7313 μs
CheckForPoints Gaussian 175 CantorPure 962.939 μs 3.4357 μs 3.0457 μs
CheckForPoints Gaussian 175 HashCodeCombine 969.980 μs 10.9830 μs 9.7361 μs
CheckForPoints Gaussian 175 MultiplySum 817.153 μs 4.5572 μs 4.2628 μs
CheckForPoints Gaussian 175 OriginalGoRogue 864.829 μs 5.0153 μs 4.4459 μs
CheckForPoints Gaussian 175 RosenbergStrongBased 1,130.974 μs 5.9792 μs 5.5930 μs
CheckForPoints Gaussian 175 Rosen(...)tiply [33] 1,097.702 μs 8.7252 μs 8.1616 μs
CheckForPoints Gaussian 175 RosenbergStrongPure 999.948 μs 5.6453 μs 5.2806 μs
CheckForPoints Gaussian 175 SimpleShift 804.003 μs 3.7005 μs 3.2804 μs
CheckForPoints Gaussian 256 CurrentPrimitives 1,812.752 μs 12.8294 μs 12.0006 μs
CheckForPoints Gaussian 256 KnownSize 1,984.833 μs 15.0644 μs 14.0912 μs
CheckForPoints Gaussian 256 KnownRange 2,051.017 μs 10.9969 μs 10.2865 μs
CheckForPoints Gaussian 256 BareMinimum8And24 1,987.735 μs 12.6636 μs 11.2259 μs
CheckForPoints Gaussian 256 BareMinimum 1,950.232 μs 6.5067 μs 6.0863 μs
CheckForPoints Gaussian 256 BareMinimumSubtract 1,967.120 μs 12.4193 μs 11.6170 μs
CheckForPoints Gaussian 256 CantorPure 2,651.336 μs 13.9445 μs 13.0437 μs
CheckForPoints Gaussian 256 HashCodeCombine 2,296.196 μs 7.9505 μs 6.6390 μs
CheckForPoints Gaussian 256 MultiplySum 1,975.103 μs 25.5282 μs 22.6301 μs
CheckForPoints Gaussian 256 OriginalGoRogue 2,116.800 μs 9.8747 μs 8.7537 μs
CheckForPoints Gaussian 256 RosenbergStrongBased 3,059.695 μs 31.6836 μs 28.0867 μs
CheckForPoints Gaussian 256 Rosen(...)tiply [33] 3,070.882 μs 12.2806 μs 11.4873 μs
CheckForPoints Gaussian 256 RosenbergStrongPure 2,731.928 μs 21.2105 μs 19.8403 μs
CheckForPoints Gaussian 256 SimpleShift 1,954.049 μs 10.8482 μs 10.1474 μs
CheckForPoints Gaussian 1024 CurrentPrimitives 44,537.051 μs 667.6400 μs 891.2803 μs
CheckForPoints Gaussian 1024 KnownSize 62,020.497 μs 451.4787 μs 377.0052 μs
CheckForPoints Gaussian 1024 KnownRange 62,443.632 μs 481.2699 μs 401.8821 μs
CheckForPoints Gaussian 1024 BareMinimum8And24 91,696.234 μs 1,377.5468 μs 1,150.3140 μs
CheckForPoints Gaussian 1024 BareMinimum 48,393.645 μs 740.6265 μs 656.5461 μs
CheckForPoints Gaussian 1024 BareMinimumSubtract 48,562.427 μs 731.2721 μs 610.6453 μs
CheckForPoints Gaussian 1024 CantorPure 193,042.785 μs 3,008.0590 μs 2,511.8655 μs
CheckForPoints Gaussian 1024 HashCodeCombine 73,777.400 μs 1,084.6623 μs 1,205.5993 μs
CheckForPoints Gaussian 1024 MultiplySum 55,064.569 μs 594.5499 μs 496.4761 μs
CheckForPoints Gaussian 1024 OriginalGoRogue 75,587.076 μs 400.7438 μs 334.6392 μs
CheckForPoints Gaussian 1024 RosenbergStrongBased 230,603.064 μs 1,955.8859 μs 1,527.0270 μs
CheckForPoints Gaussian 1024 Rosen(...)tiply [33] 231,928.267 μs 3,162.4232 μs 2,803.4058 μs
CheckForPoints Gaussian 1024 RosenbergStrongPure 182,300.733 μs 957.2684 μs 848.5935 μs
CheckForPoints Gaussian 1024 SimpleShift 47,886.606 μs 287.9624 μs 240.4616 μs
tommyettinger commented 1 year ago

This looks like the most thorough analysis we could possibly do and still wind up with, essentially, "It's better, and I don't know why." Just adding and rotating doesn't seem like it should work this well, especially when adding and left-shifting (SimpleShift in the benchmarks) tends to get no full-hash collisions even when both positive and negative inputs are used. But, it does seem to work quite well. Since the original GoRogue hash seems to do a lot more work just to get significantly more collisions than it should, switching out to almost any of the competitive hashes would probably be a win (MultiplySum, in particular, seems robust much of the time, despite two multiplications and an add being supposedly slower than an add and a rotation).

This seems to have been a rather powerful nerd-snipe; we could probably find people involved with the internals of this part of .NET, and everyone combined would still be missing the complete picture of why some hashes perform better. I'm definitely impressed by how well .NET's Dictionary and HashSet handle such simplistic hashes; they seem to be doing the bulk of the work to distribute items properly, so the hash can be really quick. I doubt we can find out much more about this without finding some way to test directly against the prime-modulus hash table used by .NET here, but what we do know should be enough for a nice speedup.