Introducción al análisis XAML

El análisis xaml es una herramienta que le notifica problemas de rendimiento en la aplicación. Comprueba el código de la aplicación con un conjunto de directrices de rendimiento y procedimientos recomendados, e identifica los problemas de un conjunto de reglas de problemas comunes.

Cuando la herramienta encuentra un problema, apunta a las herramientas de diagnóstico, la información de origen y la documentación de Visual Studio para poder investigar y corregir el problema.

Tamaño de imagen descodificado mayor que el tamaño de representación

Las imágenes capturadas en resoluciones altas pueden hacer que la aplicación use más CPU al descodificar y más memoria después de cargar desde el disco. No hay ninguna ventaja de descodificar una imagen de alta resolución si solo se muestra a un tamaño menor. En su lugar, crea una versión de la imagen del tamaño al que la dibujes en pantalla usando las propiedades DecodePixelWidth y DecodePixelHeight.

Impacto

Mostrar imágenes con tamaños distintos de su tamaño nativo puede afectar negativamente al tiempo de CPU (descodificación y descarga) y la memoria.

Causas y soluciones

La imagen no se establece de forma asincrónica

La aplicación usa SetSource() en lugar de SetSourceAsync(). Use siempre SetSourceAsync al establecer una secuencia para descodificar imágenes de forma asincrónica.

El origen de la imagen se establece antes de que el elemento esté en el árbol activo.

BitmapImage se conecta al árbol XAML activo después de establecer el contenido con SetSourceAsync o UriSource. Adjunte siempre bitmapImage al árbol activo antes de establecer el origen. Cuando especifica un elemento de imagen o un pincel en el lenguaje de marcado, la asociación se realiza automáticamente.

Bien — origen especificado en el marcado mediante BitmapImage:

<Image x:Name="myImage">
    <Image.Source>
        <BitmapImage UriSource="Assets/cool-image.png"/>
    </Image.Source>
</Image>

Bueno : conectar BitmapImage al árbol antes de establecer su UriSource:

Image myImage = new Image();
var bitmapImage = new BitmapImage();
myImage.Source = bitmapImage;
bitmapImage.UriSource = new Uri("ms-appx:///Assets/cool-image.png", UriKind.RelativeOrAbsolute);

Incorrecto: establecer la propiedad UriSource de BitmapImage antes de conectarla al árbol:

Image myImage = new Image();
var bitmapImage = new BitmapImage();
bitmapImage.UriSource = new Uri("ms-appx:///Assets/cool-image.png", UriKind.RelativeOrAbsolute);
myImage.Source = bitmapImage;

El pincel de imagen no es rectangular

Al usar una imagen para un pincel no rectangular, la imagen utiliza un proceso de rasterización por software, que no permite escalar imágenes. Además, el sistema almacena una copia de la imagen en la memoria de software y hardware. Al usar un pincel no rectangular, redimensione previamente las imágenes al tamaño aproximado al que las va a renderizar.

Como alternativa, establezca un tamaño de descodificación explícito mediante las propiedades DecodePixelWidth y DecodePixelHeight :

<Image>
    <Image.Source>
    <BitmapImage UriSource="ms-appx:///Assets/highresCar.jpg"
                 DecodePixelWidth="300" DecodePixelHeight="200"/>
    </Image.Source>
</Image>

Las unidades de DecodePixelWidth y DecodePixelHeight son píxeles físicos de forma predeterminada. Establezca DecodePixelType en Logical para que el tamaño de descodificación tenga automáticamente en cuenta el factor de escala actual del sistema, similar al de otro contenido XAML.

Si no puedes determinar un tamaño de descodificación adecuado con antelación, confía en la descodificación automática de tamaño correcto de XAML, lo que hace un mejor intento de descodificar la imagen en el tamaño adecuado.

Las imágenes usadas dentro de BitmapIcons vuelven a su tamaño original

Establezca un tamaño de descodificación explícito mediante las DecodePixelWidth propiedades y DecodePixelHeight .

DecodePixelWidth o DecodePixelHeight son mayores que el tamaño de pantalla

Si estableces explícitamente DecodePixelWidth o DecodePixelHeight a un valor mayor que el tamaño de visualización en pantalla de la imagen, la aplicación consume memoria adicional (hasta 4 bytes por píxel), lo que puede resultar costoso para imágenes grandes.

La imagen está oculta

La imagen está oculta estableciendo el valor de Opacity en 0 o Visibility en Collapsed en el elemento host de la imagen, en el pincel o en un elemento padre. Las imágenes no visibles en la pantalla debido al recorte o la transparencia pueden revertir a la descodificación a tamaño natural.

La imagen usa la propiedad NineGrid

Cuando usa una imagen con NineGrid, la imagen utiliza un proceso de rasterización por software. Redimensione previamente las imágenes al tamaño aproximado al que las renderiza.

Elementos contraídos en tiempo de carga

Un patrón común es ocultar los elementos de la interfaz de usuario inicialmente y mostrarlos más adelante. En la mayoría de los casos, debería posponer estos elementos mediante x:Load para evitar el coste de crear el elemento durante la carga.

Impacto

Los elementos colapsados se cargan junto con otros elementos y aumentan el tiempo de carga.

Solution

Use el atributo x:Load para retrasar la carga de la interfaz de usuario. El elemento se carga cuando lo necesita, lo que reduce el procesamiento inicial. También puede usar x:Bind para controlar el estado de carga.

ListView no está virtualizado

La virtualización de la interfaz de usuario es la mejora más importante que puede realizar para el rendimiento de la recopilación. Los elementos de la interfaz de usuario que representan los elementos se crean a petición. Para un control enlazado a una colección de 1000 elementos, la creación de toda la interfaz de usuario a la vez desperdicia recursos porque no se pueden mostrar todos los elementos simultáneamente. ListView y GridView se encargan de la virtualización de la interfaz de usuario: generan la interfaz de usuario para los elementos cercanos al área visible y liberan memoria de los elementos que se desplazan fuera de la vista.

Impacto

Un elemento ItemsControl sin virtualización aumenta el tiempo de carga y el uso de recursos al cargar más elementos secundarios de los necesarios.

Solution

Establezca un ancho y una altura en el ItemsControl para definir un área de visualización. Cuando se coloca un control virtualizado en un panel con espacio ilimitado (como ScrollViewer o un Grid con filas de tamaño automático), el control ocupa el espacio suficiente para todos los elementos, lo que anula la virtualización.

Subproceso de interfaz de usuario bloqueado o inactivo durante la carga

El bloqueo del hilo de la interfaz de usuario se produce cuando las llamadas síncronas a funciones que se ejecutan en otro hilo bloquean el hilo de la interfaz de usuario. Mantenga la capacidad de respuesta del subproceso de interfaz de usuario mediante API asincrónicas. Para obtener más información, consulte Mantener la capacidad de respuesta del subproceso de la interfaz de usuario.

Usar {x:Bind} en lugar de {Binding}

{Binding} usa más tiempo y memoria que {x:Bind}. Crear una {Binding} genera una serie de asignaciones de memoria, y actualizar un destino de enlace de datos puede implicar reflexión y encapsulado. Use {x:Bind}, que compila enlaces en tiempo de compilación para mejorar el rendimiento y la validación en tiempo de compilación.

Note

{x:Bind} no es adecuado para todos los casos, como los escenarios de enlace tardío. Consulte la documentación de {x:Bind} para obtener más información.

Uso de x:Key en lugar de x:Name en ResourceDictionaries

Cuando se usa x:Name en un recurso, la plataforma lo crea inmediatamente porque x:Name crea una referencia de campo. Use x:Key en su lugar cuando no necesite hacer referencia al recurso desde el código subyacente.

Uso de paneles de virtualización para colecciones

Si proporciona una plantilla de panel de elementos personalizados (vea ItemsPanel), use un panel de virtualización como ItemsWrapGrid o ItemsStackPanel. Usar VariableSizedWrapGrid, WrapGrid o StackPanel desactiva la virtualización.

Accesibilidad: proporcione nombres para los elementos UIA.

Establezca AutomationProperties.Name en el XAML de su control en una cadena localizada apropiada. Si un elemento no debe aparecer en el árbol UIA, establezca AutomationProperties.AccessibilityView = "Raw".

Evite proporcionar dos elementos UIA con el mismo elemento primario igual Name y ControlType. En listas donde se suelen producir nombres duplicados, use el enlace para establecer AutomationProperties.Name desde un origen de datos.