[Tips and Tricks] Windows Phone. DeviceStatus. Uso de memoria

memory-chipIntroducción

Por encima de cuidar detalles como la funcionalidad o la estética de nuestra aplicación, tenemos que lograr un objetivo que parece simple pero que a veces se escapa, nuestra aplicación debe funcionar correctamente bajo todas las condiciones en todos los dispositivos para la que sea lanzada. Un fallo comun suele ser que se escape la gestión de memoria de la aplicación pudiendo obtener una excepción de tipo OutOfMemoryException. Ya vimos como el control MemoryCounter del Coding4Fun Toolkit nos ayuda a saber el uso de memoria en todo momento. También tenemos disponible la herramienta Windows Phone Performance Analysis para poder analizar el uso de memoria de nuestra aplicación entre otras opciones. Sin embargo, el propio SDK nos incluye la posibilidad de saber el uso de memoria de nuestra aplicación e incluso el límite máximo de uso de memoria o la memoria disponible del dispositivo. Vamos a aprender como realizar esta tarea en este artículo.

Monitorizar la memoria

Tenemos disponible en el SDK de Windows Phone la API DeviceStatus que nos permite obtener información del hardware del dispositivo como la cantidad de memoria o la versión del sistema por ejemplo. Además, tenemos disponible una serie de eventos a los que podemos suscribirnos para recibir una notificación cuando un parámetro del sistema cambia.

Vamos a realizar un ejemplo práctico donde utilizar la API DeviceStatus. Creamos un nuevo proyecto:

La plantilla seleccionada será “Windows Phone Application” para simplificar al máximo el ejemplo. Comenzamos creando la base de nuestra interfaz. Añadiremos dos botones, uno para aumentar el consumo de memoria y otro para liberarla:

<Button Content="Aumenta consumo memoria"/>
<Button Content="Libera consumo memoria"/>

Añadimos sus eventos clic:

<Button Content="Aumenta consumo memoria" Click="AumentaMemoria_Click" />
<Button Content="Libera consumo memoria" Click="LiberaMemoria_Click"/>

Y en el code-behind:

private void AumentaMemoria_Click(object sender, RoutedEventArgs e)
{

}

private void LiberaMemoria_Click(object sender, RoutedEventArgs e)
{

}

Creamos una colección de Bytes para cargar en memoria:

List<Byte[]> _memoria;

En el primer botón añadimos 10MB al uso de memoria cada vez que sea pulsado. En el segundo, limpiamos la colección y llamamos el recolector de basura:

private void AumentaMemoria_Click(object sender, RoutedEventArgs e)
{
     _memoria.Add(new Byte[1024 * 1024 * 10]);
}

private void LiberaMemoria_Click(object sender, RoutedEventArgs e)
{
     _memoria.Clear();
     GC.Collect();
}

Hasta aqui todo lo necesario para poder probar la memoria, podemos aumentarla y liberarla. Sin embargo, no tenemos ahora mismo posibilidad de saber que consumo esta realizando la aplicación. Vamos a añadir en nuestra interfaz un TextBlock donde mostrar la información relacionada con el uso de memoria:

<TextBlock Name="Data" />

Vamos a crear un método que actualice el texto del TextBlock anterior con la información relacionada con la memoria. Dentro del método usaremos la API DeviceStatus para acceder a ciertas propiedades relacionadas con la memoria. Las propiedades son:

private void ActualizarDatos()
{
     Data.Text = String.Format(@"
     Actual: {0}MB
     Pico máximo: {1}MB
     Límite de uso: {2}MB
     Total dispositivo: {3}MB",
     (DeviceStatus.ApplicationCurrentMemoryUsage / 1000000).ToString(CultureInfo.InvariantCulture),
     (DeviceStatus.ApplicationPeakMemoryUsage / 1000000).ToString(CultureInfo.InvariantCulture),
     (DeviceStatus.ApplicationMemoryUsageLimit / 1000000).ToString(CultureInfo.InvariantCulture),
     (DeviceStatus.DeviceTotalMemory / 1000000).ToString(CultureInfo.InvariantCulture));
}

Para finalizar llamaremos al método en los clic de los botones para actualizar los valores en pantalla cada vez que pulsemos uno de ellos:

ActualizarDatos();
Uso de memoria

Uso de memoria

Sin duda una forma sencilla para poder consultar el uso de memoria. Sin embargo, no es práctico en nuestras aplicaciones mostrar la información en pantalla. Para solventar esa situación, podemos realizar un sencillo Helper, llamado MemoryHelper, que contenga un método que obtendrá la misma información cada X segundos y las mostrará en la ventana de Output de Visual Studio:

public static void GetMemoryData(int seconds)
{
     _timer = new Timer(state =>
     {
          string result = string.Empty;
          result += String.Format(@"
          Fecha: {0}
          Actual: {1}MB
          Pico máximo: {2}MB
          Límite de uso: {3}MB
          Total dispositivo: {4}MB",
          DateTime.Now.ToLongTimeString(),
          (DeviceStatus.ApplicationCurrentMemoryUsage / 1000000).ToString(CultureInfo.InvariantCulture),
          (DeviceStatus.ApplicationPeakMemoryUsage / 1000000).ToString(CultureInfo.InvariantCulture),
          (DeviceStatus.ApplicationMemoryUsageLimit / 1000000).ToString(CultureInfo.InvariantCulture),
          (DeviceStatus.DeviceTotalMemory / 1000000).ToString(CultureInfo.InvariantCulture));

     Deployment.Current.Dispatcher.BeginInvoke(() => Debug.WriteLine(result));
     },
     null,
     TimeSpan.FromSeconds(seconds),
     TimeSpan.FromSeconds(seconds));
}
Ejemplo OutOfMemory 02

Resultados en la ventana de depuración

Podéis descargar el ejemplo a continuación:

Más información

Deja un comentario