Closed mikebattista closed 1 month ago
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).
cswinrt link - https://github.com/microsoft/CsWinRT/issues/373
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.
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.
@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.
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.
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 tried enabling trimming and now my app crashes on launch.
@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?
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.
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.
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...
How come trimming is not supported for framework-dependent deploys. A simple app produces lots of dlls that not half of it is used:
@mikebattista @codendone since https://github.com/microsoft/CsWinRT/issues/373 is closed, should this issue be closed too?
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:
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 thePublish...
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 supportdotnet publish
and thePublish...
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