-
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
Call String.Contains(char) from String.Contains(string) for single-char literals #97632
Conversation
Tagging subscribers to this area: @dotnet/area-system-runtime Issue DetailsAddresses Benchmark: using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
public class MyBenchmarks
{
readonly string _inputString =
"Permission is hereby granted, free of charge, to any person obtaining " +
"a copy of the Unicode data files and any associated documentation";
[Benchmark]
public bool Contains_string() => _inputString.Contains("X");
}
It uses
|
We already special-case length 1 inside of SpanHelpers.IndexOf. Presumably then the 1.7ns difference here is a fixed overhead involved in the non-inlined IndexOf call and the few extra instructions there, rather than something that grows with the length of the haystack? |
That is my understanding as well, I just though that a simple harmless change to eliminate that difference wouldn't hurt |
I wonder if there's something we can with regards to PGO or general inlining to help the JIT better understand cases like this. That is, we have "many" (I believe thousands) of places where we have In a more ideal world, the JIT would be able to do partial inlining or we'd have |
There is also a different/better/more generic way to solve this - inline large methods as is and don't compile cold parts (partial compilation) if their hot part is small according to context-sensitive PGO data. But both options will likely require a lot of efforts 🤷♂️ Andy already implemented some basic support for this, only for tier0 for now. |
@EgorBo Would that mean https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1847 should be removed? |
IMO, no. It's still better, simpler, and overall cheaper to use the explicit overload where it exists. It also doesn't rely on runtime specific optimizations (which may not light up for AOT, Mono, Burst, etc). Where-as if you know you have a single character, using the dedicated API explicitly does the right thing always. |
Could we do the same with EndsWith / StartsWith? |
Addresses
String.Contains
performance concerns in this tweet: https://twitter.com/STeplyakov/status/1751858621212991573Benchmark:
It uses
IsKnownConstant
to avoid perf regressions for non-constant and non-single-char input (although, it's probably also beneficial for non-constant and single-char)