How to Work with the Memory Limits of Windows Phone Apps

Introduction

To get the best possible performance out of Windows Phone applications, it is important that the applications do not become a resource hog. In this article, we will look at working with memory limits for Windows Phone applications.

Application developers should note that all Windows Phone devices are high memory devices. In fact, the minimum memory supported by Windows Phone 8 platform is 512 MB memory. With a portion of that memory reserved for the operating systems, applications have to work with a subset of the available memory.

Memory caps on a device can vary by the type of application as well as the memory size on the device.

Here is a table of the memory cap types.

Memory Cap Limit type

Application Type

Lower-memory phones

Higher-memory phones

Default memory cap

XNA based applications

150 MB

150MB

Default memory cap

XAML applications

150 MB

300MB

Higher memory cap

All application

180 MB

380 MB or higher

Note that a phone with all the sensors on it can still be a low memory device.

How to Check Memory Limits on a Device

Windows Phone 8 supports numerous APIs to get the memory limits for the device.

You can use the Microsoft.Phone.Info.DeviceStatus.DeviceTotalMemory property to get the total memory available on device.

How to Get Windows Phone Application Memory Metrics

As we saw in the memory cap table above, each application has an associated limit under which is needs to operate. This can be discovered programmatically by calling the Microsoft.Phone.Info.DeviceStatus.ApplicationMemoryUsageLimit property from the application itself. Note that the limit is returned in bytes.

The current memory usage can be accessed by calling the Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage property, which returns the information in bytes.

For application performance, the working set and committed bytes are also important. 

The working set information can be gotten from the device’s extended properties by querying for the ApplicationWorkingSetLimit property.

How to Request a Higher Memory Cap for Your Windows Phone Application

To request a higher memory cap for a Windows Phone application, you need to declare the ID_FUNCCAP_EXTEND_MEM functionality capability in the application manifest file.

Open up WMAppManifest.xml and add the highlighted lines.

<?xml version="1.0" encoding="utf-8"?>
 
<Deployment xmlns="http://schemas.microsoft.com/windowsphone/2012/deployment" AppPlatformVersion="8.0">
  <DefaultLanguage xmlns="" code="en-US"/>
  <App xmlns="" ProductID="{30dfeb7a-5d46-4270-b8ea-b2cbdd1fd4ea}" Title="PhoneApp2" RuntimeType="Silverlight" Version="1.0.0.0" Genre="apps.normal"  Author="PhoneApp2 author" Description="Sample description" Publisher="PhoneApp2" PublisherID="{0467aa6f-8322-4a11-b568-213057831158}">
    <IconPath IsRelative="true" IsResource="false">Assets\ApplicationIcon.png</IconPath>
    <Capabilities>
      <Capability Name="ID_CAP_NETWORKING"/>
      <Capability Name="ID_CAP_MEDIALIB_AUDIO"/>
      <Capability Name="ID_CAP_MEDIALIB_PLAYBACK"/>
      <Capability Name="ID_CAP_SENSORS"/>
      <Capability Name="ID_CAP_WEBBROWSERCOMPONENT"/>
    </Capabilities>
    <Tasks>
      <DefaultTask  Name ="_default" NavigationPage="MainPage.xaml"/>
    </Tasks>
    <Tokens>
      <PrimaryToken TokenID="PhoneApp2Token" TaskName="_default">
        <TemplateFlip>
          <SmallImageURI IsRelative="true" IsResource="false">Assets\Tiles\FlipCycleTileSmall.png</SmallImageURI>
          <Count>0</Count>
          <BackgroundImageURI IsRelative="true" IsResource="false">Assets\Tiles\FlipCycleTileMedium.png</BackgroundImageURI>
          <Title>PhoneApp2</Title>
          <BackContent></BackContent>
          <BackBackgroundImageURI></BackBackgroundImageURI>
          <BackTitle></BackTitle>
          <DeviceLockImageURI></DeviceLockImageURI>
          <HasLarge></HasLarge>
        </TemplateFlip>
      </PrimaryToken>
    </Tokens>
    <ScreenResolutions>
      <ScreenResolution Name="ID_RESOLUTION_WVGA"/>
      <ScreenResolution Name="ID_RESOLUTION_WXGA"/>
      <ScreenResolution Name="ID_RESOLUTION_HD720P"/>
    </ScreenResolutions>
    <FunctionalCapabilities>
      <FunctionalCapability Name="ID_FUNCCAP_EXTEND_MEM"/>
    </FunctionalCapabilities>
  </App>
 
</Deployment>

This does not block installation on low memory devices, and allows the application a higher memory allocation.

