-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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 SpanHelpers.SequenceCompareTo for String.CompareOrdinal #111586
base: main
Are you sure you want to change the base?
Conversation
Tagging subscribers to this area: @dotnet/area-system-runtime |
You should test perf for longer strings as well. CompareOrdinalHelper implementation is specifically tuned for string alignment that is only going to show up on longer strings https://github.com/dotnet/runtime/pull/111586/files#diff-79247fffe0432073a5ddd0de692f4beaf015c0c483dd311a921393d05568a3e4L119-L122 |
Well there is regression at ~40 length, where SIMD should start to kick in. |
@EgorBot -intel -amd using System;
using System.Collections.Generic;
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
namespace BenchmarkGround
{
public class Bench
{
public IEnumerable<object[]> Args =>
[
["Foo", "FooBar"],
["Foo", "Bar"],
["A quick brown fox jumps over a lazy dog", "A quick brown fox jumps over a lazy hog"],
[new string([.. Enumerable.Repeat('a', 1000), '1']), new string([.. Enumerable.Repeat('a', 1000), '2'])],
];
[Benchmark]
[ArgumentsSource(nameof(Args))]
public int Compare(string left, string right) => string.Compare(left, right, StringComparison.Ordinal);
[Benchmark]
[ArgumentsSource(nameof(Args))]
public int CompareOridinal(string left, string right) => string.CompareOrdinal(left, right);
}
} |
@huoyaoyuan I was wondering if I should add that ability to define simple benchmarks without classes too 🤔 |
I was making more mistakes for example missing Actually I'm getting help from bot just because benchmark in Windows Terminal over RDP looks unstable. |
The benchmark shows small regression on Cascade Lake/small length. It's similar to what I see on Raptor Lake. What's the preference for the action 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.
nit: unsafe context can be removed from CompareOrdinalHelper
Since it's Intel only it is most likely JCC Erratum |
@@ -84,112 +84,43 @@ private static unsafe int CompareOrdinalHelper(string strA, string strB) | |||
"For performance reasons, callers of this method should " + | |||
"check/short-circuit beforehand if the first char is the same."); | |||
|
|||
int length = Math.Min(strA.Length, strB.Length); | |||
// Check if the second chars are different 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.
Does this implementation effectively depend on this small wrapper to be inlined into the few callers for good perf / no regressions variety of inputs?
I am wondering whether it would be better to mark this small wrapper with AggressiveInlining and move the comparison of the first char (that's manually inlined today) into it as well.
// takes up 8 bytes on 32-bit, 12 on x64. For empty strings the null | ||
// terminator immediately follows, leaving us with an object | ||
// 10/14 bytes in size. Since everything needs to be a multiple | ||
// of 4/8, this will get padded and zeroed out. |
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.
It is interesting that we are not doing any tricky casing like this for string Equals that is presumably much more common operation than string Compare.
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.
filed #111806 to experiment with microbenchmarks 🙂
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.
BTW: is it actually legal to rely on padding after \0 in empty strings to be always zeroed? (the comment mentions it)
Helps reusing centralized code under
SpanHelpers
. There shouldn't be much change for performance, just ensuring no regression.Benchmark: