dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.37k stars 4.75k forks source link

NativeAOT codegeneration question #82023

Closed kant2002 closed 1 year ago

kant2002 commented 1 year ago

I trying to analyze small MVC web app compiled using NativeAOT. It has only like 2 forms, one list and second edit/add items and it has size of 100MB. Data access using ef core. I have no complaint about size because know that ASP.net core and EF Core not yet ready.

but I see other unknown to me things.

I analyse MSTAT file and specifically look at System.Private.CompilerGenerated pseudo-assembly methods, where I see following lines which seems to be duplicates.

!0 Boxed_Enumerator<System.__Canon>::get_Current_Unbox()      39
!0 Boxed_Enumerator<System.__Canon>::get_Current_Unbox()      39
!0 Boxed_Enumerator<System.__Canon>::get_Current_Unbox()      39
...... skipped ....
!0 Boxed_Enumerator<System.__Canon>::get_Current_Unbox()      39

Also interesting that sometimes these duplicates has different sizes

System.Boolean Boxed_Enumerator<Microsoft.Identity.Json.Utilities.StructMultiKey`2<System.__Canon,System.__Canon>>::MoveNext_Unbox()      39
System.Boolean Boxed_Enumerator<Microsoft.Identity.Json.Utilities.StructMultiKey`2<System.__Canon,System.__Canon>>::MoveNext_Unbox()      15
System.Boolean Boxed_Enumerator<Microsoft.Identity.Json.Utilities.StructMultiKey`2<System.__Canon,System.__Canon>>::MoveNext_Unbox()      15
System.Boolean Boxed_Enumerator<Microsoft.Identity.Json.Utilities.StructMultiKey`2<System.__Canon,System.__Canon>>::MoveNext_Unbox()      39

which is puzzling.

Also a lot of code coming from the System.Private.CompilerGenerated in general, it's second item(8.3Mb) after S.P.CoreLib(14.8Mb) which is 15% of all methods size (53.9Mb). Is this expected?

Most of the code here seems to be Unboxing like above and also DynamicInvoke calls. Isn't this code good candidate for folding?

dotnet-issue-labeler[bot] commented 1 year ago

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

MichalStrehovsky commented 1 year ago

where I see following lines which seems to be duplicates.

Enumerator is usually a nested type on various containers. Looks like the tool you used to generate this output from MSTAT doesn't show nested types properly (the containing type is missing).

Most of the code here seems to be Unboxing like above and also DynamicInvoke calls. Isn't this code good candidate for folding

What's the <TrimMode> you're using? ASP.NET defaults TrimMode to partial. This makes the whole world visible to reflection and reflection invocable. This means a lot of dynamic invoke stubs.

ghost commented 1 year ago

Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas See info in area-owners.md if you want to be subscribed.

Issue Details
I trying to analyze small MVC web app compiled using NativeAOT. It has only like 2 forms, one list and second edit/add items and it has size of 100MB. Data access using ef core. I have no complaint about size because know that ASP.net core and EF Core not yet ready. but I see other unknown to me things. I analyse MSTAT file and specifically look at `System.Private.CompilerGenerated` pseudo-assembly methods, where I see following lines which seems to be duplicates. ``` !0 Boxed_Enumerator::get_Current_Unbox() 39 !0 Boxed_Enumerator::get_Current_Unbox() 39 !0 Boxed_Enumerator::get_Current_Unbox() 39 ...... skipped .... !0 Boxed_Enumerator::get_Current_Unbox() 39 ``` Also interesting that sometimes these duplicates has different sizes ``` System.Boolean Boxed_Enumerator>::MoveNext_Unbox() 39 System.Boolean Boxed_Enumerator>::MoveNext_Unbox() 15 System.Boolean Boxed_Enumerator>::MoveNext_Unbox() 15 System.Boolean Boxed_Enumerator>::MoveNext_Unbox() 39 ``` which is puzzling. Also a lot of code coming from the `System.Private.CompilerGenerated` in general, it's second item(8.3Mb) after `S.P.CoreLib`(14.8Mb) which is 15% of all methods size (53.9Mb). Is this expected? Most of the code here seems to be Unboxing like above and also `DynamicInvoke` calls. Isn't this code good candidate for folding?
Author: kant2002
Assignees: -
Labels: `untriaged`, `area-NativeAOT-coreclr`
Milestone: -
kant2002 commented 1 year ago

Looks like the tool you used to generate this output from MSTAT doesn't show nested types properly (the containing type is missing).

Because I use Cecil either bug is here, os somehow issue in how ILC generates the mstat. Have to replicate on smaller apps.

What's the you're using? I use default TrimMode, so that's probably the reason. so you are saying that DynamicInvocation is some relection-related code?

MichalStrehovsky commented 1 year ago

Because I use Cecil either bug is here, os somehow issue in how ILC generates the mstat. Have to replicate on smaller apps.

I spot checked an MSTAT in ILDASM - I don't see any orphaned Enumerator classes. They all look to be nested.

so you are saying that DynamicInvocation is some relection-related code?

Yes, it's the stub that places arguments from an object[] (used in MethodInfo.Invoke) to the CPU registers/stack that the called method body expects.