-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Add Span SequenceCompareTo extension method #26232
Conversation
Debug.Assert(secondLength >= 0); | ||
|
||
if (Unsafe.AreSame(ref first, ref second)) | ||
goto Equal; |
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.
return firstLength.CompareTo(secondLength);
can be right here. I do not think you are getting anything by jumping to 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 would say this "AreSame" will be optimization only in very rare cases, but if you see it as useful, then goto solution will generate shorter native code, so I am for leaving it there.
int result = Unsafe.AddByteOffset(ref first, i).CompareTo(Unsafe.AddByteOffset(ref second, i)); | ||
if (result != 0) return result; | ||
i += 1; | ||
} |
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.
Direct return 0;
would be better, I think.
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.
Where would I return 0? After the loop ends, we may still return other values.
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.
After the loop ends, you know that the two sequences are 100% equal. No?
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.
Sorry, I have misread this ... I though that the first statement is comparing the lengths.
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.
Your implementation was fine as it was. (Also ignore the other 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.
No, minLength is the length of the smaller sequence. The lengths could be different still.
} | ||
|
||
Equal: | ||
return firstLength.CompareTo(secondLength); |
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 am for changing this to simple return firstLength-secondLength
(because lengths could be only positive there cannot happen any bad overflow).
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 wanted the results here to be consistent with the existing int.CompareTo. Subtracting could result in values other than {-1, 1, 0}. I am not sure if the performance win is worth the inconsistency. Thoughts?
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 contract for Compare
methods is to return positive, 0, negative. It is not necessary to normalize to -1,1,0 - other paths in your implementation do not normalize either.
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 contract for
Compare
methods is to return positive, 0, negative. It is not necessary to normalize to -1,1,0
Fair point
other paths in your implementation do not normalize either.
Where? Every comparison uses the CompareTo method (at least for T = byte), as far as I can tell.
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.
Byte.CompareTo method also does not return just -1, 1, 0 (it is also simple subtraction). Only int one have to due to possibility of overflow for negative inputs. And because of mispredicted comparisons in int.CompareTo overhead could be nontrivial, but it is harder to measure...
Is this PR good to go? |
* Add SequenceCompareTo initial * Update tests and remove use of Dangerous API * Add SequenceCompareTo performance test and loop unroll * Revert loop unrolling SequenceCompareTo * Vectorize SequenceCompareTo<byte> * Fix performance test class name. * Address PR feedback Commit migrated from dotnet/corefx@7931769
Fixes https://github.com/dotnet/corefx/issues/16878
SequenceCompareTo<byte>
implementationSequenceCompareTo<T>
similar toSequenceEqual<T>
since I observed no performance improvement (in fact there was some regression for T = int)cc @KrzysztofCwalina, @jkotas, @atsushikan, @AronParker, @Bobris