News

.NET MAUI Devs Wrestled with iOS App Size, Android Startup

Microsoft struggled to improve .NET MAUI performance beyond that of Xamarin.Forms, wrestling with thorny issues like iOS app size and Android startup times.

According to a lengthy, painstakingly detailed blog post about those struggles, it worked for .NET MAUI (.NET Multi-application UI), which just hit General Availability status on its path to replace Xamarin.Forms, including the ability to create desktop apps in addition to mobile apps.

"Our goal was for .NET MAUI to be faster than its predecessor, Xamarin.Forms, and it was clear that we had some work to do in .NET MAUI itself," said Jonathan Peppers, senior software engineer, in a gargantuan June 7 post titled "Performance Improvements in .NET MAUI."

He said the team believed that gains in developer productivity shouldn't come at the cost of application performance.

"The same could be said about application size -- what overhead is present in a blank .NET MAUI application? When we began optimizing .NET MAUI, it was clear that iOS had some work needed to improve application size, while Android was lacking in startup performance," he continued.

To strike a balance between app size and startup performance, the team addressed a dizzying array of concerns with many tests and tweaks that fine-tuned aspects ranging from different kinds of ahead-of-time (AOT) compilation to lazy loading to Dependency Injection to optimized color parsing and hundreds more.

Take AOT, for example, a big sticking point in the .NET world as the lack of officially supported native AOT actually kept developers away from the framework, according to a 2020 Microsoft survey.

AOT was found to be faster than just in time (JIT) compilation, as the latter happens the first time each C# method is called and thus implicitly impacts startup performance, which is a huge concern in mobile apps. However, AOT increases app size, because, for example, an Android native library is added in the final app for every .NET assembly, boosting the amount of code that needs to be loaded up. This conundrum required a balanced trade-off, a compromise that's prevalent in software development.

"To give the best of both worlds, startup tracing or Profiled AOT is a current feature of Xamarin.Android," Peppers said. "This is a mechanism for AOT'ing the startup path of applications, which improves launch times significantly with only a modest app size increase.

"It made complete sense for this to be the default option for Release builds in .NET 6. In the past, the Android NDK was required (a multiple gigabyte download) for doing AOT of any kind with Xamarin.Android. We did the legwork for building AOT'd applications without an Android NDK installed, making it possible to be the default going forward."

Through that and many other optimizations, the team did indeed lower startup times, as evidenced by the two graphics below, the first one showing test results for Android startup times in early previews, while the second one shows performance improvements "after the dust settled."

Android Startup Times in Early Previews
[Click on image for larger view.] Android Startup Times in Early Previews (source: Microsoft).
Android Startup Times After Optimizations
[Click on image for larger view.] Android Startup Times After Optimizations (source: Microsoft).

"To arrive at where we are today, it was a collaboration of several different teams," Peppers said. "We improved areas like Microsoft.Extensions and DependencyInjection usage, AOT compilation, Java interop, XAML, code in .NET MAUI in general, and many more."

While several developers lauded the team's efforts in the comments section of the blog post, one took exception, claiming performance boosts are secondary to more important concerns like missing features and functionality.

"Currently there are many cases where an API on a platform does nothing but [is] documented as working," said the comment. "Most importantly Essentials APIs. E.g. taking photos on Windows does nothing. Processing images using Maui.Graphics on Windows does nothing because they cannot be loaded as IImage (not fully implemented)! How can this be a full release? How can you release a feature that does not work -- taking look at the publicly available source code and seeing only parts implemented? I don't understand this behavior with MAUI."

About the Author

David Ramel is an editor and writer at Converge 360.

comments powered by Disqus

Featured

  • VS Code 1.125 Adds Copilot Spend Meter After Billing Shock

    VS Code 1.125 adds in-editor visibility into additional Copilot budget usage as GitHub's AI-credit billing model continues to draw developer scrutiny.

  • TypeScript 7.0 RC Moves Microsoft's Go Rewrite Into the Mainline Compiler

    Microsoft's Go-based TypeScript rewrite has reached Release Candidate status, moving from a separate native-preview package into the regular TypeScript npm package while leaving some ecosystem-facing API work for TypeScript 7.1 or later.

  • Microsoft Highlights Visual Studio Live! Event Lineup and Longtime Developer Community Role

    A Microsoft MVP Blog post on Visual Studio Live!'s longevity arrives as the 2026 conference series continues with upcoming stops at Microsoft HQ, San Diego and Orlando.

  • Using Local AI to Cut Copilot Usage-Based Billing Shock

    After being gobsmacked by the new billing plan using almost all my monthly credits in one or two days, I tried pushing some Copilot-style coding work onto local models in VS Code. What I found was less "free AI" and more "pick your pain": cloud charges on one side, heavy local resource use and long waits on the other.

Subscribe on YouTube