-
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
[RyuJIT] Unroll StartsWith/SequenceEqual for ([ReadOnly]Span<char>, const-string) #46392
Conversation
…inter) == ToHex("cstr")`
…inter) == ToHex("cstr")`
I couldn't figure out the best area label to add to this PR. If you have write-permissions please help me learn by adding exactly one area label. |
For SIMD we only need to emit something like this in JIT:
it depends on const string size, it can be a single vector (128 or 256bit). |
57a2833
to
1f25caf
Compare
0646428
to
27232d8
Compare
Any interest on the above or I should close? |
@EgorBo My thought is that this is a lot of code for a very specific set of APIs, and quite restricted compared to the generality of the specified APIs (e.g., only certain types of strings). Is it sufficiently motivated? Namely, is there no other way for users to achieve better performance with a source-level implementation that would be "good enough", without the need to support all-platforms with JIT changes? Could the JIT do better (even if not optimal) with the general case without converting these to intrinsics? Could the source implementation use already existing hardware intrinsics? Could a new, specific, set of source-level APIs be defined to handle these special cases, not requiring JIT changes to achieve the perf results? |
Ok, makes sense going to close it. PS: Still, this benchmark: [Benchmark]
public bool SpanStartsWith(string str) =>
str.AsSpan().StartsWith("ProxyAuthenticateHeader", StringComparison.OrdinalIgnoreCase);
is a sign we can do better there. |
This PR optimizes the following APIs:
when the second arg is a constant string. For now it only handles strings with length of 1, 2 or 4 chars, but it can be extended to handle longer strings as well via SIMD (
[8..32]
range), here are some benchmarks.It addresses #45613 but only for spans since we promote them for high-performance tasks. In theory, it can be then extended to support plain string objects if needed.
1. Small strings (e.g. length is 4)
Codegen diff example: https://www.diffchecker.com/BeNpMF78
2. Small strings (e.g. length is 4, ignore case)
3. Bigger strings (e.g. length is 23)
2. Bigger strings (e.g. length is 23, ignore case)
Standalone benchmark: https://gist.github.com/EgorBo/8a4e4cda14eac0e605dd7bac68c56314
Inspired by LLVM: https://godbolt.org/z/8fcqfb
/cc @jkotas @dotnet/jit-contrib