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.
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
Convert.Try{From/To}HexString #86556
Convert.Try{From/To}HexString #86556
Changes from 10 commits
3a0c31e
cc13dca
eecaed0
b8cb6dd
772208f
7333ca3
f23df24
70c9321
f80a8d3
9fd5c99
d063d4f
986c8fa
c644e59
794eff8
8a858be
6e48f51
071e5f4
80431ab
38d018f
948616f
af59a7f
dbfe893
30afc43
010c836
f532064
9afd0cb
e7439d4
f247ed0
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
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.
Use concrete types here. Same on other places.
Perf-wise this could be
nuint
, so all the division and modulo operations are treated as (fast) bit-operations.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.
That's interesting. We rarely use native width types except in interop contexts. @jkotas @EgorBo is it correct that in hot code of this type, it can have perf benefit for simple storage of counters and offsets?
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.
Afair, JIT knows that Span.Length (and Array.Length as well) are never negative so it doesn't need extra efforts from the C# side 🙂 e.g.:
(some of the changes landed in .NET 8.0 so might be not visible on sharplab yet)
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.
Right -- I'm not aware of patterns where nuint gives better code.
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.
Thanks for the reminder -- I'll forget sometimes about the new JIT-goodness.
Quite a lot of vectorized code uses the native width types, because memory operations don't need (sign-) extending moves then (e.g.
Unsafe.Add(ref ptr, intVariable)
vs.Unsafe.Add(ref ptr, nuintVariable)
-- https://godbolt.org/z/v8E31Wdsx).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.
Would
Math.DivRem
be more efficient here? Especially once it becomes an intrinsic.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 doubt it, since the JIT optimizes
length % 2 != 0
to(length & 1) != 0
.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.
That comment wasn't just about the single length check, but also the division done a few lines later. DivRem in theory combines the two operations.
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 JIT can optimize
(uint)length / 2
to(uint)length >> 1
. On X86,DivRem
would likely be implemented using adiv
instruction, which is an relatively expensive operation.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.
We usually use a seeded Random so the tests are reproducible.
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 agree with Dan, but since the existing tests in this type were already using
Security.Cryptography.RandomNumberGenerator
it's acceptable to keep it.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 can see that you have provided the PR before the API got approved: #78472 (comment)
In the approved proposal the methods have been renamed (no
Try
prefix) and they are supposed to returnOperationStatus
rather thanbool
. Please change the contract and implementation to reflect that.They also include two out parameters. But since
charsConsumed
would be always equalbytesWritten
I think it's reasonable to have only one parameter. We did exactly the same thing forAscii
:https://github.com/dotnet/runtime/blob/24d7f5a58ac4bcee1ec5197427068e437f19552f/src/libraries/System.Runtime/ref/System.Runtime.cs#L14306-L14307
But I don't have the power to approve API changes without board review. @bartonjs can we have only one
out
parameter here?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.
charsConsumed
will be twicebytesWritten
, unless the method supports whitespace (which I don't remember if it's supposed to, or not) and then it'll becharsConsumed >= 2 * bytesWritten
.The pattern for OperationStatus-returning members is
OperationStatus [Method](ReadOnlySpan<TSource> source, Span<TDestination> destination, [required options], out {bytes|chars|items}Consumed, out {bytes|chars|items}Written, [defaulted parameters])
, even when consumed and written will have a known/stable relationship.