The evolution of Windows Phone memory management

My colleague Mike Battista posted some great info earlier this year about how to develop apps for lower-memory phones. There’s also some excellent best practice guidance on the Windows Phone Dev Center.

In this post, I aim to give you the big picture, so you can understand the reasoning behind the guidance we’ve provided and help ensure your apps continue to work well while the Windows Phone memory management story evolves. Here’s a handy reference table:

image

A history lesson

Windows Phone OS 7.0 and 7.1, apps were limited to using 90 MB of memory. The 90 MB threshold is a certification constraint, and while an app might actually sometimes get to use more than 90 MB, it’s never guaranteed. 90 MB was the guaranteed minimum that an app could rely on. But what was the maximum? Some developers have a perception that Windows Phone apps are not memory capped, and that they can consume more than 90 MB. This is only partly true. In fact, apps have always been memory capped—it’s just that the cap is not a constant value. An app could keep on consuming memory above 90 MB, and at some point an allocation would fail. For a managed app, this is surfaced as an OutOfMemoryException (OOM).

An app that hits an OutOfMemoryException and doesn’t handle it is terminated. Exactly when the app hits this variable cap depends on what else is going on in the system at the time. The Resource Manager component on the phone manages memory for apps, but not for the OS itself, so the amount of memory available to an app varies: it is always at least 90 MB, sometimes more, and sometimes not. This unpredictability is difficult to develop against. All the data we have on the existing Windows Phone Store catalog shows that the majority of apps do actually stay within 90 MB. That said, there are some apps that exceed 90 MB, and there are one or two extreme outliers where the maximum peak recorded consumption is far in excess of that.

When Windows Phone 7.1.1 was released, the app memory cap became more interesting. The only guarantee remains 90 MB. What made Windows Phone 7.1.1 interesting is that it introduced paging. Now, the OS was always capable of paging, but it wasn’t previously enabled on the phone. This is because paging is (a) time-consuming and in the worst-case scenario slow enough that it affects the UX, and (b) can eventually lead to degradation of the flash storage (used for writing out the page file).

Paging is the norm in desktop and server computers, but is relatively uncommon in mobile devices. Paging gives the system the ability to allocate more memory than is physically present on the device. It does this by using a flash-based page file. On Windows Phone 7.1.1, an app can actually allocate up to 110 MB of virtual memory. If the app only uses 50 to 60 MB of memory (the precise value varies according to what’s going on in the system overall), all that memory will be in real physical memory. If the app’s consumption exceeds that threshold, the additional memory is allocated in virtual (non-physical) memory in the page file. As the app executes, code and data that resides out in the page file gets paged in when it’s needed, and paged out again (or discarded entirely) when it’s not needed (and when something else in the ecosystem needs the physical memory).

Paging in and out takes time, and page writes especially cause wear on the flash device. Excessive page writes eventually degrade sections of flash and they become unusable. Eventually, you can imagine the extreme case where there just isn’t enough valid flash left to perform enough paging. The device’s overall performance degrades, and apps increasingly OOM. One of our challenges in 7.1.1 was to figure out the optimal paging value so that we wouldn’t risk hitting unacceptable flash degradation within the expected lifetime of the device.

Paging was introduced in 7.1.1 to meet the needs of low-memory devices. There’s a high demand worldwide for smartphones that meet the minimum requirements and have a low memory capacity. Even without detailed inside knowledge, you can speculatively do the math (all numbers are ballpark approximations):

image

If all developers stuck to the guidelines and didn’t consume more than 90 MB, under the Windows Phone OS 7.1 memory model—that is, no paging—then a large percentage of existing apps would OOM with unacceptable frequency when running on a 256 MB device. Therefore, even for well-behaved apps, the option to page became unavoidable. Then the question became, how much should we page? If we wanted to support the extreme outliers, we’d have to support such a large amount of paging that it would simply cause the system to thrash—it would repeatedly page in and out, and never actually get any real work done—obviously unacceptable.

