-
Notifications
You must be signed in to change notification settings - Fork 174
reduce amount allocation for single number decode #65
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
reduce amount allocation for single number decode #65
Conversation
I may have missed the purpose of the |
The following code throws var hashids = new HashidsNet.Hashids("salt", minHashLength: 4);
var hash = hashids.Encode(123);
Console.WriteLine(hash);
var decoded = hashids.DecodeSingle(hash); // <-- Exception here
Console.WriteLine(decoded); |
Thanks I'll take a look. |
I think I managed to find a way to actually improve Decode for multiple numbers without allocating string arrays for guards 😄 |
@jetersen this still throws with |
Damn empty entries 🤣🤣🤣🤣 |
The slight speed difference I think is only down to outliers... Which is set to not remove 🤔 Before: a7478cd
After: a7478cd
|
Hmm, the following code produces different exception for var hashids = new HashidsNet.Hashids("salt", minHashLength: 0, alphabet: "0123456789ABCDEF");
var hash = hashids.EncodeLong(long.MaxValue);
Console.WriteLine(hash);
var decoded = hashids.DecodeSingleLong(hash + "1"); // HashidsNet.NoResultException on main branch and HashidsNet.MultipleResultsException on PR branch
Console.WriteLine(decoded); |
I've checked the 1.4.1 version and following sample produces array of 0 length: var hashids = new HashidsNet.Hashids("salt", minHashLength: 0, alphabet: "0123456789ABCDEF");
var hash = hashids.EncodeLong(1000);
Console.WriteLine(hash);
var decodedArray = hashids.DecodeLong(hash + "1");
Console.WriteLine(decodedArray.Length); // <-- 0 (No results decoded) While on the PR branch this gives a MultipleResultsException. |
I took your example @KeterSCP You specifically added a So how can I can remove the check for separators but than I should also remove the I tried to keep the behavior of hashids.net/src/Hashids.net/Hashids.cs Lines 180 to 181 in b2c7877
|
Rebased |
The log doesn't show the changes. You might need to pull down the changes on |
Signed-off-by: Joseph Petersen <josephp90@gmail.com>
Rebased successfully 😅 I forgot to fetch upstream before rebasing. |
Well, I just checked how it behaves for invalid hashes and compared how it did before. If such change is ok for the author of library, then i suppose it can be merged. Code looks good. |
As this can never happen without checking for separators.
I created 535df3d as another way. This would result in NoResultException when trying to parse multiple when using I can remove the commit as well. I have added my reasons for the PRs in the description. |
return Array.Empty<long>(); | ||
} | ||
|
||
private long[] NumbersFrom(string hash) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created this new method to reset stack and avoid stackoverflow 😅
Before:
After 99a41e4, 395a2d6 and 7567d90:
I would like to see if it possible to get them to return But |
src/Hashids.net/Hashids.cs
Outdated
public string EncodeLong(long number) => GenerateHashFrom(stackalloc[] { number }); | ||
public string EncodeLong(long number) | ||
{ | ||
Span<char> result = stackalloc char[20]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why there is a limit of 20 chars? Now it throws if you try to encode value with minHashLength
parameter set to >20, however previously it was possible to get string of any length
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought the max length for a long was 19 plus 1 for lottery hence 20.
We should have a test that validate any length.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also potentially any length does not make sense when it comes to max url length or other serialization issues or memory optimization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't confuse input number length (e.g var num = 1234
has length of 4) and output hash length (which can differ)
hey @jetersen The fundamental problem here is that As nice as it is to have improved performance, I don't think it should come at the cost of correct results. Is there a way to fix this? |
@manigandham As you can see there was an argument about this Whether it returns But as you can see I suggest I can revert that change in 535df3d Before 535df3d it is possible to detect multiple entries but apparently the way I do that was not appreciated. I was looking for any Separator characters, and throw Again What difference does it make |
An exception being thrown signals that there's an issue with the operation, but the actual exception type describes why there was an issue. I think it's very important for the user to know so they understand why the result didn't decode (whether there's multiple numbers or none). I'll leave it to @ullmark to decide how to proceed. |
@manigandham If the performance increases of this library is important for the ones who uses it, and this looks good we should merge this. tbh; it uses some syntax I've never seen or used (or had any need to) in C#, so @jetersen you are welcome to come in and maintain if you like. :) Re. the errors, if it's not possible to detect multiple entries in a good way, just throw a "NoResultException" since that is still true, given the alphabet + salt, and how you use the library, we weren't able to get a result. 🤷♂️ |
@jetersen if you want to change the exception to say |
@manigandham it is already throwing |
@ullmark I would be happy to help maintain and review PRs 😄 |
v1.6.0 released https://www.nuget.org/packages/Hashids.net/1.6.0 |
Reason for change:
Almost 5x saving for single decode
After further changes by adding a optimized splitter using
Span<char>
it is only a 2x saving.By adding a specific
GetNumberFrom
that handles a single number we avoid creating unnecessary array forlong[]
and can simply pass backlong
I think it would greatly benefit to also actually have a
GenerateHashFrom
that takes single int/long that would mean single encode decode could be 100% allocation free.