How to Block Install on Low Memory Phones

To ensure that application does not install on low memory phones, you can declare the following requirement in the application manifest.

<?xml version="1.0" encoding="utf-8"?>
 
<Deployment xmlns="http://schemas.microsoft.com/windowsphone/2012/deployment" AppPlatformVersion="8.0">
  <DefaultLanguage xmlns="" code="en-US"/>
  <App xmlns="" ProductID="{30dfeb7a-5d46-4270-b8ea-b2cbdd1fd4ea}" Title="PhoneApp2" RuntimeType="Silverlight" Version="1.0.0.0" Genre="apps.normal"  Author="PhoneApp2 author" Description="Sample description" Publisher="PhoneApp2" PublisherID="{0467aa6f-8322-4a11-b568-213057831158}">
    <IconPath IsRelative="true" IsResource="false">Assets\ApplicationIcon.png</IconPath>
    <Capabilities>
      <Capability Name="ID_CAP_NETWORKING"/>
      <Capability Name="ID_CAP_MEDIALIB_AUDIO"/>
      <Capability Name="ID_CAP_MEDIALIB_PLAYBACK"/>
      <Capability Name="ID_CAP_SENSORS"/>
      <Capability Name="ID_CAP_WEBBROWSERCOMPONENT"/>
    </Capabilities>
    <Tasks>
      <DefaultTask  Name ="_default" NavigationPage="MainPage.xaml"/>
    </Tasks>
    <Tokens>
      <PrimaryToken TokenID="PhoneApp2Token" TaskName="_default">
        <TemplateFlip>
          <SmallImageURI IsRelative="true" IsResource="false">Assets\Tiles\FlipCycleTileSmall.png</SmallImageURI>
          <Count>0</Count>
          <BackgroundImageURI IsRelative="true" IsResource="false">Assets\Tiles\FlipCycleTileMedium.png</BackgroundImageURI>
          <Title>PhoneApp2</Title>
          <BackContent></BackContent>
          <BackBackgroundImageURI></BackBackgroundImageURI>
          <BackTitle></BackTitle>
          <DeviceLockImageURI></DeviceLockImageURI>
          <HasLarge></HasLarge>
        </TemplateFlip>
      </PrimaryToken>
    </Tokens>
    <ScreenResolutions>
      <ScreenResolution Name="ID_RESOLUTION_WVGA"/>
      <ScreenResolution Name="ID_RESOLUTION_WXGA"/>
      <ScreenResolution Name="ID_RESOLUTION_HD720P"/>
    </ScreenResolutions>
    <Requirements>
      <Requirement Name="ID_REQ_MEMORY_300"/>
    </Requirements>
  </App>
 
</Deployment>

This will block the availability of the application on low memory phones.

Hands-On

Let us build a simple application which retrieves the memory metrics of the device and application.

Create a new Windows Phone 8 project in Visual Studio 2012/2013.

Add a few textblocks and a button under your XAML renders as below.

Add a few textblocks and a button under your XAML
Add a few textblocks and a button under your XAML

Your manifest for the MainPage:

