-
Notifications
You must be signed in to change notification settings - Fork 174
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
100% readonly fields and ReadOnlySpan #47
Conversation
Using ReadOnlySpan<Char> instead of Char[]. Adding reimpl for .NET 4.x.
Tidying up.
Hey @Jehoel One small change noted there but I'll go ahead and merge to get this in. Looking forward to the other changes, but please keep the PRs as small as you can. Easier to review multiple PRs if needed. |
@manigandham Uhhh, I wasn't prepared for it to be merged as-is - there's a bunch of TODOs and Questions left in comments.... |
I only see 3 TODOs; - One about short variable names and the others about the seps/alphabet characters. We can take care of that after your other changes before doing a release. This project was ported directly from the Javascript version originally so it followed the same layout and naming. Feel free to create a new branch or just push to this one and we can make another PR. |
I'll admit this PR is a bit busy, I had a bad case of "one more thing...".
My main objective was to change
class Hashids
such that all of its fields werereadonly
, as currently the (somewhat twisted) initialization logic for_alphabet
and_seps
happens in a separate non-static method which mutatesthis
fields, which isn't permitted byreadonly
.The main commit that matters is c0564ad which moves that init logic into a new
static void InitCharArrays
.Another significant change is in 99bd19f which replaces occurrences of
char[]
andlong[]
withReadOnlySpan<>
to signal intent that a parameter is not mutated, which is always a concern when passing around arrays as parameters (given C# lacks C++-styleconst
-correctness or first-class support for immutability).For compatibility with pre-.NET Standard 2.1 consumers (.NET Framework, etc) the library includes a thin
internal struct ReadOnlySpan<T>
reimplementation, which should be zero-cost (so long as it isn't moved to the GC heap or boxed), and the JIT should also inline all or most of its members.I actually didn't put much (any?) effort into other optimizations, though I'm happy with the benchmark results below.
I'm tempted to add another commit with C# 8.0 nullability too...
UPDATE: I successfully implemented C#
<Nullable>enabled</Nullable>
as well as other performance improvements (such as eliminating array allocations in the variousEncode
/Decode
overloads), but things snowballed and it became far too much to put into a PR, so I've moved those changes to a separate branch I'll submit a PR for only after this is approved (and hopefully merged).Benchmark results:
ReadOnlySpan
implementation. I don't believe that the .NET 4.8 runtime and JIT has any optimizations forreadonly
fields though.readonly
fields and the fact thatReadOnlySpan
is heavily optimized in .NET Core..NET Framework 4.8
Before
After
.NET 5.0
Before
After