One of the first things consumers notice about a mobile application is its beginning.
If users spend several seconds staring at a splash screen before the first interactive panel displays, a feature-rich program might have great functionality but yet seem sluggish.
Startup for.NET MAUI apps involves more than just loading the initial page:
For .NET MAUI applications, startup includes more than loading the first page:
The move to CoreCLR for .NET MAUI mobile applications makes startup benchmarking particularly relevant. In .NET 11 Preview 6, CoreCLR became the only runtime for .NET MAUI applications targeting Android, iOS, and Mac Catalyst. Microsoft also identifies performance and application size among the areas expected to benefit from the unified runtime direction.
However, an important distinction is required:
A runtime change does not automatically mean that every application will start faster.
Startup depends on the runtime, application initialization, dependencies, native libraries, networking, database initialization, reflection, configuration, device hardware, and build configuration.
Therefore, the correct engineering approach is to establish a controlled baseline and measure the complete startup path.
What Should Be Measured?
A useful startup benchmark should not produce only one number.
Measure at least:
| Metric | Why It Matters |
|---|---|
| Cold startup | Measures launch from a terminated state |
| Warm startup | Measures resume/relaunch behavior |
| Time to first UI | Represents perceived responsiveness |
| Time to interactive UI | Represents usable application state |
| Memory after startup | Shows initial memory footprint |
| Peak startup memory | Detects initialization spikes |
| CPU during startup | Shows initialization pressure |
| Application size | Measures deployment footprint |
| Crash/hang rate | Detects migration problems |
The exact values should be collected from the target application.
Do not use theoretical startup numbers as production benchmarks.
Define Startup Before Measuring It
The first mistake in startup benchmarking is failing to define what “startup” means.
Consider these possible endpoints:
These are different measurements.
For most user-facing applications, a useful primary metric is:
You may also track:
Keep the definition identical between runtime versions.
Establish a Baseline Before Migration
Suppose an application currently runs using the previous runtime configuration.
Record:
Then record the measurements:
| Measurement | Baseline |
|---|---|
| Cold startup | Measure |
| Warm startup | Measure |
| First interactive UI | Measure |
| Memory after startup | Measure |
| Peak memory | Measure |
| CPU | Measure |
| Package size | Measure |
These numbers become the reference point.
After migrating to CoreCLR, repeat exactly the same test.
Keep the Test Environment Consistent
A meaningful runtime comparison should look like:
Changing several variables simultaneously makes the result difficult to interpret.
For example, avoid comparing:
If startup changes, there is no reliable way to determine which change caused it.
Test Physical Devices
Mobile startup performance should be measured on physical devices.
Emulators are useful for development and automated testing, but they do not necessarily represent the performance characteristics of a user’s device.
Create a representative device matrix:
The exact devices should reflect the application’s supported-device policy.
Record the device model and operating-system version with every benchmark.
Test Cold Startup
A cold-start test begins with the application terminated.
A simplified process is:
Repeat the measurement several times.
For example:
Do not rely on the first run alone.
Startup can vary because of device state, OS activity, storage behavior, and other background processes.
Test Warm Startup Separately
Warm startup is a different workload.
For example:
or:
depending on how the application lifecycle is being evaluated.
Record warm-start measurements separately from cold-start measurements.
Do not combine them into one average.
Measure First Interactive UI
A splash screen does not necessarily mean that the application is ready.
For example:
If the application waits for the API call before becoming interactive, users may perceive the entire process as startup.
A better architecture can sometimes allow:
This distinction matters when evaluating startup improvements.
The benchmark should therefore distinguish:
from:
Instrument Application Initialization
Application code often contributes more startup work than expected.
Consider:
Dependency registration itself is not necessarily expensive.
The problem often appears when initialization performs real work:
If these operations execute synchronously during startup, they become part of the critical path.
Measure them separately.
Add Startup Timing
A simple timing mechanism can identify application-level startup costs:
Then instrument major initialization stages:
The important principle is to identify where the startup time is actually being spent.
Separate Runtime Time From Application Time
Suppose the measurement changes from:
That does not tell you why.
The startup path might look like:
After migration:
The application-level difference may be entirely runtime-related.
But if:
then the overall startup could still become slower.
This is why instrumentation is more valuable than a single stopwatch measurement.
Avoid Network Calls in the Critical Startup Path
One of the most common startup problems is synchronous dependence on remote services.
For example:
If this operation blocks the first interactive screen, startup now depends on:
A more responsive architecture can often display the initial UI and load non-critical data afterward.
For example:
The exact design depends on whether the data is required before the application can safely operate.
Do not move critical initialization into the background merely to make a benchmark number smaller.
Measure Database Initialization
Local databases can also affect startup.
For example:
Measure:
Test both:
Test First Installation Separately
A fresh installation can involve:
An existing installation may involve:
These are separate startup scenarios.
Create at least two benchmark categories:
| Scenario | Description |
|---|---|
| Fresh install | First launch after installation |
| Existing install | Launch with existing application state |
Do not use one scenario as a substitute for the other.
Measure Memory at Startup
Startup memory should be measured at consistent points.
For example:
Record:
The goal is to identify:
rather than focusing on one platform-independent number.
Test Memory After Repeated Launches
A single launch does not reveal memory-retention problems.
Repeat:
Then compare memory behavior.
For an application that remains active for long periods, also test:
If memory continually grows, investigate retained objects, event handlers, native resources, caches, and page lifetimes.
Do not automatically classify every memory difference as a runtime regression.
Test UI Initialization
XAML-heavy pages can create substantial startup or navigation work.
Consider:
The cost can come from:
Measure the first page separately from later navigation.
A runtime migration may change the timing of one stage without changing the overall architecture.
Avoid Loading Large Data Sets During Startup
For example:
If the database contains thousands of records, loading everything during startup can delay the first screen.
Prefer loading only what is required:
Then load additional data based on user interaction.
This is an application optimization rather than a CoreCLR-specific optimization, but it is important when measuring runtime migration effects.
Measure Image Initialization
Images can significantly affect perceived startup.
Avoid unnecessarily loading large assets before the first screen becomes interactive.
For example:
The test should reflect the actual product experience rather than an artificially optimized startup path.
Test Dependency Injection Resolution
Dependency injection can become expensive if large object graphs are created immediately.
For example:
Registration does not necessarily instantiate everything.
However, resolving a service may create a dependency graph:
Avoid optimizing registrations simply because the application has many services.
Measure first.
Test Reflection and Runtime Discovery
Applications sometimes perform assembly scanning during startup:
This can increase initialization work.
Search for:
Do not remove reflection blindly.
Determine whether it is actually part of the startup bottleneck.
Test Release Builds
Startup benchmarks must eventually use the application’s real deployment configuration.
Compare:
and, where applicable:
configurations.
A debug build is not representative of the production binary.
Native AOT and trimming can change application behavior and impose restrictions on dynamic runtime features, so applications using those deployment modes need dedicated validation.
Compare Application Size
Application size is another useful migration metric.
Record:
where applicable.
Keep packaging configuration constant.
For example:
Otherwise, a package-size difference may be caused by unrelated dependency changes.
Benchmark Startup on Multiple Architectures
Where the application supports different device architectures, test the deployment variants used in production.
For example:
The exact architecture matrix depends on the target platform and distribution requirements.
Record architecture with every benchmark.
Run Repeated Measurements
Startup performance is noisy.
Run each scenario multiple times.
For example:
Then report a distribution rather than a single measurement.
A useful table is:
| Runtime | p50 | p95 | Minimum | Maximum |
|---|---|---|---|---|
| Baseline | Measure | Measure | Measure | Measure |
| CoreCLR | Measure | Measure | Measure | Measure |
The exact statistical method can be adapted to the testing environment.
The important point is to capture variability.
Define a Regression Threshold
Before interpreting results, define what qualifies as a meaningful regression.
For example:
These are example engineering thresholds, not Microsoft requirements.
Your organization should select thresholds based on:
- Existing SLOs
- User expectations
- Measurement variance
- Device class
- Application criticality
Avoid declaring a regression because one run differs by a few milliseconds.
Compare p50 and Tail Behavior
If startup measurements vary significantly, the average alone can hide problems.
Suppose:
The outlier matters.
For user-facing applications, investigate why a small number of launches take significantly longer.
Possible causes include:
Do not automatically attribute the outlier to the runtime.
Create a Startup Benchmark Harness
A useful benchmark harness should capture:
Store the result in a machine-readable format.
For example:
Replace the zero values with actual measurements from the test environment.
This allows results to be compared over time.
Build a Startup Regression Dashboard
For teams maintaining multiple mobile releases, track:
over each runtime upgrade.
For example:
| Version | Cold Startup | Memory | Package Size | Crashes |
|---|---|---|---|---|
| Baseline | Measure | Measure | Measure | Measure |
| Candidate | Measure | Measure | Measure | Measure |
The goal is not to create a vanity dashboard.
The dashboard should identify whether a release crosses an agreed regression threshold.
Separate Runtime Regressions From Application Regressions
Suppose startup increases after migration.
Use this investigation sequence:
If the problem disappears after removing application initialization, it may be application-specific.
If a minimal application reproduces the difference, the runtime or framework becomes a stronger candidate.
Create a Minimal MAUI Startup Reproduction
A useful reproduction can be extremely small:
Avoid:
unless they are required to reproduce the problem.
Then compare the same minimal application under the relevant runtime versions.
This helps determine whether the startup difference is:
Test Authentication Separately
Authentication often introduces network and browser dependencies.
Measure:
This distinction is important.
For example:
is very different from:
Do not mix them into a single startup benchmark.
Test Offline Startup
A production mobile application should often remain usable when the network is unavailable.
Test:
If the application waits for a network call before rendering the first screen, startup can become highly variable.
This is a valuable test regardless of runtime version.
Test Startup After Upgrade
A runtime migration should also test an existing installation.
For example:
The first startup after an application upgrade may perform:
- Database migration
- Preference migration
- Cache rebuilding
- Authentication validation
- File migration
Measure this separately from ordinary cold startup.
Common Startup Problems
Everything Is Initialized in App
Large constructors or startup methods can create a long critical path.
Review:
Move non-critical work out of the critical startup path where the application architecture allows it.
Database Migration Runs During Startup
Database migrations can be expensive.
Measure migration time separately.
Network Calls Block the First Screen
Do not make non-critical remote calls prerequisites for initial interactivity.
Large Object Graphs Are Created Immediately
Review startup dependency resolution and lazy initialization opportunities.
Large Images Load Before UI
Defer non-critical media where appropriate.
Analytics Initialization Blocks Startup
Measure third-party initialization independently.
If a vendor SDK blocks startup, determine whether initialization can be deferred without affecting required functionality.
Troubleshooting
CoreCLR Build Starts More Slowly
First determine whether the increase comes from:
Use startup instrumentation rather than assuming the runtime is responsible.
Startup Improved but Memory Increased
Treat this as a trade-off requiring investigation.
Measure:
A faster startup with substantially higher memory may not be an overall improvement for low-memory devices.
Startup Is Stable on Desktop but Slow on Mobile
Desktop results are not representative of mobile startup.
Use physical mobile devices for the final benchmark.
Only Release Build Shows a Problem
Inspect:
The release configuration may exercise code paths that Debug does not.
Only One Device Class Regresses
Investigate device-specific characteristics:
A runtime behavior may interact differently with different hardware.
Recommended Benchmark Matrix
A serious CoreCLR startup evaluation can use this matrix:
| Dimension | Scenarios |
|---|---|
| Runtime | Baseline / CoreCLR |
| Platform | Android / iOS / Mac Catalyst |
| Device | Low / Mid / High |
| Build | Debug / Release |
| Installation | Fresh / Existing |
| Startup | Cold / Warm |
| Network | Online / Offline / Slow |
| Authentication | Existing session / Login required |
| Data | Empty / Existing / Large |
| Metrics | Startup / Memory / CPU / Size |
Not every application needs every scenario.
The matrix should reflect the application’s architecture and supported platforms.
Best Practices
- Define startup precisely before benchmarking.
- Establish a baseline before migration.
- Use the same device and OS for before/after comparisons.
- Test physical devices.
- Measure cold and warm startup separately.
- Measure time to first interactive UI.
- Instrument application initialization.
- Separate network and database initialization from runtime startup.
- Measure memory alongside startup.
- Test fresh and existing installations.
- Test Debug and Release separately.
- Test trimming/AOT configurations used for production.
- Run multiple iterations.
- Compare distributions rather than one run.
- Define regression thresholds before interpreting results.
- Test Android, iOS, and Mac Catalyst independently.
- Record SDK, runtime, MAUI, device, OS, and build configuration.
- Create a minimal reproduction for confirmed runtime-level issues.
Frequently Asked Questions
Does CoreCLR guarantee faster .NET MAUI startup?
No.
Microsoft identifies performance and application-size improvements as expected benefits of the unified CoreCLR direction, but actual application startup depends on the complete application and deployment environment.
What is the most important startup metric?
For a user-facing application, time to first interactive UI is usually more meaningful than process-start time alone.
However, track several metrics because a single number cannot explain why startup changed.
Should I benchmark an emulator?
Emulators are useful for development and automated testing, but final performance comparisons should include representative physical devices.
Should startup include API calls?
Only if the application intentionally requires those calls before becoming usable.
Measure network-dependent initialization separately from runtime and local startup.
How many benchmark runs should I perform?
There is no universal number.
Run enough repetitions to characterize normal variability and investigate outliers. The exact number depends on the device, test harness, and required confidence.
Should I compare Debug and Release builds?
Yes, but separately.
Release should be the primary production performance benchmark.
Does application size affect startup?
Potentially.
Larger packages can affect installation and deployment characteristics, but package size alone does not determine startup time. Measure both independently.
What should I do if startup gets slower after migration?
First reproduce the result.
Then profile the startup path and determine which stage changed:
Create a minimal reproduction if the issue appears runtime-related.
Conclusion
The CoreCLR transition in .NET MAUI creates an opportunity to evaluate mobile startup behavior with better measurement discipline.
Microsoft’s .NET 11 documentation describes performance and application size among the areas expected to benefit from the unified runtime direction, while CoreCLR is now the runtime path for MAUI mobile applications targeting Android, iOS, and Mac Catalyst.
But the correct engineering question is not:
“Is CoreCLR faster?”
It is:
“How does CoreCLR change startup behavior for this application under a controlled workload?”
A reliable benchmark follows this process:
The most important distinction is between runtime startup and application startup.
A .NET MAUI application may spend significant time initializing databases, resolving services, loading configuration, creating pages, loading images, authenticating users, or contacting APIs. Those operations can dominate the user-visible startup experience even when the underlying runtime is performing well.
Therefore, a credible CoreCLR migration benchmark should measure the complete startup path while keeping the application, device, dependencies, and configuration controlled.
Only then can a team determine whether a startup change is actually caused by the runtime migration or by another part of the application.
Best and Most Recommended ASP.NET Core 10.0 Hosting
Fortunately, there are a number of dependable and recommended web hosts available that can help you gain control of your website’s performance and improve your ASP.NET Core 10.0 web ranking. HostForLIFE.eu is highly recommended. In Europe, HostForLIFE.eu is the most popular option for first-time web hosts searching for an affordable plan. Their standard price begins at only €3.49 per month. Customers are permitted to choose quarterly and annual plans based on their preferences. HostForLIFE.eu guarantees “No Hidden Fees” and an industry-leading ’30 Days Cash Back’ policy. Customers who terminate their service within the first thirty days are eligible for a full refund.
By providing reseller hosting accounts, HostForLIFE.eu also gives its consumers the chance to generate income. You can purchase their reseller hosting account, host an unlimited number of websites on it, and even sell some of your hosting space to others. This is one of the most effective methods for making money online. They will take care of all your customers’ hosting needs, so you do not need to fret about hosting-related matters.