Uh oh!
There was an error while loading. Please reload this page.
Improve EqualityComparer for NativeAOT - #83054
Conversation
ghost
commented
Mar 7, 2023
Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas Issue DetailsCloses #81592 staticboolTest(inta,intb)=>EqualityComparer<int>.Default.Equals(a,b);Old codegen on NativeAOT: ; Method Program:Bar[int](int,int):bool57pushrdi56pushrsi 4883EC28 subrsp,40 8BF1 movesi,ecx 8BFA movedi,edx 488B0500000000 movrax, qword ptr [(reloc 0x4000000000425988)]4883780800cmp gword ptr [rax+08H],07505jne SHORT G_M49161_IG04 E800000000 call System.Collections.Generic.EqualityComparer`1[int]:Create()G_M49161_IG04: 33C0 xoreax,eax 3BF7 cmpesi,edi 0F94C0 sete al 4883C428 addrsp,40 5E poprsi 5F poprdi C3 ret; Total bytes of code: 43New codegen: ; Method Program:Bar[int](int,int):bool 33C0 xoreax,eax 3BCA cmpecx,edx 0F94C0 sete al C3 ret; Total bytes of code: 8cc @dotnet/ilc-contrib @MichalStrehovsky
|
EgorBo
commented
Mar 7, 2023
More complicated example involving generics: usingSystem.Collections.Generic;usingSystem.Runtime.CompilerServices;classProgram{staticvoidMain(){Foo(1,2);Foo("1","2");}[MethodImpl(MethodImplOptions.NoInlining)]staticboolFoo<T>(Ta,Tb)=>Bar(a,b);[MethodImpl(MethodImplOptions.NoInlining)]staticboolBar<T>(Ta,Tb)=>EqualityComparer<T>.Default.Equals(a,b);}codegen diff: https://www.diffchecker.com/MyttN9cW/ |
If a type is preinitialized, we shouldn't need the cctor pointer anymore. This was the only thing keeping around general-purpose comparers logic after @EgorBo's dotnet#83054.
eerhardt
commented
Mar 7, 2023
It looks like this caused a ~50KB size on disk regression on the BasicMinimalApi app on linux-x64. The regression happened in this commit range. Doing an analysis of the .mstat files before and after, I see most of the size increase in And then dumping the difference in that namespace, the biggest chunk that stands out: (note there are many more ObjectComparers on the right, these are just a snippet of them. There are also new Attached are the mstat files and dumping them to txt. |
agocke
commented
Mar 7, 2023
Is it possible that #83063 will bring things back into alignment? |
eerhardt
commented
Mar 7, 2023
Unfortunately, no. Note that both this commit and that commit are in the above commit range. So the 50KB regression is after both changes. |
eerhardt
commented
Mar 7, 2023
Also note that the regression on win-x64 seems to be smaller. More like ~20KB. |
EgorBo
commented
Mar 7, 2023
@MichalStrehovsky any ideas what we can do here to avoid type loading in runtime? if not - can we somehow do lazy init only for non-value type instanciations? |
MichalStrehovsky
commented
Mar 8, 2023
I looked at this in a bit more detail. Previously, comparer types for reference type T were always loaded lazily - we generated the code for "any reference type", and at runtime we would land here where we essentially MakeGenericType the right comparer: With the change in this PR, comparers are preinitialized at compile time (we actually preallocate the object instance). It is a compromise. Doing things lazily helps size, but impacts startup. For the BasicWebApi sample, we were previously loading 3 comparers at startup and another 4 on first request. So we avoid 7 type loads. The 7 type loads cost about 0.2 ms in startup time in total. So we're basically looking at <0.5% size regression for <0.5% startup improvement. If it was more than 0.5% I would be more concerned but maybe this is an acceptable tradeoff? |
eerhardt
commented
Mar 8, 2023
Yeah, it sounds like it. I just wanted to raise the size regression here just to see if there was anything we could do. But since this is so small, if there isn't anything trivial/obvious we can just live with it. |
MichalPetryka
commented
Mar 8, 2023
Can this be removed now? runtime/src/libraries/System.Private.CoreLib/src/System/Array.cs Lines 1366 to 1370 in 0e1ede5 |
MichalStrehovsky
commented
Mar 8, 2023
It would likely bring a lot more comparers for no clear benefit. |


Closes#81592
Old codegen on NativeAOT:
New codegen:
cc @dotnet/ilc-contrib @MichalStrehovsky