Makes GetChildKeys more efficient#67186
Conversation
|
Tagging subscribers to this area: @dotnet/area-extensions-configuration Issue DetailsDetailsPrevents Fixes #62510 BenchmarksBenchmark code: link to gist
|
|
@adamsitnik not sure if I need to change a setting for the |
src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs
Outdated
Show resolved
Hide resolved
|
Can you also add a performance test for keys that do need the split? |
As you suspected the commit was not optimized for the keys needing split. Now with the newest diff I changed it to be optimized for split case. Using: {
// in Setup:
var splittingKeys = new Dictionary<string, string>() { };
for (int i = 1000; i < 2000; i++)
{
splittingKeys.Add("a:" + i.ToString(), string.Empty);
}
_chainedConfigWithSplitting = new ChainedConfigurationProvider(new ChainedConfigurationSource
{
Configuration = new ConfigurationBuilder()
.Add(new MemoryConfigurationSource { InitialData = splittingKeys })
.Build(),
ShouldDisposeConfiguration = false,
});
}
[Benchmark]
public void AddChainedConfigurationWithSplitting()
=> _chainedConfigWithSplitting.GetChildKeys(new string[0], null);
|
|
Should your perf tests get added to the perf repo? BTW you can copy paste the results tables into an issue like this as they are valid markdown. That’s easier than pasting screenshots. |
src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs
Outdated
Show resolved
Hide resolved
| y = yParts[i]; | ||
| if (x!.Contains(ConfigurationPath.KeyDelimiter) && y!.Contains(ConfigurationPath.KeyDelimiter)) | ||
| { | ||
| string[] xParts = x!.Split(_keyDelimiterArray, StringSplitOptions.RemoveEmptyEntries); |
There was a problem hiding this comment.
I agree with @tarekgh.
BTW it's a pity that the code which is consuming this type is using string to represent a complex type and uses indexof/split back and forth.
The index is known here:
then a substring is performed:
then all the logic is reversed to be able to sort the keys:
It's just a digression, I don't expect @maryamariyan to fix it in this PR (these types are public)
adamsitnik
left a comment
There was a problem hiding this comment.
not sure if I need to change a setting for the MultimodalDistribution warning showing up in the screenshot
You don't need to change anything. This benchmark just seems to be multimodal.
| y = yParts[i]; | ||
| if (x!.Contains(ConfigurationPath.KeyDelimiter) && y!.Contains(ConfigurationPath.KeyDelimiter)) | ||
| { | ||
| string[] xParts = x!.Split(_keyDelimiterArray, StringSplitOptions.RemoveEmptyEntries); |
There was a problem hiding this comment.
I agree with @tarekgh.
BTW it's a pity that the code which is consuming this type is using string to represent a complex type and uses indexof/split back and forth.
The index is known here:
then a substring is performed:
then all the logic is reversed to be able to sort the keys:
It's just a digression, I don't expect @maryamariyan to fix it in this PR (these types are public)
src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Günther Foidl <gue@korporal.at>
|
With new changes, Without diff: With changes: For |
|
Should your benchmarks above be added to dotnet/performance to protect your change from regressions? |
src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs
Outdated
Show resolved
Hide resolved
I plan to add those. Are you recommending to add them before this PR goes in? |
That's your call. Adding them before the main PR (at least say half a day before) has the nice effect of gathering numbers before the change, so you see a nice uptick in the graph when your change goes in, and if it regresses it might possibly be interesting what the original value was. I don't think it matters otherwise. |
src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs
Outdated
Show resolved
Hide resolved
|
Found certain use cases for which replacing The replacement function needs to behave similar to One way forward would be to make use of something like the Vaguely something like: var splitterX = spanX.Split(',', StringSplitOptions.RemoveEmptyEntries);
var splitterY = spanY.Split(',', StringSplitOptions.RemoveEmptyEntries);
while (splitterX.TryMoveNext(out var sliceX) && splitterY.TryMoveNext(out var sliceY))
{
// then compare sliceX with sliceY
}
// return splitterX.Length - splitterY.LengthUPDATE Seems like |
This looks a good idea to use. |
- Also fixing a regression from last commit + adds test
|
I first tried using Without diff: UPDATED TO LATEST: |
src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs
Outdated
Show resolved
Hide resolved
eerhardt
left a comment
There was a problem hiding this comment.
We know that xDelimiterIndex is at a delimiter. There is no reason to slice to that location, you can skip past it.
src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Eric Erhardt <eric.erhardt@microsoft.com>
eerhardt
left a comment
There was a problem hiding this comment.
This looks good to me. Thanks for the great work here, @maryamariyan.




Details
Prevents
ChainedConfigurationProvider.GetChildKeysfrom splitting strings or making unnecessary allocation when keys do not contain delimiter or when keys are empty.Fixes #62510
Benchmarks
Benchmark code: link to gist
Also dotnet/performance PR: dotnet/performance#2336
Without diff:
UPDATED TO LATEST:
With latest PR diff (updated using b128f63):