Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ios] Investigate stripping EntryPoint strings from assemblies as a size optimization for Mono iOS applications #21732

Open
ivanpovazan opened this issue Dec 1, 2024 · 1 comment
Labels
app-size enhancement The issue or pull request is an enhancement
Milestone

Comments

@ivanpovazan
Copy link
Contributor

ivanpovazan commented Dec 1, 2024

Description

In .NET 9 we enabled managed-static registrar to be the default setting when targeting iOS platforms with Mono.
This change regressed MAUI sample application size when targeting iOS by ~2-3% as reported in: #20174
The reason for the regression is generating more managed code which needs to be AOT-compiled.

During some investigation I noticed that after we run ILStrip (Mono's size-optimization task which removes unneeded IL code from assemblies which are preserved mostly for metadata information and reflection support) we keep UnmanagedCallersOnly attributes data on methods which are generated for the new registrar, for example:

.class auto ansi sealed nested assembly __Registrar_Callbacks__
         extends [System.Private.CoreLib]System.Object
  {
    .method public hidebysig static valuetype [Microsoft.iOS]ObjCRuntime.NativeHandle 
            callback_0_Eone_AppDelegate_get_Window(native int pobj,
                                                   native int sel,
                                                   native int* exception_gchandle) cil managed noinlining
    {
      .custom instance void [System.Private.CoreLib]System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute::.ctor() = ( 01 00 01 00 53 0E 0A 45 6E 74 72 79 50 6F 69 6E   // ....S..EntryPoin
                                                                                                                              74 26 63 61 6C 6C 62 61 63 6B 5F 30 5F 45 6F 6E   // t&callback_0_Eon
                                                                                                                              65 5F 41 70 70 44 65 6C 65 67 61 74 65 5F 67 65   // e_AppDelegate_ge
                                                                                                                              74 5F 57 69 6E 64 6F 77 )                         // t_Window
      // Code size       1 (0x1)
      .maxstack  8
      IL_0000:  ret
    } // end of method __Registrar_Callbacks__::callback_0_Eone_AppDelegate_get_Window
...

Here we can see a size-saving opportunity, specifically in regard to EntryPoint values on UCO methods which are not needed or used during runtime.

SIze-saving

By creating a simple Mono.Cecil task which strips out only custom attributes from methods defined on __Registrar_Callbacks__ types from stripped assemblies of the app, it has been estimated that with a dotnet new maui app and .NET 9 GA SDK we could save ~2% of the application size when using Mono with this approach.

NOTE: The save saving is currently applicable only to Mono, as with Native AOT we do not need/keep managed assemblies in the application bundle.

Comparing managed-static registrar without and with UCO EntryPoint stripping with .NET 9 GA

dotnet new maui managed-static managed-static w stripped UCOs diff (%)
SOD (MB) 44,08 43,04 -2,36%
.ipa (MB) 15,45 15,07 -2,46%

Comparing static with managed-static registrar and UCO EntryPoint stripping with .NET 9 GA

Such an improvement would make the app sizes between the new managed-static and the old static registrar almost identical.

dotnet new maui static managed-static w stripped UCOs diff (%)
SOD (MB) 42,87 43,04 0,39%
.ipa (MB) 15,14 15,07 -0,47%

Proposal

Investigate adapting https://github.com/dotnet/runtime/tree/e7d837da5b1aacd9325a8b8f2214cfaf4d3f0ff6/src/tasks/MonoTargetsTasks/ILStrip/AssemblyStripper
so that it strips out EntryPoint values on UCO methods introduced for managed-static registrar and measure the actual size saving.

@ivanpovazan ivanpovazan added the enhancement The issue or pull request is an enhancement label Dec 1, 2024
@ivanpovazan ivanpovazan added this to the .NET 10 milestone Dec 1, 2024
@ivanpovazan
Copy link
Contributor Author

/cc: @rolfbjarne @vitek-karas

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
app-size enhancement The issue or pull request is an enhancement
Projects
None yet
Development

No branches or pull requests

2 participants