So, we looked at paging performance, and the overall user experience, and after exhaustive testing, honed in on a figure of 110 MB—that is, 55 MB physical memory + 55 MB additional virtual memory. On a 256 MB device, any attempt to allocate memory beyond 110 MB will result in an OOM. Note that this was based on the app usage graph, in which the majority of apps actually fit in 55 MB of physical memory, and >90 percent actually fit in 90 MB. Moreover, even an app that consumes 90 MB, doesn’t consume 90 MB all the time. This means that most of the time the app is not paging. The net of all this is that the paging values allowed us to maintain support for the existing Windows Phone Store catalog, while at the same time producing a predictable, balanced overall UX.

To be clear, 110 is emphatically not the new 90. You’re still not guaranteed any more than 90 MB. The 7.1.1 paging model allows apps to go up to 110 MB, if memory is available, but this is a hard, fixed, enforced cap (unlike the variable cap on Windows Phone OS 7.0 and Windows Phone OS 7.1 devices). On a 256 MB device, you will always OOM beyond 110 MB. The same app running on a high-memory device—where the 110 MB cap is not enforced—may well be able to use >110 MB, although there’s still no guarantee.

From a big picture perspective, what this means is that the vast majority of apps in the existing catalog will work acceptably on all known devices. On top of that, an app typically works better on devices with >256 MB of memory, because the app probably has more memory available to it most of the time, and it won’t be forcibly capped at 110 MB.

The developer’s choice

Now that you’ve seen the rationale for memory management in Windows Phone OS 7.x, what can you do about this? You have two choices:

The first option is to make your app fit within 90 MB, so that it works on all devices and everything is rosy. There’s plenty of support in the app platform APIs—as discussed in the links at the top, and also in my earlier post—to help you tune your app. Plus, of course, you can use the Visual Studio memory profiler to monitor your app’s performance at run time. If you can’t fit within 90 MB, but can fit within 110 MB, then you’re still OK on all devices. It’s just that your UX might not perform as well on 256 MB devices because of paging. The APIs give you enough tools to be able to tune your app, perhaps by conditionally enabling some subset of your functionality only on higher-memory devices.  

If you just can’t fit within 110 MB, even after tuning and conditionally disabling features, then you have another choice. First, you could profile your app to figure out exactly which code paths cause consumption >110 MB, and how common they are. If the user is only going to hit the problem in extremely rare circumstances, you might consider this acceptable. On the other hand, if this is likely to be a common occurrence, then your other option is to disqualify your app from low-memory devices. Just to be clear on this option: low-memory devices are extremely important. If you don’t ensure that your app will work on a low-memory device, you’re effectively eliminating it from a substantial segment of the smartphone app market.

    A crystal ball

    Paging was introduced to support the greatest number of apps on the greatest number of devices. The cost is in slightly degraded performance—some of the time, on some devices. But even this is, for the most part, hardly noticeable to users.

    So what’s the strategy going forward? In Windows Phone 8, as Kevin Gallo has noted, the OS is no longer Windows CE, but instead shares a common codebase with Windows 8 (aka, “Big Windows”). And, of course Windows 8 uses paging. Does that mean we’ll use paging in Windows Phone 8? The strategy actually has not changed since 7x: the OS is capable of paging, and we’ll likely use paging when it makes sense, and otherwise avoid it—for all the same reasons as in the past. The aim, as always, is to continue to support all apps on all devices, without adversely affecting the UX in any unacceptable way.

    As you will have seen from the recent announcements from Nokia and HTC, the upcoming Windows Phone 8 phones include some with 720p (1280 x 720) or WXGA (1280 x 768) screens. If you think about it, you’ll probably conclude that higher-resolution graphics means more memory consumed. 7x supports only WVGA (800 x 480), and even if you don’t update your 7x app to use higher-res graphics, existing graphics still have to be scaled up (by platform) to the higher-res screens. An existing 7x app is therefore likely to consume more memory on Windows Phone 8. Right now, I can’t reveal any specifics about how things will work in Windows Phone 8, but you can rest assured that we’ve thought long and hard about the transition from 7x, and of all its implications. Watch this space for details soon!