Översikt över XAML-analys

XAML-analys är ett verktyg som meddelar dig om prestandaproblem i din app. Den kontrollerar din appkod mot en uppsättning prestandariktlinjer och metodtips och identifierar problem från en regeluppsättning med vanliga problem.

När verktyget hittar ett problem pekar det på Visual Studio diagnostikverktyg, källinformation och dokumentation så att du kan undersöka och åtgärda problemet.

Avkodad bildstorlek större än återgivningsstorlek

Bilder som tagits med hög upplösning kan göra att appen använder mer CPU vid avkodning och mer minne efter inläsning från disk. Det finns ingen fördel med att avkoda en högupplöst bild om du bara visar den med en mindre storlek. Skapa i stället en version av bilden med den storlek som du ritar den på skärmen med hjälp av DecodePixelWidth egenskaperna och DecodePixelHeight .

Påverkan

Om du visar bilder i andra storlekar än deras ursprungliga storlek kan det påverka cpu-tiden (avkodning och nedladdning) och minnet negativt.

Orsaker och lösningar

Avbildningen har inte ställts in asynkront

Appen använder SetSource() i stället för SetSourceAsync(). Använd alltid SetSourceAsync när du ställer in en ström för att avkoda bilder asynkront.

Bildkällan anges innan elementet finns i liveträdet

BitmapImage är ansluten till XAML-liveträdet när innehållet har angetts med SetSourceAsync eller UriSource. Koppla alltid en BitmapImage till liveträdet innan du anger källan. När du anger ett bild-element eller en pensel i märkspråk kopplas det automatiskt.

Bra – källa som anges i markering med :BitmapImage

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

Bra – koppla BitmapImage till trädet innan du anger UriSource:

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

Felaktig – ange BitmapImages UriSource innan du ansluter den till trädet:

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

Bildpenseln är inte rektangulär

När du använder en bild för en orektangulär pensel använder bilden en programvarubaserad rasteriseringsväg, vilket innebär att bilden inte skalas. Dessutom lagrar systemet en kopia av avbildningen i både programvaru- och maskinvaruminnet. När du använder en icke-rektangulär pensel skalar du bilderna i förväg till ungefär den storlek som du renderar dem på.

Du kan också ange en explicit avkodningsstorlek med egenskaperna DecodePixelWidth och DecodePixelHeight :

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

Enheterna för DecodePixelWidth och DecodePixelHeight är som standard fysiska bildpunkter. Ange DecodePixelType till Logisk så att avkodningsstorleken automatiskt tar hänsyn till systemets aktuella skalningsfaktor, ungefär som för annat XAML-innehåll.

Om du inte kan fastställa en lämplig avkodningsstorlek i förväg kan du förlita dig på XAML:s automatiska avkodning av rätt storlek, vilket gör det bästa sättet att försöka avkoda bilden med lämplig storlek.

Bilder som används i BitmapIcons återgår till naturlig storlek

Ange en explicit avkodningsstorlek med egenskaperna DecodePixelWidth och DecodePixelHeight .

DecodePixelWidth eller DecodePixelHeight är större än visningsstorleken

Om du uttryckligen anger DecodePixelWidth eller DecodePixelHeight är större än bildens visningsstorlek på skärmen använder appen extra minne (upp till 4 byte per pixel), vilket blir dyrt för stora bilder.

Bilden är dold

Bilden döljs genom att ange Opacity 0 eller Visibility till Collapsed på värdbildelementet, penseln eller ett överordnat element. Bilder som inte visas på skärmen på grund av urklipp eller transparens kan återgå till avkodning i naturlig storlek.

Avbildningen använder ninegrid-egenskapen

När du använder en bild med NineGrid renderas bilden via programvarurasterisering. Skala bilderna i förväg till ungefär den storlek som du renderar dem till.

Komprimerade element vid inläsningstid

Ett vanligt mönster är att dölja gränssnittselement från början och visa dem senare. I de flesta fall bör du skjuta upp dessa element med x:Load för att undvika kostnaden för att skapa dem vid inläsning.

Påverkan

Hopfällda element laddas tillsammans med andra element och ökar laddningstiden.

Solution

Använd attributet x:Load för att fördröja inläsningen av användargränssnittet. Elementet läses in när du behöver det, vilket minskar den initiala bearbetningen. Du kan också använda x:Bind för att styra inläsningstillståndet.

ListView är inte virtualiserat

Virtualisering av användargränssnittet är den viktigaste förbättringen du kan göra för insamlingsprestanda. Gränssnittselement som representerar objekt skapas på begäran. För en kontroll som är bunden till en samling med 1 000 objekt slösar skapande av alla användargränssnitt samtidigt resurser eftersom du inte kan visa alla objekt samtidigt. ListView och GridView hanterar virtualisering av användargränssnittet åt dig – de genererar användargränssnitt för objekt nära visningsporten och återtar minne för objekt som rullats ur vyn.

Påverkan

Ett icke-virtualiserat ItemsControl ökar inläsningstiden och resursanvändningen genom att ladda in fler underordnade element än nödvändigt.

Solution

Ange en bredd och höjd på ItemsControl för att definiera ett visningsområde. När du placerar en virtualiserad kontroll i en panel med obegränsat utrymme (till exempel ScrollViewer eller en Grid med rader i automatisk storlek) tar kontrollen tillräckligt med utrymme för alla objekt, vilket förhindrar virtualisering.

UI-tråd blockerad eller inaktiv under belastning

Blockering av användargränssnittstrådar uppstår när synkrona anrop till funktioner som körs utanför tråden blockerar användargränssnittstråden. Håll användargränssnittstråden dynamisk med hjälp av asynkrona API:er. Mer information finns i Håll användargränssnittstråden dynamisk.

Använd {x:Bind} i stället för {Binding}

{Binding} använder mer tid och minne än {x:Bind}. Att skapa en {Binding} medför en rad allokeringar, och att uppdatera ett bindningsmål kan innebära reflektion och boxning. Använd {x:Bind}, som kompilerar bindningar vid byggtiden för bättre prestanda och kompileringstidsverifiering.

Note

{x:Bind} är inte lämplig i alla fall, till exempel i scenarier där bindningen sker sent. Mer information finns i dokumentationen om {x:Bind} .

Använd x:Key i stället för x:Name i ResourceDictionaries

När du använder x:Name på en resurs instansierar plattformen den omedelbart eftersom x:Name den skapar en fältreferens. Använd x:Key i stället när du inte behöver referera till resursen från code-behind.

Använda virtualiseringspaneler för samlingar

Om du anger en panelmall för anpassade objekt (se ItemsPanel), använder du en virtualiseringspanel som ItemsWrapGrid eller ItemsStackPanel. Använder VariableSizedWrapGrid, WrapGrideller StackPanel inaktiverar virtualisering.

Hjälpmedel: Ange namn för UIA-element

Ange AutomationProperties.Name i kontrollens XAML som en lämplig lokaliserad sträng. Om ett element inte ska visas i UIA-trädet anger du AutomationProperties.AccessibilityView = "Raw".

Undvik att ge två UIA-element med samma överordnade element samma Name och samma ControlType. I listor där dubbletter av namn ofta förekommer använder du bindning för att ange AutomationProperties.Name från en datakälla.