-
Notifications
You must be signed in to change notification settings - Fork 58
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
Use NatsMemoryOwner for Base64Url Encoder #565
base: main
Are you sure you want to change the base?
Conversation
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.
Self review with asks for feedback.
{ | ||
using (var owner = EncodeToMemoryOwner(inArray, raw)) | ||
{ | ||
var segment = owner.DangerousGetArray(); |
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.
The use here isn't dangerous since we are owning it in scope,
This was just easiest way to call new string
without #if
type stuff for different FWs.
As it stands, this should still be a significant improvement as far as array allocations due to the pooling.
LMK if this deserves a comment.
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 think it's good. as you said it's in scope so it's fine. a short comment might be nice for our future selves. btw if you're concerned maybe use span.tostring()? - i believe that was you suggestion to something else before 😅 having said that I'm guessing string.ctor(char[]) must be super fast!
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.
span.tostring()?
I had the same realization lol... span.ToString
is going to be the best way to go on these.
|
||
var lengthMod3 = length % 3; | ||
var limit = length - lengthMod3; | ||
var output = new char[(length + 2) / 3 * 4]; | ||
var owner = NatsMemoryOwner<char>.Allocate((length + 2) / 3 * 4); |
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.
Should we be try-catch-dispose-throw
around this, case something derps in the encode?
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, Should we be adding a flag to the method here to specify 'clearing' and pass it in here? I guess it depends on the security concern of the SHA lingering.
CC @mtmk @caleblloyd
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.
Should we be try-catch-dispose-throw around this, case something derps in the encode?
Should we encode to span instead? in case of sha we can also stackalloc maybe?
Also, Should we be adding a flag to the method here to specify 'clearing' and pass it in here?
Do you mean clearing the input array or output?
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.
Should we encode to span instead? in case of sha we can also stackalloc maybe?
Hmm I can give it a shot, it might be cleaner...
Do you mean clearing the input array or output?
Clearing the buffered array. IIRC NatsMemoryOwner has a flag to say whether the array is cleared on return.
My 'gut' says yes but if we can get away with stackallocing the span, point is moot. Will check.
if (info.Digest == null | ||
|| info.Digest.StartsWith("SHA-256=") == false | ||
|| info.Digest.AsSpan().Slice("SHA-256=".Length).SequenceEqual(digest.Span) == false) |
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.
There is likely a 'better way' to handle this case, but this seemed clear and should be performant enough.
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 think it's good. maybe ordinal StartsWith to avoid cultures?
Resolves #557
By using NatsMemoryOwner we can avoid a lot of GC thrashing here.
Note:
Once Microsoft.Bcl.Memory hits 9.0, there will be a
Base64Url
class to get rid of our encoder, see : dotnet/runtime#103617If we are OK pulling in 'odd-numbered' deps, once that is released, we will want to revisit the topic.
Above note aside, this PR should lower GC pressure on ObjectStore operations all targets (i.e. NETSTANDARD/NET).
I kept it as simple as I could in the mindset that longer term, we can lean on BCL instead, i.e. Future PRs can optimize for scenarios where more IFDEFs are worth the cost and/or we update deps.