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
Move the IsLeft/IsRight decision out of the loop and use computed substring set #88516
Move the IsLeft/IsRight decision out of the loop and use computed substring set #88516
Changes from all commits
677d59d
c8c8801
a168767
860ebb3
c1dd5d9
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.
Here's a real improvement. We do the math for setting a negative index (e.g. from the right side) starting with
count
characters from the right (as before). Then on line 81 we keep decrementingcomparer.Index
as we go on moving the "cursor" left.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 need to re-slice the string again here. It would be awesome if we could have a
HashSet<ReadOnlySpan<char>
but that's not going to happen as those would be structs not objects.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.
This ternary is the sole remaining conditional jump in the hot loop, but there's no good way to avoid that simultaneous avoiding
delegate
overhead so make it as simple as possible. The number of jumps (old vs. new) is identical, but this is a tiny tiny block of JITtable goodness.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 have tried running this as a jumpless method body, but it makes little difference and is harder to grok; passing
fromRight = 0
for left, orfromRight = 1
for right which requires theSubstringComparer
s to carry the left/right multiplier with them (so more state...):Also, if we COULD swap the
HashSet<string>
's comparer out for left vs. right the we could just have that knowledge embedded with a trait and thus fully jumpless, but that would require allocating twoHashSet<string>
s which might be an allocation regression nobody wants :(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 did something like that in PR #89689 which is a huge win... since we can't swap the comparer, I ended up creating both a left and right HashSet with backing comparer that "hard codes" the left/right logic. HUGE WINS, see that PR.
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 Slicer does the left/right based on the sign of the
Index
value now, which should JIT down better.I really wish that String.AsSpan understood the use of
-1
start intrinsically as string.Length - 1... that would make the ternary unneeded.