Fixed HashCode not being Case Insensitive, Improved HashCode Performance & Use SIMD/Intrinsics Code from External Library (Fixes #25) #31
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Changelog
Replaced String Hash Function with Custom One tailored for Lowercase
Optimised for ASCII inputs hashing as lower in-place. non-ASCII inputs fallback to first converting to lowercase before hashing.
To give some context, for strings, .NET uses a cryptographically secure, DoS resistant hash function.
It slow enough that
Dictionary
andHashSet
are hardcoded in the runtime to use a different, non-DoS resistant function if the key istypeof(string)
. (Hint: I checked that function out, it's DJB2 w/ 2 hashes, mixed at the end)Unfortunately you can't use that function 😊 at all, because it's internal, and because
RelativePath
/AbsolutePath
aren'tstring
, you're forced to use the slow one; which is a no-no for us.For a typical
AbsolutePath
to a file within game folder (~120 characters), the improvement in hashing speed is ~8-12x. (Depending on AVX2 availability)For a typical
RelativePath
for a file within game folder, or a file segment in a dictionary (~8-12 characters), the improvement is around ~2.3x.Hash quality is a bit lower/more collision prone, however the time save on hashing heavily outweighs the penalty spent on the occasional moment there's 1 more linear probe in .NET Dictionary (BCL dict uses linear probing). This applies even when used with short <8 character file paths.
For the curious, you can find the relevant benchmarks here.
Moved fancy SIMD/Intrinsics Code
Removed fancy SIMD and Intrinsics code from this library.
Now using the originals from Reloaded.Memory, where I originally copied them from.
For context: It's a lightweight, high performance library for low level memory manipulation & zero cost abstractions, created/maintained by me. Mostly used in game mods & tools [around 200 projects use it], and also has stable API.
This should make maintenance easier, hopefully. (Removes ~1700 LoC from the repo)
The only new code that was specifically written for this PR is the aforementioned lowercase variant of custom string hash.
Note: This is a breaking change, because some of these were public APIs previously. However fixing any relevant code should be easy as the API names should not have changed, so it's just a matter of adding/replacing a namespace.
Improved AbsolutePath.Equals
Equals
comparisons inAbsolutePath.Equals
.Other