-
Couldn't load subscription status.
- Fork 5.2k
Optimize Dictionary.FindValue for constant keys (no constant folding) #117427
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
Conversation
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs
Show resolved
Hide resolved
|
Blocked on #117431 |
|
@EgorBot -amd -intel -arm using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
public class StringDictionaryDefault
{
private static readonly Dictionary<string, int> StringDictionary = new()
{
{ "DOTNET_ThreadPool_UnfairSemaphoreSpinLimit" + 1, 1 },
{ "Hello World" + 2, 2 },
{ "aa" + 3, 3 },
};
[Benchmark] public int LongKey() => StringDictionary["DOTNET_ThreadPool_UnfairSemaphoreSpinLimit1"];
[Benchmark] public int MediumKey() => StringDictionary["Hello World2"];
[Benchmark] public int ShortKey() => StringDictionary["aa3"];
}
public class StringDictionaryIgnoreCase
{
private static readonly Dictionary<string, int> StringDictionary = new(StringComparer.OrdinalIgnoreCase)
{
{ "DOTNET_ThreadPool_UnfairSemaphoreSpinLimit" + 1, 1 },
{ "Hello World" + 2, 2 },
{ "aa" + 3, 3 }
};
[Benchmark] public int LongKey_IgnoreCase() => StringDictionary["DOTNET_ThreadPool_UnfairSemaphoreSpinLimit1"];
[Benchmark] public int MediumKey_IgnoreCase() => StringDictionary["Hello World2"];
[Benchmark] public int ShortKey_IgnoreCase() => StringDictionary["aa3"];
}
public class StringDictionary_SameRef
{
private static readonly Dictionary<string, int> StringDictionary = new()
{
{ "DOTNET_ThreadPool_UnfairSemaphoreSpinLimit", 1 },
{ "Hello World", 2 },
{ "aa", 3 }
};
[Benchmark] public int LongKey_SameRef() => StringDictionary["DOTNET_ThreadPool_UnfairSemaphoreSpinLimit"];
[Benchmark] public int MediumKey_SameRef() => StringDictionary["Hello World"];
[Benchmark] public int ShortKey_SameRef() => StringDictionary["aa"];
} |
|
PTAL @stephentoub essentially what this PR does - it enables unrolling for this Equals call (for both Ordinal and OrdinalIgnoreCase comparers) when Dynamic PGO decides to devirtualize those and the key is a string literal. No impact on value-type keys. |
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs
Show resolved
Hide resolved
|
/ba-g "android-x64 timed out" |
Since I was not able to easily workaround the
arg is address exposedcaused byuint hashCode = (uint)key.GetHashCode();line (which isldarga + constrained. callvirt) which in its turns breaks the inliner-level constant propagation, let's see if this helps.Also, remove
string.EqualsOrdinalIgnoreCase- it was not unrolling friendly.