Optimize Startup Time
The first of the four principles I mentioned in Optimizing Apps for Lower Cost Devices is Optimize Startup Time.
Fast startup is an essential component of any mobile application. It is the first impression a user has of your app and is the first chance you have to either impress or frustrate your users.
If you're wondering just how fast your startup time can get on Windows Phone, use the VS Project Templates as a starting point. Create a new project, deploy it to the device, and experience how quickly the app starts up.
A general principle to keep in mind is that any regressions in startup time from the VS Project Templates are the result of app code delaying the rendering of the first frame. The more app code you can remove or delay before the first frame is rendered, the closer your startup time will match the baseline startup time of the VS Project Templates.
To fully understand the areas of opportunity for improving startup time, it's important to understand the workflow of a launching application.
- The App constructor is called in App.xaml.cs.
- XAML in App.xaml is parsed.
- Application_Launching is called in App.xaml.cs.
- The Page constructor of your MainPage is called.
- XAML in your MainPage is parsed.
- OnNavigatedTo is called in your MainPage.
Once you understand this workflow, it is easy to conclude that any app code or XAML introduced in this workflow will result in startup time regressions from the VS Project Templates.
To minimize the impact of app code in this startup path, you should either remove code from these events or execute code on background threads to unblock the UI thread. Only code executing on the UI thread will have a severe impact on startup performance. Deferring activity to background threads will allow your first frame to render quickly. Use Dispatcher.BeginInvoke from background threads to return back to the UI thread when necessary.
To minimize the impact of XAML parsing on startup time, you can simplify and remove unnecessary XAML from both your MainPage and from App.xaml.
- Remove unnecessary namespaces declared in <phone:PhoneApplicationPage>.
- If your XAML elements aren't prefixed by a declared namespace, then the namespace declaration can be safely removed.
- Avoid explicit declarations of default attribute values.
- Grid.Row="0", for instance, is the default value if Grid.Row is not declared, so just don't declare it.
- SupportedOrientations="Portrait" and Orientation="Portrait" can be removed as well for portrait only pages since this is the default.
- Understand default values and remove redundant XAML.
- Avoid retemplating controls in App.xaml.
- Retemplating controls can require complex XAML which is expensive to parse.
- For Metro-style apps that are theme-aware, this is less of a concern. If you need to retemplate controls to support a branded experience, for instance, then understand what is necessary to override and what can be omitted.
- If templates are only needed for particular pages, consider moving the custom templates to the pages that need them. This will delay the cost of parsing the XAML until the necessary page is loaded rather than require the cost to be paid at startup.
- Normalize Style declarations.
- If you are consistently setting FontFamily, FontSize, and Foreground in a similar way on several TextBoxes, for instance, then consider using Styles instead.
- Simplify page layouts.
- Don't use nested Grids and StackPanels when one root container would be sufficient to layout your page.
- Declare your app bar in code.
- This will be faster to process than parsing the XAML and is actually the only way to localize your app bar components.
With your first frame rendered quickly, you can then turn your attention to indicating progress to the user while the rest of your content loads. Perceived startup time can go a long way to minimize the amount of frustration content load times can impose on users. The first frame of your app should always include the chrome of your application (system tray, app title, page title, pivot titles, app bar, etc.) as well as a ProgressIndicator to indicate that your content is loading. You'll want to use the ProgressIndicator over other progress bars as (1) the ProgressBar control has known performance issues and (2) the ProgressIndicator will provide the most consistent experience with the rest of the built-in experiences on the phone.
Note that the system tray and app bar are shell components and so will render more quickly than the content in your PhoneApplicationPage. You can take advantage of this to improve perceived startup time even further. You'll notice in the Weather app that the system tray and app bar appear first followed by the rest of the page content. If you're using the system tray ProgressIndicator as recommended above to indicate progress, it will appear as well immediately when the system tray is rendered.
A bonus to using both the system tray and app bar is that these components render together and provide a recognizable chrome for your app while it loads. Many apps hide the system tray and use only an app bar. If you've used these apps, you'll notice often that the app bar renders first before the rest of the content loads. The lack of symmetry in this case introduced by not showing the system tray actually contributes to the perception of lag that the user experiences. By adding the system tray, you can eliminate this perception while also providing a consistent chrome that is recognizable across apps. If you don't want to show the system tray but want to take advantage of it for the reasons mentioned above, show the system tray on launch with an opacity of 0. Using an opacity of 0 means the system tray won't affect your page layout at all. Once the rest of your content loads, you can then hide the system tray if you'd like.
Many apps use a splash screen to solve the perceived startup problem as it is cheap to implement and can promote the brand of the app. While this is a great practice, you may find that after following the guidance above, the splash screen will actually slow down your startup time. Adding a splash screen to the Weather app, for instance, would actually harm its startup performance. With your startup time optimized, assess whether a splash screen is really necessary. Your apps will actually feel more like integrated experiences if they don't use a splash screen, so don't be afraid to leave it off completely. The combination of fast startup time, no splash screen, and extensibility points like secondary tiles will really make your apps shine on Windows Phone.