You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
.net 11 RC1 iOS and Android app Size is nearly double #134182
We just built and deployed the app locally and noticed a huge increate in the size of the app - the same app now is quite large -it add at least 30mb to it see screenshots - the .net 10 is considerably smaller
Hope the above helps to diagnose the issue .. this is a production app so obviously is not feasible to add as a repo.
thanks
Reproduction Steps
this is a production app so obviously is not feasible to add as a repo.
You can try with ReadyToRun, NativeAOT options to test with size, performance and compatibility, and track related issues at https://github.com/dotnet/android etc.
@huoyaoyuan thanks for your reply - my clients will be not pleased at all!! We are not talking about a few mb - it’s 40 mb increase on both platforms!!
Can I use mono? Is the option still available?
Whenever I heard David Ortinau and all the talks they said something like 10% android and iOS was smaller! I do hope we have the option for mono for this year because it’s not acceptable!!
Will this be investigated? Because this is what people complained in earlier previews and then it was fixed!
@davidortinau can you help? I think this is worth investigating before .NET 11 GA because this appears very similar to a problem that was already identified earlier in the .NET 11 cycle.
In #124212, Microsoft measured the MAUI sample at approximately 50 MB using Mono and 80 MB using CoreCLR — a ~30 MB increase. That issue resulted in several .NET 11 size improvements, including trimming changes, native symbol stripping (~36 MB reduction) and removal of debug libraries from Release builds (~3 MB). The issue was subsequently closed against the .NET 11 milestone.
We are now seeing effectively the same ~30 MB regression again with .NET 11 RC1, and importantly we are seeing it on both iOS and Android with an existing production MAUI application. The application itself has not changed in a way that would account for this increase; the significant variable is the move from .NET 10 to .NET 11/CoreCLR.
This matters because CoreCLR is becoming the default runtime. Even if a ~100 MB application remains within App Store/Google Play limits, an additional ~30 MB is a substantial regression for a mobile application: it affects initial downloads, every application update, mobile-data usage and storage, and becomes more significant for larger real-world applications.
Because the earlier CoreCLR size regression was considered important enough to optimise during the .NET 11 development cycle, I think it would be valuable to confirm whether:
one of those size optimisations is no longer being applied in RC1;
this is an expected remaining CoreCLR/R2R overhead; or
there is a new regression affecting Release MAUI builds.
I cannot provide the production application as a reproduction project, but the consistent increase across both iOS and Android, together with the very similar +30 MB previously identified in #124212, suggests this deserves investigation rather than being treated simply as expected application growth.
Can the mono csproj switch be reinstated for .net 11?
Also is this dotnet/android#12867 waiting approval has any impact on a positive outcome?
Unlikely - you already tried that basically. Simon did an experiment with some runaway generics and found that in that specific case this would help keep the size reasonable while still getting similar perf - so it was motivated by this issue, but unlikely the same root cause.
@TedMobile I was reviewing this and one thing stuck out to me:
I don't see an indication that Mono+AOT was being used in your .NET 10 application.
Are there any (Mono) libaot-*.so files? There should be one per .NET assembly.
So, is it possible you were using Mono (JIT only) and you moved to .NET 11, which is now using ReadyToRun? In theory, the libaot-*.so file size should get shuffled around into libassembly-store.so when you move to .NET 11 (but were there none?). So, disabling ReadyToRun entirely would be a better comparison to .NET 10?
Let me know if I'm on the right track at all, thanks!
Thanks a lot for the command lines - from those it seems that on Android the problem is full R2R actually (even though it's not explicitly enabled). The root is likely that your project uses Microsoft.Maui.Controls version 10.0 which doesn't contain the necessary build changes and data files to enable partial R2R on CoreCLR (it does that only for mono). Could you please try upgrading Microsoft.Maui.Controls (and probably the whole MAUI) to 11.0.0-rc.1.26451.6 (this should be the version which belongs to .NET 11 RC1 release)?
I was able to validate locally that on Android this has a big impact, but it's not clear as noted by Jonathan if your app was using AOT on Android at all - in which case updating MAUI would get you closer, but not fully there since it will do partial AOT, not no-AOT.
For iOS the MAUI update should have an effect but much smaller based on my local testing. So for iOS we would need to check what was the configuration of the app before. Specifically do you set either UseInterpreter or MtouchInterpreter MSBuild properties - ideally check the value of these in the binlog as that should show the effective value used during the build.
@vitek-karas
Hi, we have trying to build/deploy the app using everything .net 11 and we have encountered issues with android packages (dependency hell!!) what used to just work in net 10 , in net 11 android does not longer like packages like Xamarin.play.core ( we used the reviewmanager there ... looking into it..
we do manage to build both ios and android and the appsize and results are identical to before .
I have attached
basically the above is with the 2 properties set to false "MauiEnableFullReadyToRun=false and publishreadytorun=false too ,
so no change at all - we also tried the other flags and they were both 100mb.. no changes there.
there was no interpreter set on iOS.
@jonathanpeppers please see the cs proj extract of what we actually set - and below is an image that shows what we get with net 11 with MauiEnableFullReadyToRun=false and publishreadytorun=false - there no Aot files as we have issues to sort out with AOT.
@TedMobile thanks a lot for providing more data for us. Please bear with me as I have to admit I'm a bit lost in what config was used where... so I'll try to restate how I understand it and please correct me if I got it wrong.
The shared R2R command lines are from the matching csproj extract projects.
Were they collected without setting PublishReadyToRun=false? - if you have binlogs could you check what was the effective value of PublishReadyToRun (I'm pretty sure it had to be true otherwise it would not run the crossgen compiler)
Your .NET 10 project for Android (the baseline) has RunAOTCompilation=false in it. Could you confirm this please?
The picture of the size of the APK is from a .NET 11 Android project which specified PublishReadyToRun=false. If I read this correctly it shows size close to the baseline 61MB of final package size. If your baseline disabled all AOT on Android, then disabling it on CoreCLR should produce similar size (probably slightly larger, but only by a couple of MBs).
I have to admit I don't know what is the situation on iOS - the original issue description states that .NET 11 adds 30 MB to the app size - is that the packaged ipa? I think you said that if you disable R2R the .NET 11 size goes back to something similar to .NET 10, right? What I'm not clear on is what was the AOT configuration for the .NET 10 project.
Could you please help us confirm the AOT configuration of your original .NET 10 iOS build?
Collect a binlog from a clean Release device build (ios-arm64), using your original settings, and share these small extracts:
In MSBuild Structured Log Viewer, search for UseInterpreter and MtouchInterpreter. What is their effective values, or they're not set at all?
Search for $task AOTCompile and select AOTCompile under _AOTCompile. Under Parameters → Assemblies, could you copy the Arguments and ProcessArguments entries for your main application assembly and System.Private.CoreLib.dll? If your main assembly is not listed, please let us know.
Side note: RunAOTCompilation has no effect on .NET 11 (CoreCLR). Similar property to that in CoreCLR is PublishReadyToRun.
Out of curiosity (if it's not too much trouble): You seem to hint that the original .NET 11 setup (with 10.0 MAUI) and the new setup (with 11.0 MAUI) produce basically the same app size on Android. Is that correct? (The original one showed full R2R, the new one shows partial R2R in the command line). I also assume they were done with R2R enabled.
@vitek-karas
My colleague who made the pipeline changes and carried out a number of the tests with the different flags is off this week, but let me try to summarise exactly what we did and hopefully remove some of the confusion.
.NET 11 + MAUI 10
Our initial migration was to the .NET 11 SDK/runtime, but we subsequently realised that we were still using the MAUI 10 workload.
These were the results from that configuration ( both net 11 + Maui 10 or Maui 11 ) have the same result!.
This is where we first noticed the significant package-size increase. Disabling R2R brought the packages back close to the sizes we were accustomed to before the migration.
.NET 11 + MAUI 11
Once we realised that we were still using the MAUI 10 workload, we upgraded to the proper MAUI 11 workload and controls and repeated the testing. We saw the same package-size behaviour: with R2R enabled the packages were significantly larger, while disabling R2R brought them back close to the previous sizes.
I will provide the equivalent MAUI 11 numbers/configuration separately so that we have a clean comparison.
Android
For clarity, all of our Android projects, both .NET 10 and .NET 11, have been built with: <RunAOTCompilation>false</RunAOTCompilation>
We have some existing Android AOT issues to resolve before we can enable it.
iOS
For both our .NET 10 and .NET 11 iOS Release builds, we are not using the interpreter.
We haven't explicitly selected an iOS AOT configuration in the project; we have relied on the normal iOS Release/toolchain defaults. Our Release configuration also has:
Let me see if I can reproduce what he did and extract the remaining information from the binlogs.
In particular, I will try to provide the requested .NET 10 iOS Release AOTCompile details:
Arguments / ProcessArguments for our main application assembly
Arguments / ProcessArguments for System.Private.CoreLib.dll
I will also confirm the effective PublishReadyToRun value for the relevant R2R-enabled build.
Hopefully this clarifies the configurations and which results came from which setup
Thanks a lot for the information. On the Android side the RunAOTCompilation=false basically explains the behavior. .NET 11 doesn't react to that property (intentional breaking change on our end - maybe we should produce a warning or error though to guide people to the right place) - it will use R2R AOT by default and that's almost certainly why the app is larger. If you disable that via PublishReadyToRun=false it seems to get the app close to the .NET 10 size numbers.
For iOS I don't have an explanation yet unfortunately - hopefully the arguments for the AOT compiler will help us there.
@vitek-karas, did you note that the linker command has -a "System.Text.Json" All and -a "System.Net.Http" All, which is causing at the very least all of the following to be rooted/kept:
So post trimming this also pulls in System.Net.Quic, System.Net.Security, System.Net.Sockets, System.Diagnostics.DiagnosticSource, etc. Which look to add up to around 14.7MB of combined cost for R2R codegen
It also looks to cause it to ignore switches like Http3Support=false and we don't seem to have a way to balance those concepts here (allow rooting something that is generally used, but also trim out specific aspects that are explicitly unused)
The new data shows .NET 10 at 117 MB and .NET 11 (with MAUI 11 and all other settings at their defaults) at 103 MB. This is, in fact, a small improvement.
Disabling R2R brings the size down considerably, to 77 MB. Again, I would not recommend this, as I expect a very significant impact on performance in general, not just startup.
There is no clear resolution for iOS, though, as some earlier comments also reported a ~30 MB regression on iOS, which is not shown in the latest data.
The logs you shared from the iOS AOT invocation on .NET 10 confirm the expected default behavior: a full LLVM AOT configuration. However, we can't fully confirm this, as the data only shows it explicitly for CoreLib.
If I rely on the newly reported data, I would consider this resolved for iOS as well.
Please do let me know if you have different observations or if any of the new behavior is unexpected for your application.
Rooting of JSON and HTTP assemblies
@tannergooding, thanks a lot for pointing that out. I didn't notice it. It's definitely an interesting observation, and it likely affects the size of the application on both platforms.
@TedMobile, we don't have enough data to tell why the System.Text.Json and System.Net.Http assemblies are fully rooted.
Typically this is done by specifying TrimmerRootAssembly items in your project file, but there are other ways as well.
This could be intentional, to work around problems with the partial trimming setup used by MAUI apps. If it's not, though, it might be a nice opportunity to reduce the size of the application.
If this was intentional, we would be very interested in the types of problems you ran into that motivated these workarounds. We would very much like to improve this going forward.
Could you search your project and shared/imported .props or .targets files for these assembly names and share any entries that preserve them, particularly TrimmerRootAssembly entries? You could also search the binlog for TrimmerRootAssembly; even knowing that it was set would help us diagnose this further.
Could you check whether the same assemblies are explicitly preserved in both the original .NET 10 Android baseline and the current .NET 11 / MAUI 11 Android build? In the binlog, the ILLink task's Parameters → RootAssemblyNames contains the effective list, including any RootMode metadata. It would also help to know whether you use equivalent preservation rules on iOS.
This would help us understand whether these roots were added intentionally by the project configuration or somehow slipped in during the upgrade.
Android
I agree its solved! we have removed all the flags and with only a few mbs difference - its a win!
iOS
in net .10 we had the interpreter on because we were getting errors very difficult to debug! and our size was 77 - now it works in .net 11 but we gain 30mb but removing the interpreter. I wish it was less - but it is what it is I guess. I will have some explaining to do when our clients will see the app size a bigger.
TrimmerRootAssembly
thanks to @tannergooding for spotting it ! yes we have those in our csproj!
the reason we added the above was because we removed nuewtonsoft and fully replaced with System.Text.Json. however when the app was released it was crashing without telling us much what was going on and what the "culprit" was so we added the above! - given the gain we could make in reducing the size I.E 15/17 mb may be we are going to investigate it again , and any tips/tricks what to look for would be good.. binlog is a bit cryptic at times but may be any suggestion could help..
PublishReadyToRun/MauiEnableFullReadyToRun
As you suggested , we have decided to fully remove them! , however I have to say we noticed the start up being snappier for sure, but not yet everywhere else, but it does make the app bigger though!.. but lets see.
thanks alot in taking the time, and we learned a lot about all these new flags.. I do wish though mono enabled could have been a fallback for .net 11 only though.
For the iOS I just want to clarify for my benefit: So you set either MtouchInterpreter=all or UseInterpreter=true in the .NET 10 project? The AOT invocation you shared about doesn't seem to be for a build where interpreter is enabled on everything.
Regardless - if your app had AOT really disabled then we don't have a corresponding configuration on .NET 11 - the closest is PublishReadyToRun=false which might work, we just don't really test it and thus you might run into problems. Also the pure-interpreter execution is likely slower on .NET 11 than it was on .NET 10 (AOT is on the other hand faster).
Trimming
The best approach is to enable trim warnings, the compiler will tell you all the places in your code which do problematic reflection (or other patterns). But it works the opposite direction, it will likely point to places which try to do something problematic, it doesn't tell you if this touches code inside the two assemblies. But it might still be helpful to at least know which areas of your code might be the cause of the problems. https://learn.microsoft.com/en-us/dotnet/maui/ios/linking#suppress-analysis-warnings - you want to enable it (MAUI disables this by default).
Full R2R
It is expected that full R2R will speed up startup if you have some meaningful amount of code running during startup. For the rest of the app this is a bit more difficult to measure and the difference might not be observable.
Mono
I do wish though mono enabled could have been a fallback for .net 11 only though.
I understand the concern here, I'm just curious where the real need comes from. My reasoning is that you can stay on .NET 10 for a while still. And even it was possible, it would just delay the change by 1 year... I'm honestly curious what is the aspect which makes it compelling (I can only theorize, you know the reality).
@vitek-karas iOS
in net 10 we used only Interpreter true (as we were getting some errors we could not clear) all good in .net 11
Trimming
Giving a go now - would be nice if we managed at our end to remove those!
Mono
It was more of a safety net - but now that I know more - its fine I guess. We always move to latest avail version of .net as even though .net 10 is supported the maui team is very small and they will concentrate on .net 11 for bugs etc and only fix critical .net 10 once 11 is out.
we are going AOT all the way.. just the iOS bump in size is a bummer...
we are going AOT all the way.. just the iOS bump in size is a bummer...
If I understand it correctly on .NET 10 you were not using AOT on iOS. Unfortunately we don't really have an option to not have it in .NET 11.
On a similar train of thought - have you considered NativeAOT - it has hard trimming and compat requirements, but it will make your app significantly smaller (and faster). But I don't know your dependencies, it might be very difficult to make it work.
Activity
huoyaoyuan commentedon Sep 19, 2026
It's somehow expected because the implementation switched from Mono to CoreCLR (https://devblogs.microsoft.com/dotnet/dotnet-maui-moves-to-coreclr-in-dotnet-11/ https://devblogs.microsoft.com/dotnet/coreclr-progress-and-mono-timeline-dotnet-maui/).
You can try with ReadyToRun, NativeAOT options to test with size, performance and compatibility, and track related issues at https://github.com/dotnet/android etc.
TedMobile commentedon Sep 19, 2026
@huoyaoyuan thanks for your reply - my clients will be not pleased at all!! We are not talking about a few mb - it’s 40 mb increase on both platforms!!
Can I use mono? Is the option still available?
Whenever I heard David Ortinau and all the talks they said something like 10% android and iOS was smaller! I do hope we have the option for mono for this year because it’s not acceptable!!
Will this be investigated? Because this is what people complained in earlier previews and then it was fixed!
Let’s hope it’s a bug
martincostello commentedon Sep 19, 2026
MichalPetryka commentedon Sep 19, 2026
This was removed.
TedMobile commentedon Sep 21, 2026
@davidortinau can you help? I think this is worth investigating before .NET 11 GA because this appears very similar to a problem that was already identified earlier in the .NET 11 cycle.
In #124212, Microsoft measured the MAUI sample at approximately 50 MB using Mono and 80 MB using CoreCLR — a ~30 MB increase. That issue resulted in several .NET 11 size improvements, including trimming changes, native symbol stripping (~36 MB reduction) and removal of debug libraries from Release builds (~3 MB). The issue was subsequently closed against the .NET 11 milestone.
We are now seeing effectively the same ~30 MB regression again with .NET 11 RC1, and importantly we are seeing it on both iOS and Android with an existing production MAUI application. The application itself has not changed in a way that would account for this increase; the significant variable is the move from .NET 10 to .NET 11/CoreCLR.
This matters because CoreCLR is becoming the default runtime. Even if a ~100 MB application remains within App Store/Google Play limits, an additional ~30 MB is a substantial regression for a mobile application: it affects initial downloads, every application update, mobile-data usage and storage, and becomes more significant for larger real-world applications.
Because the earlier CoreCLR size regression was considered important enough to optimise during the .NET 11 development cycle, I think it would be valuable to confirm whether:
I cannot provide the production application as a reproduction project, but the consistent increase across both iOS and Android, together with the very similar +30 MB previously identified in #124212, suggests this deserves investigation rather than being treated simply as expected application growth.
Can the mono csproj switch be reinstated for .net 11?
thanks
dotnet-policy-service commentedon Sep 21, 2026
Tagging subscribers to 'os-ios': @vitek-karas, @kotlarmilos, @steveisok, @akoeplinger
See info in area-owners.md if you want to be subscribed.
dotnet-policy-service commentedon Sep 21, 2026
Tagging subscribers to 'arch-android': @vitek-karas, @simonrozsival, @steveisok, @akoeplinger
See info in area-owners.md if you want to be subscribed.
16 remaining items
vitek-karas commentedon Sep 23, 2026
Unlikely - you already tried that basically. Simon did an experiment with some runaway generics and found that in that specific case this would help keep the size reasonable while still getting similar perf - so it was motivated by this issue, but unlikely the same root cause.
jonathanpeppers commentedon Sep 23, 2026
@TedMobile I was reviewing this and one thing stuck out to me:
libaot-*.sofiles? There should be one per .NET assembly.So, is it possible you were using Mono (JIT only) and you moved to .NET 11, which is now using ReadyToRun? In theory, the
libaot-*.sofile size should get shuffled around intolibassembly-store.sowhen you move to .NET 11 (but were there none?). So, disabling ReadyToRun entirely would be a better comparison to .NET 10?Let me know if I'm on the right track at all, thanks!
vitek-karas commentedon Sep 23, 2026
Thanks a lot for the command lines - from those it seems that on Android the problem is full R2R actually (even though it's not explicitly enabled). The root is likely that your project uses Microsoft.Maui.Controls version 10.0 which doesn't contain the necessary build changes and data files to enable partial R2R on CoreCLR (it does that only for mono). Could you please try upgrading Microsoft.Maui.Controls (and probably the whole MAUI) to 11.0.0-rc.1.26451.6 (this should be the version which belongs to .NET 11 RC1 release)?
I was able to validate locally that on Android this has a big impact, but it's not clear as noted by Jonathan if your app was using AOT on Android at all - in which case updating MAUI would get you closer, but not fully there since it will do partial AOT, not no-AOT.
For iOS the MAUI update should have an effect but much smaller based on my local testing. So for iOS we would need to check what was the configuration of the app before. Specifically do you set either
UseInterpreterorMtouchInterpreterMSBuild properties - ideally check the value of these in the binlog as that should show the effective value used during the build.TedMobile commentedon Sep 25, 2026
@vitek-karas
Hi, we have trying to build/deploy the app using everything .net 11 and we have encountered issues with android packages (dependency hell!!) what used to just work in net 10 , in net 11 android does not longer like packages like Xamarin.play.core ( we used the reviewmanager there ... looking into it..
we do manage to build both ios and android and the appsize and results are identical to before .
I have attached
Android_CommandLineArguments_CreateR2RImages.txt
ios-csprojExtract.txt
iOS-CommandLineArguments_R2R.txt
Android-CSProj.txt
basically the above is with the 2 properties set to false "MauiEnableFullReadyToRun=false and publishreadytorun=false too ,
so no change at all - we also tried the other flags and they were both 100mb.. no changes there.
there was no interpreter set on iOS.
@jonathanpeppers please see the cs proj extract of what we actually set - and below is an image that shows what we get with net 11 with MauiEnableFullReadyToRun=false and publishreadytorun=false - there no Aot files as we have issues to sort out with AOT.
is the above of any help?
vitek-karas commentedon Sep 25, 2026
@TedMobile thanks a lot for providing more data for us. Please bear with me as I have to admit I'm a bit lost in what config was used where... so I'll try to restate how I understand it and please correct me if I got it wrong.
The shared R2R command lines are from the matching csproj extract projects.
Were they collected without setting
PublishReadyToRun=false? - if you have binlogs could you check what was the effective value ofPublishReadyToRun(I'm pretty sure it had to be true otherwise it would not run the crossgen compiler)Your .NET 10 project for Android (the baseline) has
RunAOTCompilation=falsein it. Could you confirm this please?The picture of the size of the APK is from a .NET 11 Android project which specified
PublishReadyToRun=false. If I read this correctly it shows size close to the baseline 61MB of final package size. If your baseline disabled all AOT on Android, then disabling it on CoreCLR should produce similar size (probably slightly larger, but only by a couple of MBs).I have to admit I don't know what is the situation on iOS - the original issue description states that .NET 11 adds 30 MB to the app size - is that the packaged ipa? I think you said that if you disable R2R the .NET 11 size goes back to something similar to .NET 10, right? What I'm not clear on is what was the AOT configuration for the .NET 10 project.
Could you please help us confirm the AOT configuration of your original .NET 10 iOS build?
Collect a binlog from a clean Release device build (
ios-arm64), using your original settings, and share these small extracts:UseInterpreterandMtouchInterpreter. What is their effective values, or they're not set at all?$task AOTCompileand selectAOTCompileunder_AOTCompile. Under Parameters → Assemblies, could you copy the Arguments and ProcessArguments entries for your main application assembly andSystem.Private.CoreLib.dll? If your main assembly is not listed, please let us know.Side note:
RunAOTCompilationhas no effect on .NET 11 (CoreCLR). Similar property to that in CoreCLR isPublishReadyToRun.Out of curiosity (if it's not too much trouble): You seem to hint that the original .NET 11 setup (with 10.0 MAUI) and the new setup (with 11.0 MAUI) produce basically the same app size on Android. Is that correct? (The original one showed full R2R, the new one shows partial R2R in the command line). I also assume they were done with R2R enabled.
TedMobile commentedon Sep 29, 2026
@vitek-karas
My colleague who made the pipeline changes and carried out a number of the tests with the different flags is off this week, but let me try to summarise exactly what we did and hopefully remove some of the confusion.
.NET 11 + MAUI 10
Our initial migration was to the .NET 11 SDK/runtime, but we subsequently realised that we were still using the MAUI 10 workload.
These were the results from that configuration ( both net 11 + Maui 10 or Maui 11 ) have the same result!.
This is where we first noticed the significant package-size increase. Disabling R2R brought the packages back close to the sizes we were accustomed to before the migration.
.NET 11 + MAUI 11
Once we realised that we were still using the MAUI 10 workload, we upgraded to the proper MAUI 11 workload and controls and repeated the testing.
We saw the same package-size behaviour: with R2R enabled the packages were significantly larger, while disabling R2R brought them back close to the previous sizes.
I will provide the equivalent MAUI 11 numbers/configuration separately so that we have a clean comparison.
Android
For clarity, all of our Android projects, both .NET 10 and .NET 11, have been built with:
<RunAOTCompilation>false</RunAOTCompilation>We have some existing Android AOT issues to resolve before we can enable it.
iOS
For both our .NET 10 and .NET 11 iOS Release builds, we are not using the interpreter.
We haven't explicitly selected an iOS AOT configuration in the project; we have relied on the normal iOS Release/toolchain defaults. Our Release configuration also has:
Let me see if I can reproduce what he did and extract the remaining information from the binlogs.
In particular, I will try to provide the requested .NET 10 iOS Release AOTCompile details:
I will also confirm the effective PublishReadyToRun value for the relevant R2R-enabled build.
Hopefully this clarifies the configurations and which results came from which setup
vitek-karas commentedon Sep 29, 2026
Thanks a lot for the information. On the Android side the
RunAOTCompilation=falsebasically explains the behavior. .NET 11 doesn't react to that property (intentional breaking change on our end - maybe we should produce a warning or error though to guide people to the right place) - it will use R2R AOT by default and that's almost certainly why the app is larger. If you disable that viaPublishReadyToRun=falseit seems to get the app close to the .NET 10 size numbers.For iOS I don't have an explanation yet unfortunately - hopefully the arguments for the AOT compiler will help us there.
TedMobile commentedon Oct 6, 2026
@vitek-karas hi we collected some data and find below hope is helpful and give you more of an insight..
Build Comparison Matrix
Arguments.txt
tannergooding commentedon Oct 6, 2026
@vitek-karas, did you note that the linker command has
-a "System.Text.Json" Alland-a "System.Net.Http" All, which is causing at the very least all of the following to be rooted/kept:So post trimming this also pulls in
System.Net.Quic,System.Net.Security,System.Net.Sockets,System.Diagnostics.DiagnosticSource, etc. Which look to add up to around 14.7MB of combined cost for R2R codegenIt also looks to cause it to ignore switches like
Http3Support=falseand we don't seem to have a way to balance those concepts here (allow rooting something that is generally used, but also trim out specific aspects that are explicitly unused)vitek-karas commentedon Oct 7, 2026
@TedMobile, thanks a lot for the update!
Size regressions after the upgrade
Please correct me if I misunderstood anything. Here is my takeaway from the data you provided:
Android
iOS
Please do let me know if you have different observations or if any of the new behavior is unexpected for your application.
Rooting of JSON and HTTP assemblies
@tannergooding, thanks a lot for pointing that out. I didn't notice it. It's definitely an interesting observation, and it likely affects the size of the application on both platforms.
@TedMobile, we don't have enough data to tell why the
System.Text.JsonandSystem.Net.Httpassemblies are fully rooted.Typically this is done by specifying
TrimmerRootAssemblyitems in your project file, but there are other ways as well.This could be intentional, to work around problems with the partial trimming setup used by MAUI apps. If it's not, though, it might be a nice opportunity to reduce the size of the application.
If this was intentional, we would be very interested in the types of problems you ran into that motivated these workarounds. We would very much like to improve this going forward.
Could you search your project and shared/imported
.propsor.targetsfiles for these assembly names and share any entries that preserve them, particularlyTrimmerRootAssemblyentries? You could also search the binlog forTrimmerRootAssembly; even knowing that it was set would help us diagnose this further.Could you check whether the same assemblies are explicitly preserved in both the original .NET 10 Android baseline and the current .NET 11 / MAUI 11 Android build? In the binlog, the
ILLinktask's Parameters → RootAssemblyNames contains the effective list, including anyRootModemetadata. It would also help to know whether you use equivalent preservation rules on iOS.This would help us understand whether these roots were added intentionally by the project configuration or somehow slipped in during the upgrade.
TedMobile commentedon Oct 7, 2026
@vitek-karas
Android
I agree its solved! we have removed all the flags and with only a few mbs difference - its a win!
iOS
in net .10 we had the interpreter on because we were getting errors very difficult to debug! and our size was 77 - now it works in .net 11 but we gain 30mb but removing the interpreter. I wish it was less - but it is what it is I guess. I will have some explaining to do when our clients will see the app size a bigger.
TrimmerRootAssembly
thanks to @tannergooding for spotting it ! yes we have those in our csproj!
the reason we added the above was because we removed nuewtonsoft and fully replaced with System.Text.Json. however when the app was released it was crashing without telling us much what was going on and what the "culprit" was so we added the above! - given the gain we could make in reducing the size I.E 15/17 mb may be we are going to investigate it again , and any tips/tricks what to look for would be good.. binlog is a bit cryptic at times but may be any suggestion could help..
PublishReadyToRun/MauiEnableFullReadyToRun
As you suggested , we have decided to fully remove them! , however I have to say we noticed the start up being snappier for sure, but not yet everywhere else, but it does make the app bigger though!.. but lets see.
thanks alot in taking the time, and we learned a lot about all these new flags.. I do wish though mono enabled could have been a fallback for .net 11 only though.
vitek-karas commentedon Oct 7, 2026
iOS size
For the iOS I just want to clarify for my benefit: So you set either
MtouchInterpreter=allorUseInterpreter=truein the .NET 10 project? The AOT invocation you shared about doesn't seem to be for a build where interpreter is enabled on everything.Regardless - if your app had AOT really disabled then we don't have a corresponding configuration on .NET 11 - the closest is
PublishReadyToRun=falsewhich might work, we just don't really test it and thus you might run into problems. Also the pure-interpreter execution is likely slower on .NET 11 than it was on .NET 10 (AOT is on the other hand faster).Trimming
The best approach is to enable trim warnings, the compiler will tell you all the places in your code which do problematic reflection (or other patterns). But it works the opposite direction, it will likely point to places which try to do something problematic, it doesn't tell you if this touches code inside the two assemblies. But it might still be helpful to at least know which areas of your code might be the cause of the problems. https://learn.microsoft.com/en-us/dotnet/maui/ios/linking#suppress-analysis-warnings - you want to enable it (MAUI disables this by default).
Full R2R
It is expected that full R2R will speed up startup if you have some meaningful amount of code running during startup. For the rest of the app this is a bit more difficult to measure and the difference might not be observable.
Mono
I understand the concern here, I'm just curious where the real need comes from. My reasoning is that you can stay on .NET 10 for a while still. And even it was possible, it would just delay the change by 1 year... I'm honestly curious what is the aspect which makes it compelling (I can only theorize, you know the reality).
TedMobile commentedon Oct 8, 2026
@vitek-karas
iOS
in net 10 we used only Interpreter true (as we were getting some errors we could not clear) all good in .net 11
Trimming
Giving a go now - would be nice if we managed at our end to remove those!
Mono
It was more of a safety net - but now that I know more - its fine I guess. We always move to latest avail version of .net as even though .net 10 is supported the maui team is very small and they will concentrate on .net 11 for bugs etc and only fix critical .net 10 once 11 is out.
we are going AOT all the way.. just the iOS bump in size is a bummer...
vitek-karas commentedon Oct 8, 2026
@TedMobile
If I understand it correctly on .NET 10 you were not using AOT on iOS. Unfortunately we don't really have an option to not have it in .NET 11.
On a similar train of thought - have you considered NativeAOT - it has hard trimming and compat requirements, but it will make your app significantly smaller (and faster). But I don't know your dependencies, it might be very difficult to make it work.