<phone:PhoneApplicationPage
    x:Class="PhoneApp2.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">
 
    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
 
        <!-- LOCALIZATION NOTE:
            To localize the displayed strings copy their values to appropriately named
            keys in the app's neutral language resource file (AppResources.resx) then
            replace the hard-coded text value between the attributes' quotation marks
            with the binding clause whose path points to that string name.
 
            For example:
 
                Text="{Binding Path=LocalizedResources.ApplicationTitle, Source={StaticResource LocalizedStrings}}"
 
            This binding points to the template's string resource named "ApplicationTitle".
 
            Adding supported languages in the Project Properties tab will create a
            new resx file per language that can carry the translated values of your
            UI strings. The binding in these examples will cause the value of the
            attributes to be drawn from the .resx file that matches the
            CurrentUICulture of the app at run time.
         -->
 
        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
            <TextBlock Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>
 
        <!--ContentPanel - place additional content here-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0">
            <Button x:Name="buttonGetMemoryMetrics" Content="Get memory metrics" HorizontalAlignment="Left" Margin="98,428,0,0" VerticalAlignment="Top" Click="buttonGetMemoryMetrics_Click"/>
            <TextBlock x:Name="textBlockDeviceTotalMemory" HorizontalAlignment="Right" Margin="0,49,26,0" TextWrapping="Wrap" VerticalAlignment="Top" Text="0"/>
            <TextBlock HorizontalAlignment="Left" Margin="40,44,0,0" TextWrapping="Wrap" Text="Device Total Memory" VerticalAlignment="Top"/>
            <TextBlock x:Name="textBlockApplicationMemoryUsageLimit" HorizontalAlignment="Right" Margin="0,97,24,0" TextWrapping="Wrap" VerticalAlignment="Top" Text="0"/>
            <TextBlock HorizontalAlignment="Left" Margin="40,92,0,0" TextWrapping="Wrap" Text="Application Memory Usage Limit" VerticalAlignment="Top"/>
            <TextBlock x:Name="textBlockApplicationCurrentMemoryUsage" HorizontalAlignment="Right" Margin="0,149,24,0" TextWrapping="Wrap" VerticalAlignment="Top" Text="0"/>
            <TextBlock HorizontalAlignment="Left" Margin="40,144,0,0" TextWrapping="Wrap" Text="Application Current Memory Usage" VerticalAlignment="Top"/>
            <TextBlock x:Name="textBlockBytesCommitLimit" HorizontalAlignment="Right" Margin="0,198,24,0" TextWrapping="Wrap" VerticalAlignment="Top" Text="0"/>
            <TextBlock HorizontalAlignment="Left" Margin="40,193,0,0" TextWrapping="Wrap" Text="Bytes Commit Limit" VerticalAlignment="Top"/>
            <TextBlock x:Name="textBlockBytesCommitted" HorizontalAlignment="Right" Margin="0,245,24,0" TextWrapping="Wrap" VerticalAlignment="Top" Text="0"/>
            <TextBlock HorizontalAlignment="Left" Margin="40,240,0,0" TextWrapping="Wrap" Text="Bytes Commited" VerticalAlignment="Top"/>
            <TextBlock HorizontalAlignment="Left" Margin="40,44,0,0" TextWrapping="Wrap" Text="Device Total Memory" VerticalAlignment="Top"/>
            <TextBlock x:Name="textBlockApplicationWorkingSetLimit" HorizontalAlignment="Right" Margin="0,295,23,0" TextWrapping="Wrap" VerticalAlignment="Top" Text="0"/>
            <TextBlock HorizontalAlignment="Left" Margin="40,290,0,0" TextWrapping="Wrap" Text="Application Working Set Limit" VerticalAlignment="Top"/>
        </Grid>
 
 
        <!--Uncomment to see an alignment grid to help ensure your controls are
            aligned on common boundaries.  The image has a top margin of -32px to
            account for the System Tray. Set this to 0 (or remove the margin altogether)
            if the System Tray is hidden.
 
            Before shipping remove this XAML and the image itself.-->
        <!--<Image Source="/Assets/AlignmentGrid.png" VerticalAlignment="Top" Height="800" Width="480" Margin="0,-32,0,0" Grid.Row="0" Grid.RowSpan="2" IsHitTestVisible="False" />-->
    </Grid>
 
</phone:PhoneApplicationPage>
 

We will now write code to extract the memory metric on the click event handler of the button.

private void buttonGetMemoryMetrics_Click(object sender, RoutedEventArgs e)
        {
           
            long totalBytes = DeviceStatus.DeviceTotalMemory;
            long usageLimit = DeviceStatus.ApplicationMemoryUsageLimit;
            long currentUsage = DeviceStatus.ApplicationCurrentMemoryUsage;
            ulong commitLimit = MemoryManager.ProcessCommittedLimit;
            ulong currentCommit = MemoryManager.ProcessCommittedBytes;
 
            long workingsetLimit = 0;
            object temp;
            if(DeviceExtendedProperties.TryGetValue("ApplicationWorkingSetLimit", out temp))
                workingsetLimit = (long)temp;
 
 
            textBlockApplicationCurrentMemoryUsage.Text = currentUsage.ToString();
            textBlockApplicationMemoryUsageLimit.Text = usageLimit.ToString();
            textBlockApplicationWorkingSetLimit.Text = workingsetLimit.ToString();
            textBlockBytesCommitLimit.Text = commitLimit.ToString();
            textBlockBytesCommitted.Text = currentCommit.ToString();
            textBlockDeviceTotalMemory.Text = totalBytes.ToString();
           
        }
 
 

We will now run the application. When the application is run and the button is clicked, we will see the memory metrics related to the device will be displayed.

Summary

In this article, we learned about memory caps and memory metrics of a Windows Phone application. I hope you have found this information useful.  You can download the sample code below.

About the author

Vipul Patel is a Program Manager currently working at Amazon Corporation. He has formerly worked at Microsoft in the Lync team and in the .NET team (in the Base Class libraries and the Debugging and Profiling team). He can be reached at vipul.patel@hotmail.com

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read