Repository navigation
[Perf] Regressions in IndexOf #54165
Copy link
Copy link
Closed
Labels
arch-x64area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMICLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIos-windowstenet-performancePerformance related issuePerformance related issuetenet-performance-benchmarksIssue from performance benchmarkIssue from performance benchmark
Milestone
Description
Run Information
| Architecture | x64 |
|---|---|
| OS | Windows 10.0.18362 |
| Baseline | 4a73cb9af55814e26b78f22d30bd35faa60c31a3 |
| Compare | 6ab1cee00ba41b308009c88864aba46b0f61f061 |
| Diff | Diff |
Regressions in System.Globalization.Tests.StringSearch
| Benchmark | Baseline | Test | Test/Base | Test Quality | Baseline IR | Compare IR | IR Ratio | Baseline ETL | Compare ETL |
|---|---|---|---|---|---|---|---|---|---|
| LastIndexOf_Word_NotFound - Duration of single invocation | 556.53 ns | 592.84 ns | 1.07 | 0.01 | |||||
| LastIndexOf_Word_NotFound - Duration of single invocation | 556.77 ns | 592.91 ns | 1.06 | 0.00 | |||||
| IndexOf_Word_NotFound - Duration of single invocation | 560.81 ns | 594.70 ns | 1.06 | 0.00 | |||||
| LastIndexOf_Word_NotFound - Duration of single invocation | 556.54 ns | 590.50 ns | 1.06 | 0.00 | |||||
| IndexOf_Word_NotFound - Duration of single invocation | 560.67 ns | 596.84 ns | 1.06 | 0.00 | |||||
| IndexOf_Word_NotFound - Duration of single invocation | 560.08 ns | 596.92 ns | 1.07 | 0.00 |
Historical Data in Reporting System
Repro
git clone https://github.com/dotnet/performance.git
py .\performance\scripts\benchmarks_ci.py -f netcoreapp5.0 --filter 'System.Globalization.Tests.StringSearch*'Details
Payloads
Histogram
System.Globalization.Tests.StringSearch.LastIndexOf_Word_NotFound(Options: (en-US, IgnoreNonSpace, False))
System.Globalization.Tests.StringSearch.LastIndexOf_Word_NotFound(Options: (en-US, None, False))
System.Globalization.Tests.StringSearch.IndexOf_Word_NotFound(Options: (, None, False))
System.Globalization.Tests.StringSearch.LastIndexOf_Word_NotFound(Options: (, None, False))
System.Globalization.Tests.StringSearch.IndexOf_Word_NotFound(Options: (en-US, IgnoreNonSpace, False))
System.Globalization.Tests.StringSearch.IndexOf_Word_NotFound(Options: (en-US, None, False))
Docs
Profiling workflow for dotnet/runtime repository
Benchmarking workflow for dotnet/runtime repository
| Architecture | x64 |
|---|---|
| OS | Windows 10.0.18362 |
| Baseline | 4a73cb9af55814e26b78f22d30bd35faa60c31a3 |
| Compare | 6ab1cee00ba41b308009c88864aba46b0f61f061 |
| Diff | Diff |
Regressions in System.Memory.ReadOnlySpan
| Benchmark | Baseline | Test | Test/Base | Test Quality | Baseline IR | Compare IR | IR Ratio | Baseline ETL | Compare ETL |
|---|---|---|---|---|---|---|---|---|---|
| IndexOfString - Duration of single invocation | 231.36 ns | 245.69 ns | 1.06 | 0.00 |
Historical Data in Reporting System
Repro
git clone https://github.com/dotnet/performance.git
py .\performance\scripts\benchmarks_ci.py -f netcoreapp5.0 --filter 'System.Memory.ReadOnlySpan*'Details
Payloads
Histogram
System.Memory.ReadOnlySpan.IndexOfString(input: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", value: "x", comparisonType: InvariantCultureIgnoreCase)
Docs
Profiling workflow for dotnet/runtime repository
Benchmarking workflow for dotnet/runtime repository
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
arch-x64area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMICLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIos-windowstenet-performancePerformance related issuePerformance related issuetenet-performance-benchmarksIssue from performance benchmarkIssue from performance benchmark







Activity
[-][Perf] Changes at 5/19/2021 3:09:27 AM[/-][+][Perf] Regressions in IndexOf[/+]tarekgh commentedon Jun 15, 2021
@EgorBo @kunalspathak, I have looked at the merged commits around the regression time, I am not seeing anything can be related to cause this issue except the following two commits:
We don't have any code globalization code changes at all around that time. Could you please have a look?
CC @jkotas
kunalspathak commentedon Jun 15, 2021
It seems to be coming from #52827 - @AndyAyersMS
3 remaining items
AndyAyersMS commentedon Aug 10, 2021
Need to use a net5.0 host for BDN to avoid some SDK skew trying to run older bits. Hopefully this is ok. Looks like per that my change indeed introduced a regression, but not from the switch peeling. Instead it may be here:
runtime/src/coreclr/jit/fgopt.cpp
Lines 1778 to 1783 in 705bbfd
The old logic effectively had
&&for that second condition, not||. Am seeing what fixing this does....AndyAyersMS commentedon Aug 10, 2021
Hmm, not that. Maybe I'll try reverting more in the area of this change. The old logic seemed wonky but perhaps it had merit at times.
AndyAyersMS commentedon Aug 10, 2021
Yep, that seems to do the trick:
Time to look at what this older logic actually did. Perhaps it is more sensible than I realized.
AndyAyersMS commentedon Aug 10, 2021
The significant diff is in
CompareInfo:IndexOfOrdinalHelper(ReadOnlySpan`1,ReadOnlySpan`1,int,long,bool):int:thiskunalspathak commentedon Aug 10, 2021
At least from the comments (that were not changed in #52827) it looks like if either
blockorbbNexthad zero weight, we would makeblockas rarely used, but with your change, that logic got flipped and we are now markingblockas being used more frequently.AndyAyersMS commentedon Aug 10, 2021
In this method there's are a mixuture of blocks with and without PGO data. The diff is that the new logic marks some merged blocks as having IBC, where the old logic did not.
Flow graph is identical before these merges. Here's a sample merge: the
bNextblockBB05has PGO data, but since the count exactly matches the count inBB04, the old logic does not markBB04has as having PGO, while the new logic does...The general problem of having a method with mixtures of PGO and non PGO method blocks (from inlining, typically) is something we need to work on in .NET 7.
We could revert this bit of the change but I suspect it would cause regressions elsewhere. So I recommend we leave NET 6 alone and work on this down the road.
AndyAyersMS commentedon Aug 10, 2021
One last note -- the reason marking a block has having PGO (
IBC) is so impactful is that it prevents the simple non-PGO based weight updates when we recognize loops. So later on we end up with this odd weight assignment:and so we end up spilling in a hot block. Logic for this weight update is here:
runtime/src/coreclr/jit/optimizer.cpp
Lines 225 to 237 in d01dae4
The general fix for this is to treat PGO and non-PGO weights on an even footing, but that requires earlier and more sensible assignments of non-PGO weights.
kunalspathak commentedon Aug 10, 2021
Makes sense to me.
AndyAyersMS commentedon Nov 1, 2022
Looking at this afresh. For the first test, we were at around 560 when the regression happened:
Now we're at 520 and have been there a while:

Other tests here look to be similarly improved or at least back to par. So am going to close this.