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

Support IL trimming #2478

Open
mikebattista opened this issue May 6, 2022 · 13 comments
Open

Support IL trimming #2478

mikebattista opened this issue May 6, 2022 · 13 comments
Assignees
Labels
area-DeveloperTools Issues related to authoring (source and IDL), debugging, HotReload, LiveVisualTree, VS integration feature proposal

Comments

@mikebattista
Copy link

mikebattista commented May 6, 2022

Overview

Apps built with the Windows App SDK should have competitive disk footprint with other frameworks and platforms.

.NET apps that use the Windows App SDK implicitly depend on several large binaries:

  • Microsoft.Windows.SDK.NET.dll which is pulled in when setting the TFM to a Windows-specific version
  • Microsoft.WinUI.dll which represents WinUI 3
  • C#/WinRT projection assemblies
  • .NET runtime binaries when self-contained

This disk footprint is inherited whether you use APIs in these binaries or not, which can inflate even new projects to unreasonable levels relative to other frameworks. The cost is amplified when apps are published ReadyToRun which includes both IL and native code versions of the assemblies.

IL trimming is a feature of .NET that can remove or trim unused code from applications, drastically reducing their disk footprint. This is not supported currently due to gaps in WinUI and C#/WinRT, so apps must pay the full disk footprint cost.

The MAUI team did some analysis with IL trimming and found that their self-contained dotnet new maui template without trimming has an installation size of 111MB, while the same template with trimming has an installation size of only 63MB. ReadyToRun inflates the untrimmed template to 155MB, while ReadyToRun with trimming results in 118MB. When you consider the untrimmed disk footprint will be carried by every MAUI application on Windows, you can see the impact not trimming can have on Windows fundamentals. MAUI also trims on other platforms already, so not trimming is a competitive disadvantage on Windows.

Furthermore, IL trimming is a prerequisite for NativeAOT which is .NET 7's ahead-of-time compilation solution. NativeAOT boosts startup and runtime performance by compiling code ahead-of-time (compared to just-in-time with JIT) and is the expected replacement for .NET Native from UWP. Apps migrating from UWP/.NET Native to .NET 6 JIT have reported 2x degradation in startup performance in some cases. NativeAOT should mitigate those issues.

We should support IL trimming for the disk footprint benefits it brings as well as the runtime performance benefits it would enable via NativeAOT.

Developer Experience

The developer experience for enabling trimming should align with https://docs.microsoft.com/en-us/dotnet/core/deploying/trimming/trim-self-contained. As of WinAppSDK 1.1, we do not yet support dotnet publish or the Publish... dialog, but we do support setting related properties in publish profiles (e.g. SelfContained). The minimum bar is that we support setting <PublishTrimmed>true</PublishTrimmed> in publish profiles. We should also strive to support dotnet publish and the Publish... dialog for a more consistent and flexible developer experience.

The .NET model today requires apps be self-contained to participate in IL trimming. In an ideal world, though, apps could choose to be framework-dependent on .NET while trimming out unused code from other binaries. In terms of .NET runtime libraries, a framework-dependent app will always have a lower disk footprint than a trimmed self-contained app.

Deliverables

@hez2010
Copy link

hez2010 commented May 6, 2022

Note that WinRT.Runtime in CsWinRT heavily relies on reflection to lookup types/ABI types during runtime, which makes it impossible to be trimming compatible. It leads to a huge trimming-incompatible Microsoft.Windows.SDK.NET.dll.

I used to do some investigation in my WinUI 3 app NativeAOT experiment (despite failure). Instead of using the Type.GetType("ABI." + type.FullName) and MakeGenericType stuff, a possible solution is to use an interface to connect the type with its ABI type so all types usage can be statically analyzed during compilation:

interface IWinRTImpl<T> { ... }
class SomeWinRTType : IWinRTImpl<ABI.SomeWinRTType> { ... }

And in my experiment, after NativeAOT the compiler only produced a 9mb single self-contained exe which is very promising (though it failed to run due to some necessary types got trimmed away).

@AdamBraden
Copy link

cswinrt link - microsoft/CsWinRT#373

@BenJKuhn BenJKuhn added feature area-DeveloperTools Issues related to authoring (source and IDL), debugging, HotReload, LiveVisualTree, VS integration and removed needs-triage labels May 19, 2022
@Balkoth
Copy link

Balkoth commented May 25, 2022

I think this is absolutely neccessary, as i have a taken winforms app to winui3 where the size of the resulting binary exploded from 700 Kilobytes to 44 Megabytes.

