-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Description
Note: I don't know whether the root cause of my issue is related with #36907 so I report an easily reproducible scenario here.
I have a high performance core library, which has some multidimensional span-like types such as Array2D and Array3D structs, which are affected by the performance degradation: accessing elements of these types are faster on .NET Core 3 than accessing elements of a regular multidimensional array but not when executing on .NET 5.
Reproduction:
- Fork or download this repository
- The library targets a bunch of target frameworks. To observe the degradation it is enough to target .NET Core 3.x and .NET 5.0 only.
- From the
KGySoft.CoreLibraries.PerformanceTestproject execute the Array2DPerformanceTest.AccessTest against both .NET Core 3 and .NET 5 - Observe the results in the console output
Online living version: I created also an online example. As per 11/10/2020 this executes the performance test on .NET Core 3.1 (this is a somewhat shortened test in order not to timeout). Targeting .NET 5 is not possible on .NET Fiddle yet.
Configuration
- dotnet --version: 5.0.100-rc.2.20479.15
- Windows 10 [Version 10.0.19042.572] 64 bit version
Regression?
The regression can be observed between .NET Core 3.0/3.1 and .NET 5.0
Data
- .NET Core 3.0 results on my machine:
==[AccessTest (.NET Core 3.0.0) Results]================================================
Iterations: 10,000
Warming up: Yes
Test cases: 3
Repeats: 5
Calling GC.Collect: Yes
Forced CPU Affinity: 2
Cases are sorted by time (quickest first)
--------------------------------------------------
1. int[y][x] = value: average time: 389.46 ms
#1 389.59 ms
#2 389.14 ms
#3 388.61 ms <---- Best
#4 389.39 ms
#5 390.58 ms <---- Worst
Worst-Best difference: 1,98 ms (0,51%)
2. Array2D<int>[y, x] = value: average time: 642.20 ms (+252.74 ms / 164.89%)
#1 641.34 ms
#2 642.98 ms
#3 642.63 ms
#4 643.43 ms <---- Worst
#5 640.61 ms <---- Best
Worst-Best difference: 2.83 ms (0.44%)
3. int[y, x] = value: average time: 701.46 ms (+312.00 ms / 180.11%)
#1 702.69 ms
#2 704.56 ms <---- Worst
#3 700.29 ms
#4 701.06 ms
#5 698.72 ms <---- Best
Worst-Best difference: 5.84 ms (0.84%)
- .NET 5.0 RC2 results on my machine:
TheArray2Dcase has a 33% performance degradation (860 ms vs. 642 ms) while the regular 2D array and jagged array performance did not change essentially.
==[AccessTest (.NET Core 5.0.0-rc.2.20475.5) Results]================================================
Iterations: 10,000
Warming up: Yes
Test cases: 3
Repeats: 5
Calling GC.Collect: Yes
Forced CPU Affinity: 2
Cases are sorted by time (quickest first)
--------------------------------------------------
1. int[y][x] = value: average time: 395.04 ms
#1 395.01 ms
#2 393.34 ms <---- Best
#3 397.91 ms <---- Worst
#4 394.28 ms
#5 394.68 ms
Worst-Best difference: 4.57 ms (1.16%)
2. int[y, x] = value: average time: 704.27 ms (+309.23 ms / 178.28%)
#1 702.28 ms
#2 702.97 ms
#3 703.96 ms
#4 700.14 ms <---- Best
#5 712.02 ms <---- Worst
Worst-Best difference: 11.89 ms (1.70%)
3. Array2D<int>[y, x] = value: average time: 860.47 ms (+465.42 ms / 217.82%)
#1 848.51 ms <---- Best
#2 870.71 ms <---- Worst
#3 853.88 ms
#4 866.94 ms
#5 862.30 ms
Worst-Best difference: 22.20 ms (2.62%)
- .NET Core 3.1 online results (.NET Fiddle): https://dotnetfiddle.net/02BdPF
Note: This test is reduced (both in time and cases) in order not to timeout .NET Fiddle. As it is not possible to run .NET 5 codes online yet it is only good for demonstrating thatArray2Daccess is faster than regular 2D array access.
Analysis
I'm not sure whether I could identify the hot-spot correctly but since Array2D uses ArraySection internally, and I could not observe any significant performance degradation in ArraySection performance test (feel free to set Repeat = 5 to get more reliable results just like above) I suspect that the issue lies in accessing the wrapped ArraySection struct inside the Array2D struct here. However, I could not find any suspicious in the IL code, and I could not check the JITted machine code of the .NET 5 version.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status