Repository navigation
[Perf] Regressions in Integer Formatting #54166
Copy link
Copy link
Closed
Labels
arch-arm64area-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 | arm64 |
|---|---|
| OS | Windows 10.0.19041 |
| Baseline | 4c7f4ee74d7a9e5bcc73b552dd020df02b039c8a |
| Compare | 8fb2eb53f75971ce492f14bebb93ed7a236bcd6e |
| Diff | Diff |
Regressions in System.Tests.Perf_Int32
| Benchmark | Baseline | Test | Test/Base | Test Quality | Baseline IR | Compare IR | IR Ratio | Baseline ETL | Compare ETL |
|---|---|---|---|---|---|---|---|---|---|
| ToString - Duration of single invocation | 24.70 ns | 34.44 ns | 1.39 | 0.21 | |||||
| TryFormat - Duration of single invocation | 19.39 ns | 21.12 ns | 1.09 | 0.17 |
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.Tests.Perf_Int32*'Details
Payloads
Histogram
System.Tests.Perf_Int32.ToString(value: 2147483647)
System.Tests.Perf_Int32.TryFormat(value: 2147483647)
Docs
Profiling workflow for dotnet/runtime repository
Benchmarking workflow for dotnet/runtime repository
Run Information
| Architecture | arm64 |
|---|---|
| OS | Windows 10.0.19041 |
| Baseline | 4c7f4ee74d7a9e5bcc73b552dd020df02b039c8a |
| Compare | 8fb2eb53f75971ce492f14bebb93ed7a236bcd6e |
| Diff | Diff |
Regressions in System.Tests.Perf_UInt64
| Benchmark | Baseline | Test | Test/Base | Test Quality | Baseline IR | Compare IR | IR Ratio | Baseline ETL | Compare ETL |
|---|---|---|---|---|---|---|---|---|---|
| TryFormat - Duration of single invocation | 10.78 ns | 12.11 ns | 1.12 | 0.13 |
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.Tests.Perf_UInt64*'Details
Payloads
Histogram
System.Tests.Perf_UInt64.TryFormat(value: 12345)
Docs
Profiling workflow for dotnet/runtime repository
Benchmarking workflow for dotnet/runtime repository
Run Information
| Architecture | arm64 |
|---|---|
| OS | Windows 10.0.19041 |
| Baseline | 4c7f4ee74d7a9e5bcc73b552dd020df02b039c8a |
| Compare | 8fb2eb53f75971ce492f14bebb93ed7a236bcd6e |
| Diff | Diff |
Regressions in System.Tests.Perf_Version
| Benchmark | Baseline | Test | Test/Base | Test Quality | Baseline IR | Compare IR | IR Ratio | Baseline ETL | Compare ETL |
|---|---|---|---|---|---|---|---|---|---|
| TryFormatL - Duration of single invocation | 96.02 ns | 103.50 ns | 1.08 | 0.15 |
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.Tests.Perf_Version*'Details
Payloads
Histogram
System.Tests.Perf_Version.TryFormatL
Docs
Profiling workflow for dotnet/runtime repository
Benchmarking workflow for dotnet/runtime repository
Run Information
| Architecture | arm64 |
|---|---|
| OS | Windows 10.0.19041 |
| Baseline | 28e63279342bd2f6ca43442d864f487613a53bc9 |
| Compare | d49bcbe0441f5c954cddcbe28a222eb34917bcaf |
| Diff | Diff |
Regressions in System.Tests.Perf_UInt32
| Benchmark | Baseline | Test | Test/Base | Test Quality | Baseline IR | Compare IR | IR Ratio | Baseline ETL | Compare ETL |
|---|---|---|---|---|---|---|---|---|---|
| ToString - Duration of single invocation | 22.92 ns | 25.28 ns | 1.10 | 0.24 | |||||
| TryFormat - Duration of single invocation | 17.54 ns | 20.77 ns | 1.18 | 0.01 |
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.Tests.Perf_UInt32*'Details
Payloads
Histogram
System.Tests.Perf_UInt32.ToString(value: 4294967295)
System.Tests.Perf_UInt32.TryFormat(value: 4294967295)
Docs
Profiling workflow for dotnet/runtime repository
Benchmarking workflow for dotnet/runtime repository
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
arch-arm64area-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/18/2021 5:35:47 PM[/-][+][Perf] Regressions in Integer Formatting[/+]danmoseley commentedon Aug 10, 2021
@tannergooding looking at the list of changes, fdbef6c popped out, but Dragon doesn't do much actual division does it?
#52893
tannergooding commentedon Aug 10, 2021
Dragon is for floating-point. Integer formatting frequently divides by 10: https://source.dot.net/#System.Private.CoreLib/Number.Formatting.cs,c66436177df5dc9b
stephentoub commentedon Aug 10, 2021
cc: @pentp
pentp commentedon Aug 11, 2021
I don't have an arm64 machine to do perf tests, so I'm trying to get some assembly diffs, but I can't get
jit-dasmto work with anything I try. From a clean repo I built the following stuff:I then tried to get dasm output:
I also tried with -j option and it complains about the file being in use (by itself probably, nothing else has it open):
I then tried to manually copy the clrjit.dll files and run with --nocopy:
I've clearly misunderstood how these utilities work. Can they even be used to get arm64 asm dumps on win-x64 or is there a better/easier way?
13 remaining items
AndyAyersMS commentedon Aug 12, 2021
Marking as 6.0 at least until we've better understood what's going on.
tannergooding commentedon Aug 12, 2021
I wonder if its partially due to certain operations, such as integer division, being significantly more expensive on x86/x64 (as you only have
divwhich computes the remainder as well).On A64, the benefits of avoiding
divare lessened and some of the algorithms that avoiddivmight expect you can have things likeleainstead.EgorBo commentedon Aug 12, 2021
@AndyAyersMS can it also be PGO related? dc7598e
pentp commentedon Aug 12, 2021
So I managed to finally generate a diff: https://www.diffchecker.com/Rr7cRI2V
I suspect the slowdown comes from using
mul Xd, Xn, Xminstead ofumull Xd, Wn, Wm?Edit: ARM software optimization guides seem to indicate that
mulandumullhave identical latencies/throughput.umulhis more expensive, but it's only used once and it should still be faster than a bunch oflsr/sub/addinstructions...AndyAyersMS commentedon Aug 12, 2021
I think these are running on Surface Pro X machines, which are A76 (big).
@echesakov can you ask the Arm folks to take a look and see if they have any ideas?
echesakov commentedon Aug 12, 2021
@TamarChristinaArm Do you think you or someone on your team would be able to help us with the issue?
TamarChristinaArm commentedon Aug 13, 2021
Sure thing!, taking a look.
TamarChristinaArm commentedon Aug 13, 2021
I think this is correct culprid, the loop has a long dependency chain off the value out of the
mul/umullwith little independent instructions so it's bound by these two and64-bit mulhas twice the latency ofumull.64-bit mulhas a latency of4(3)andumullhas2(1)on Cortex-A76. Were you perhaps comparing the AArch32 instructions? Note that on AArch64mulandumullaren't real instructions but are architectural aliases formaddandumaddlrespectively so you need to look at the latencies for those.The
mulseems to be unneeded though, both inputs are 32-bits so you should be able to just useumullthere as before.TamarChristinaArm commentedon Aug 16, 2021
As a side note, while looking at the diff I noticed some other general improvements that could be made in the future:
can become
and
can become
lastly
can become
and probably want to move the constant out of the loop.