@kant2002
Copy link

kant2002 commented Jun 1, 2022

I would like that microsoft.windowsappsdk provide small change in buildTransitive\Microsoft.WinUI.AppX.targets to provide escape hatch for these who willing to play with NativeAOT and maybe contribute to CsWinRT
Right now ILtrimming completely blocked, understandbly why. But if change blocking part to

<Target Name="ValidateNoPublishTrimmed" BeforeTargets="PrepareForBuild" 
    Condition="'$(PublishTrimmed)'=='true' and '$(_SuppressILTrimDisabling)' != 'true'">
  <Error Text="Publishing with IL trimming is not yet supported."/>
</Target>

so somebody extremely enthusiastic can try use WinUI in NativeAOT context without hacking MSbuild targets. That's similar to how WinForms and WPF block linking, since they are not ready yet for it.

@dotMorten
Copy link
Contributor

@kant2002 just double-click the error in VS, and it'll take you right to this bit of code inside the nuget, and you can just delete it and save. That would enable you to locally "play" with trimming.

@manodasanW
Copy link
Member

You can also try out WinAppSDK 1.2 preview 2 where that target should have been removed and IL trimming is now supported. Here is a pointer to the release notes that talks about it.

@dotMorten
Copy link
Contributor

Curious if anyone actually got that to work? I’ve been unable to get a trimmed WinUI app published. Lots of trim warnings and ultimately build errors

@JasonWei512
Copy link

I tried enabling trimming and now my app crashes on launch.

@manodasanW
Copy link
Member

manodasanW commented Oct 19, 2022

@dotMorten what are the build errors you are seeing? And what type of trim warnings are you seeing?

@JasonWei512 Have you been able to get a call stack and exception message for where you are seeing a crash or determine which type is causing the crash?

@ocdtrekkie
Copy link

Built a toy MAUI app with three textboxes and SQLite, and it is a whopping 300 MB (127 MB zipped) to set a couple values in a database. Meanwhile, I wrote a whole home automation system with WinForms and .NET Framework which fits in like a 7 MB zip file. I can't imagine MAUI being taken seriously as a development platform on Windows while this is an open issue. Hoping this makes it to stable channel really soon.

@adamplonka
Copy link

adamplonka commented Mar 27, 2023

Curious if anyone actually got that to work? I’ve been unable to get a trimmed WinUI app published. Lots of trim warnings and ultimately build errors

I managed to make it run after some experimenting.
First I set the following project properties:

   <PublishTrimmed>true</PublishTrimmed>
   <TrimMode>partial</TrimMode>

and published the project. It reduced the size of Microsoft.Windows.SDK.NET from 20334KB down to 351KB and Microsoft.WinUI from 6385KB to 1007KB. Then I recompiled the application normally and copied the trimmed files back into framework dependent version, it saved over 25MB from the app size and the application works normally. It's around 68MB self-contained with WindowsAppSDK or 48MB runtime dependent (sample project with DataGrid and settings page using Template Studio).

I couldn't make it run with full TrimMode; tried to play with TrimmerRootAssembly list but nothing works. Also it looks like the compiler doesn't see properly any of the components used in XAML. I guess a code generator could be used to workaround this and statically reference any components used.
Anyway the size of improperly fully trimmed application is 67.2MB (70,503,216 bytes) and after partial trimming it's 67.6 MB (70,885,342 bytes). I guess it's not worth the hassle.
99MB for ready to run single file self-contained x64 (39.8 MB zipped), or 70MB for self-contained single-file x64 without aot (27.8 MB zipped), not so bad.

@tipa
Copy link

tipa commented Oct 15, 2023

It's around 68MB self-contained with WindowsAppSDK or 48MB runtime dependent (sample project with DataGrid and settings page using Template Studio).

99MB for ready to run single file self-contained x64 (39.8 MB zipped), or 70MB for self-contained single-file x64 without aot (27.8 MB zipped), not so bad.

I don't know... A 70 MB "sample project with DataGrid and settings page" doesn't sound that great to me. And the fact that this was only achieved with some hacks makes it even worse. Given there seems to be zero activity on this issue, I will be sticking with UWP for much much longer than I hoped...

@karmeye
Copy link

karmeye commented May 3, 2024

How come trimming is not supported for framework-dependent deploys. A simple app produces lots of dlls that not half of it is used:

Screenshot 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-DeveloperTools Issues related to authoring (source and IDL), debugging, HotReload, LiveVisualTree, VS integration feature proposal
Projects
None yet
Development

No branches or pull requests