Let us begin by … oh heck; we are trying to cut the fluff & fine-tune our Windows Phone applications, right? 🙂
So, here goes:
- Images:
- DataContext/Binding:
- App Startup:
- Threading:
- Network Calls:
- Isolated Storage:
- Performance Tools:
- Controls:
- Low-Cost Device Optimization:
- Common Sense:
This should be common knowledge .. Windows Phone handles JPGs much quicker than PNGs. So, unless we need transparency, let’s stay away from unnecessary PNGs. Next comes the Resource vs Content dilemma. Resources adds bulk to DLL and Content adds files to the XAP. Larger DLL will add to App startup time; but render images quicker than first-time file access for Contents. There is no easy thumbrule here; depends on what fits your app. I personally see better performance with a Resource if app startup time isn’t being hindered much, and if using an image many times as panorama/page backgrounds. Much more details HERE.
If the XAML page has data binding (specially in case of panoramas), I find it odd to provide context to XAML on Page_Loaded event. Why not on Constructor, if possible? Not that Constructors need to be bloated; but why wait for the Loaded event if you can data bind right away and allow rendering? Even if I am firing off heavy operations on background thread, I prefer data binding (with cached data) before anything else. Data binding on Loaded/NavigatedTo should be reserved for times when on back navigations, you truly want updated data source or two-way binding.
Let us do everything possible to not hinder the rendering of the first frame page. Shoot for minimal code in App Constructor/Launching; similarly in MainPage with simple XAML layout. Progress indicators are great after first page renders; consider if the SplashScreen is really needed. If data binding needs dynamic data, consider overlaying the page contents with some progress indicators until ready. If binding to static data but fetching fresh data in background, I think it’s ok to load page and warn the user that he is looking as stale data. Great article HERE.
Let’s make sure we understand the subtleties of threading and never ever block the king, the UI thread. Composition threads handle animations and off-load work to GPU; so not suitable for us to do any more heavy-lifting. Let’s make friends with the Background thread/worker (HERE‘s how) and push off anything we can to this guy. Until Async-Await become more mainstream, let us be diligent about marshaling stuff back to the UI thread through shared variables or Dispatcher.BeginInvoke().
4 thumbrules I try to follow: Through Background thread/HTTPWebRequest. Grab more in one call, instead of making many API calls. Cache anything possible. Check for connectivity & degrade gracefully.
If not close to 90MB memory restriction, I try to minimize hits to Isolated Storage for disk access. It’s ok to have a giant object & serialize/deserialize in one go. And remember, encryption/decryption is expensive; so reserve for the super-sensitive stuff.
Let’s use what’s at our disposal – the Windows Phone Performance Analysis Tool (HERE) for detailed performance walkthrough and the Frame Rate Counters to figure out the bottlenecks. I try to watch out for huge memory footprints, like a high resolution image loaded in memory, but displayed as a small picture.
Yes, we would love our Apps to be flashy; but complex & nested XAML comes at a price .. so let’s try to keep our layouts simple. Panoramas render all panels with data binding at once, which can take a toll on memory. Deferred panel loading and background bitmap as Resource are things I try doing when using Panoramas, or considers Pivots when possible. Things like toolkit HubTile controls also add a little bulk; make sure to stop animations on non-visible areas. Maps & WebBrowsers are expensive too; consider if the corresponding Tasks fit what you are trying to do.
Taking the marketing fight downstream was needed; hence comes the so-called lower devices with 256MB RAM. For the most part, we should be fine if following performance best practices for regular Windows Phone devices. Just a few additional things for us to keep in mind: Let’s not use Background Agents (can’t depend on them anyways since they can be disabled by user or overuse); watch the 90MB memory footprint; no looping backstack navigation; use the 256MB emulator for lowest common factor and let’s do all the things above to make our apps performant in low-memory devices. Best possible checklist HERE.
The cliched term is true and lack of common sense on our part can have expensive performance repercussions. Or may be, this is just me :). Late night coding sessions are great for ego & getting stuff done; but let’s sleep on it & review our work the next day for sanity checks. I have done stupid things like setting a background image on a panorama/grid & then the same one on every panel; result – double the brush memory gets loaded & counted against the app footprint. A responsive UI wins the battle any day over a complex layout. No unnecessary namespaces, proper use of threading & resources and general common sense = wonderfully performant Windows Phone apps. And a proud you, right?
Adios!
Thank you very much for these tips. They are really useful !