Aracılığıyla paylaş


XAML işaretlemenizi iyileştirme

Bellekteki nesneleri oluşturmak için XAML işaretlemesini ayrıştırmak karmaşık bir kullanıcı arabirimi için zaman alır. Burada, XAML işaretlemenizin ayrıştırma ve yükleme süresini ve uygulamanızın bellek verimliliğini geliştirmek için yapabileceğiniz bazı işlemler vardır.

Uygulama başlangıcında, yüklenen XAML işaretlemesini yalnızca ilk kullanıcı arabiriminiz için ihtiyacınız olan değerle sınırlayın. İlk sayfanızdaki (sayfa kaynakları dahil) işaretlemeyi inceleyin ve hemen gerekli olmayan ek öğeleri yüklemediğinizden emin olun. Bu öğeler kaynak sözlükleri, başlangıçta daraltılmış öğeler ve diğer öğelerin üzerine çizilmiş öğeler gibi çeşitli kaynaklardan gelebilir.

XAML'nizi verimlilik için en iyi duruma getirmek için dengelemeler yapmak gerekir; her durum için her zaman tek bir çözüm yoktur. Burada bazı yaygın sorunlara göz atacak ve uygulamanız için doğru dengeleri sağlamak için kullanabileceğiniz yönergeler sağlıyoruz.

Öğe sayısını azaltma

XAML platformu çok sayıda öğe görüntüleme yeteneğine sahip olsa da, istediğiniz görselleri elde etmek için en az sayıda öğeyi kullanarak uygulamanızın daha hızlı bir şekilde düzenlenmesini ve işlenmesini sağlayabilirsiniz.

Kullanıcı arabirimi denetimlerinizi nasıl düzenleyeceğiniz konusunda yaptığınız seçimler, uygulamanız başlatıldığında oluşturulan kullanıcı arabirimi öğelerinin sayısını etkiler. Düzeni iyileştirme hakkında daha ayrıntılı bilgi için bkz. XAML düzeninizi iyileştirme.

Her öğe her veri öğesi için yeniden oluşturulduğundan, veri şablonlarında öğe sayısı son derece önemlidir. Liste veya kılavuzdaki öğe sayısını azaltma hakkında bilgi için, Öğeye göre öğe azaltma bölümüne, ListView ve GridView kullanıcı arabirimi iyileştirme makalesinde bakınız.

Burada, başlangıçta uygulamanızın yüklemesi gereken öğe sayısını azaltmanın diğer bazı yollarını inceleyeceğiz.

Öğe oluşturmayı erteleme

XAML işaretlemeniz hemen göstermediğiniz öğeler içeriyorsa, bu öğelerin yüklenmesini gösterilene kadar erteleyebilirsiniz. Örneğin, sekme benzeri bir kullanıcı arabiriminde ikincil sekme gibi görünür olmayan içeriğin oluşturulmasını geciktirebilirsiniz. Alternatif olarak, öğeleri varsayılan olarak kılavuz görünümünde gösterebilir, ancak kullanıcının verileri listede görüntülemesi için bir seçenek sağlayabilirsiniz. Gerekli olana kadar listeyi yüklemeyi geciktirebilirsiniz.

Öğenin ne zaman gösterileceğini denetlemek için Görünürlük özelliği yerine x:Load özniteliğini kullanın. Bir öğenin görünürlüğü Daraltılmışolarak ayarlandığında, görüntüleme geçişi sırasında atlanır, ancak yine de bellekte nesne örneği maliyetlerini ödersiniz. Bunun yerine x:Load kullandığınızda, çerçeve gerekli olana kadar nesne örneğini oluşturmaz, bu nedenle bellek maliyetleri daha da düşüktür. Bunun dezavantajı, kullanıcı arabirimi yüklenmediğinde küçük bir bellek yükü (yaklaşık 600 bayt) ödemenizdir.

Uyarı

x:Load veya x:DeferLoadStrategy özniteliğini kullanarak öğelerin yüklenmesini geciktirebilirsiniz. x:Load özniteliği Windows 10 Creators Update'den (sürüm 1703, SDK derleme 15063) itibaren kullanılabilir. Visual Studio projenizin hedeflediği en düşük sürümün x:Load kullanabilmesi için Windows 10 Creators Update (10.0, Derleme 15063) olması gerekir. Önceki sürümleri hedeflemek için x:DeferLoadStrategy kullanın.

Aşağıdaki örneklerde, kullanıcı arabirimi öğelerini gizlemek için farklı teknikler kullanıldığında öğe sayısı ve bellek kullanımı arasındaki fark gösterilmektedir. Aynı öğeleri içeren ListView ve GridView, sayfanın kök Kılavuzuna yerleştirilir. ListView görünmez, ancak GridView gösterilir. Bu örneklerin her birindeki XAML, ekranda aynı kullanıcı arabirimini oluşturur. Visual Studio'nun profil oluşturma ve performans için araçlarını kullanarak öğe sayısını ve bellek kullanımını denetleriz.

Seçenek 1 - Verimsiz

Burada ListView yüklenir, ancak Width 0 olduğundan görünür değildir. ListView ve alt öğelerinin her biri görsel ağaçta oluşturulur ve belleğe yüklenir.

<!-- NOTE: EXAMPLE OF INEFFICIENT CODE; DO NOT COPY-PASTE.-->
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <ListView x:Name="List1" Width="0">
        <ListViewItem>Item 1</ListViewItem>
        <ListViewItem>Item 2</ListViewItem>
        <ListViewItem>Item 3</ListViewItem>
        <ListViewItem>Item 4</ListViewItem>
        <ListViewItem>Item 5</ListViewItem>
        <ListViewItem>Item 6</ListViewItem>
        <ListViewItem>Item 7</ListViewItem>
        <ListViewItem>Item 8</ListViewItem>
        <ListViewItem>Item 9</ListViewItem>
        <ListViewItem>Item 10</ListViewItem>
    </ListView>

    <GridView x:Name="Grid1">
        <GridViewItem>Item 1</GridViewItem>
        <GridViewItem>Item 2</GridViewItem>
        <GridViewItem>Item 3</GridViewItem>
        <GridViewItem>Item 4</GridViewItem>
        <GridViewItem>Item 5</GridViewItem>
        <GridViewItem>Item 6</GridViewItem>
        <GridViewItem>Item 7</GridViewItem>
        <GridViewItem>Item 8</GridViewItem>
        <GridViewItem>Item 9</GridViewItem>
        <GridViewItem>Item 10</GridViewItem>
    </GridView>
</Grid>

ListView'un yüklü olduğu canlı görsel ağaç. Sayfa için toplam öğe sayısı 89'dir.

Liste görünümüne sahip görsel ağacının ekran görüntüsü.

ListView ve alt öğeleri belleğe yüklenir.

ListView ve alt öğelerinin belleğe yüklendiğini gösteren Yönetilen Bellek Testi Uygulaması 1 nokta E X E tablosunun ekran görüntüsü.

Seçenek 2 - Daha iyi

Burada ListView'un Görünürlüğü daraltılmış olarak ayarlanmıştır (diğer XAML, özgün XAML ile aynıdır). ListView görsel ağaçta oluşturulur, ancak alt öğeleri bu ağaçta oluşturulmaz. Ancak bunlar belleğe yüklenir, bu nedenle bellek kullanımı önceki örnekle aynıdır.

<ListView x:Name="List1" Visibility="Collapsed">

ListView daraltılmış canlı görsel ağaç. Sayfa için toplam öğe sayısı 46'dır.

Daraltılmış liste görünümüne sahip görsel ağacının ekran görüntüsü.

ListView ve alt öğeleri belleğe yüklenir.

ListView ve alt öğelerinin belleğe yüklendiğini gösteren Yönetilen Bellek Testi Uygulaması 1 noktalı E X E tablosunun güncelleştirilmiş ekran görüntüsü.

Seçenek 3 - En Verimli

Burada ListView, x:Load özniteliği False olarak ayarlanmıştır (diğer XAML, özgün XAML ile aynıdır). ListView, görsel ağaçta oluşturulmaz veya başlangıçta belleğe yüklenmez.

<ListView x:Name="List1" Visibility="Collapsed" x:Load="False">

ListView yüklü olmayan canlı görsel ağaç. Sayfa için toplam öğe sayısı 45'tir.

liste görünümü yüklenmemiş Görsel ağacı

ListView ve alt öğeleri belleğe yüklenmez.

Liste görünümüne sahip Görsel ağaç

Uyarı

Bu örneklerdeki öğe sayıları ve bellek kullanımı çok küçüktür ve yalnızca kavramı göstermek için gösterilir. Bu örneklerde, x:Load kullanmanın yükü bellek tasarruflarından daha fazladır, bu nedenle uygulama yararlı olmaz. Uygulamanızın ertelenmiş yüklemeden yararlanıp yararlanmayacağını belirlemek için uygulamanızdaki profil oluşturma araçlarını kullanmanız gerekir.

Düzen paneli özelliklerini kullanma

Düzen panelleri Arka Plan özelliğine sahip olduğundan, yalnızca renklendirmek için Panel'in önüne Dikdörtgen kullanmanıza gerek yok.

Verimsiz

<!-- NOTE: EXAMPLE OF INEFFICIENT CODE; DO NOT COPY-PASTE. -->
<Grid>
    <Rectangle Fill="Black"/>
</Grid>

Verimli

<Grid Background="Black"/>

Düzen panelleri de yerleşik kenarlık özelliklerine sahiptir, bu nedenle düzen panelinin çevresine Kenarlık öğesi yerleştirmeniz gerekmez. Daha fazla bilgi ve örnek için bkz. XAML düzeninizi iyileştirme.

Vektör tabanlı öğelerin yerine görüntüleri kullanma

Aynı vektör tabanlı öğeyi yeterince kez yeniden kullanırsanız, bunun yerine Görüntü öğesini kullanmak daha verimli hale gelir. CPU her öğeyi ayrı ayrı oluşturması gerektiğinden vektör tabanlı öğeler daha pahalı olabilir. Görüntü dosyasının kodunun yalnızca bir kez çözülmesi gerekir.

Kaynakları ve kaynak sözlüklerini iyileştirme

Genellikle uygulamanızın birden çok yerinde başvurmak istediğiniz kaynakları genel düzeyde depolamak için kaynak sözlükleri kullanırsınız. Örneğin, stiller, fırçalar, şablonlar vb.

Genel olarak, ResourceDictionary'yı, istenmediği sürece kaynakları örneklemeyecek şekilde optimize ettik. Ancak kaynakların gereksiz yere oluşturulmaması için kaçınmanız gereken durumlar vardır.

x:Name ile kaynaklar

Kaynaklarınıza başvurmak için x:Key özniteliğini kullanın. x:Name özniteliğine sahip herhangi bir kaynak, platformun optimizasyon avantajlarından yararlanamayacak; bunun yerine, ResourceDictionary oluşturulur oluşturulmaz örneklenir. Bunun nedeni, x:Name'in platforma, uygulamanızın bu kaynağa alan erişimine ihtiyacı olduğunu belirtmesidir. Bu yüzden, platformun bir referans oluşturmak için bir şey oluşturması gerekmektedir.

UserControl'de ResourceDictionary

UserControl içinde tanımlanan ResourceDictionary bir ceza taşır. Platform, UserControl'ün her örneği için böyle bir ResourceDictionary'nin bir kopyasını oluşturur. Çok kullanılan bir UserControl'leriniz varsa ResourceDictionary'yi UserControl'ün dışına taşıyın ve sayfa düzeyine yerleştirin.

Kaynak ve Kaynak Sözlüğü kapsamı

Bir sayfa farklı bir dosyada tanımlanan bir kullanıcı denetimine veya kaynağa başvuruda bulunursa, çerçeve bu dosyayı da ayrıştırıyor demektir.

Burada InitialPage.xaml ExampleResourceDictionary.xaml'den bir kaynak kullandığından, başlangıçta ExampleResourceDictionary.xaml tamamının ayrıştırılması gerekir.

InitialPage.xaml.

<Page x:Class="ExampleNamespace.InitialPage" ...>
    <Page.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="ExampleResourceDictionary.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Page.Resources>

    <Grid>
        <TextBox Foreground="{StaticResource TextBrush}"/>
    </Grid>
</Page>

ExampleResourceDictionary.xaml dosyası.

<ResourceDictionary>
    <SolidColorBrush x:Key="TextBrush" Color="#FF3F42CC"/>

    <!--This ResourceDictionary contains many other resources that
        are used in the app, but are not needed during startup.-->
</ResourceDictionary>

Uygulamanızın tamamında birçok sayfada bir kaynak kullanıyorsanız, bunu App.xaml depolamak iyi bir uygulamadır ve yinelemeyi önler. Ancak app.xaml uygulama başlangıcında ayrıştırılır, bu nedenle yalnızca bir sayfada kullanılan tüm kaynaklar (bu sayfa ilk sayfa değilse) sayfanın yerel kaynaklarına yerleştirilmelidir. Bu örnek, yalnızca bir sayfa (bu ilk sayfa değil) tarafından kullanılan kaynakları içeren App.xaml dosyasını göstermektedir. Bu işlem, uygulama başlatma süresini önemli ölçüde artırır.

App.xaml

<!-- NOTE: EXAMPLE OF INEFFICIENT CODE; DO NOT COPY-PASTE. -->
<Application ...>
     <Application.Resources>
        <SolidColorBrush x:Key="DefaultAppTextBrush" Color="#FF3F42CC"/>
        <SolidColorBrush x:Key="InitialPageTextBrush" Color="#FF3F42CC"/>
        <SolidColorBrush x:Key="SecondPageTextBrush" Color="#FF3F42CC"/>
        <SolidColorBrush x:Key="ThirdPageTextBrush" Color="#FF3F42CC"/>
    </Application.Resources>
</Application>

InitialPage.xaml.

<!-- NOTE: EXAMPLE OF INEFFICIENT CODE; DO NOT COPY-PASTE. -->
<Page x:Class="ExampleNamespace.InitialPage" ...>
    <StackPanel>
        <TextBox Foreground="{StaticResource InitialPageTextBrush}"/>
    </StackPanel>
</Page>

SecondPage.xaml.

<!-- NOTE: EXAMPLE OF INEFFICIENT CODE; DO NOT COPY-PASTE. -->
<Page x:Class="ExampleNamespace.SecondPage" ...>
    <StackPanel>
        <Button Content="Submit" Foreground="{StaticResource SecondPageTextBrush}"/>
    </StackPanel>
</Page>

Bu örneği daha verimli hale getirmek için SecondPageTextBrushSecondPage.xaml taşıyın ve ThirdPageTextBrushThirdPage.xamliçine taşıyın. uygulama kaynaklarının her durumda uygulama başlangıcında ayrıştırılması gerektiğinden InitialPageTextBrushApp.xaml kalabilir.

Aynı görünen birden çok fırçayı tek bir kaynakta birleştirme

XAML platformu yaygın olarak kullanılan nesneleri önbelleğe almaya çalışır, böylece mümkün olduğunca sık yeniden kullanılabilirler. Ancak XAML, bir işaretleme parçasında bildirilen fırçanın başka bir işaretlemede bildirilen fırçayla aynı olup olmadığını kolayca anlayamaz. Buradaki örnekte SolidColorBrush kullanılırken, durum büyük olasılıkla ve daha da önemle GradientBrushile ilişkilidir. Ayrıca önceden tanımlanmış renkleri kullanan fırçaları denetleyin; örneğin, "Orange" ve "#FFFFA500" aynı renktedir.

Verimsiz.

<!-- NOTE: EXAMPLE OF INEFFICIENT CODE; DO NOT COPY-PASTE. -->
<Page ... >
    <StackPanel>
        <TextBlock>
            <TextBlock.Foreground>
                <SolidColorBrush Color="#FFFFA500"/>
            </TextBlock.Foreground>
        </TextBlock>
        <Button Content="Submit">
            <Button.Foreground>
                <SolidColorBrush Color="#FFFFA500"/>
            </Button.Foreground>
        </Button>
    </StackPanel>
</Page>

Yinelemeyi düzeltmek için fırçayı kaynak olarak tanımlayın. Diğer sayfalardaki denetimler aynı fırçayı kullanıyorsa, bunu App.xamltaşıyın.

Verimli.

<Page ... >
    <Page.Resources>
        <SolidColorBrush x:Key="BrandBrush" Color="#FFFFA500"/>
    </Page.Resources>

    <StackPanel>
        <TextBlock Foreground="{StaticResource BrandBrush}" />
        <Button Content="Submit" Foreground="{StaticResource BrandBrush}" />
    </StackPanel>
</Page>

Aşırı çizimi en aza indirme

Aynı ekran piksellerinde birden fazla nesne çizildiğinde üzerine çizim yapılır. Bu kılavuz ile öğe sayısını en aza indirme isteği arasında bazen bir denge olduğunu unutmayın.

Görsel tanılama amacıyla DebugSettings.IsOverdrawHeatMapEnabled kullanın. Sahnede olduğunu bilmediğiniz nesneler çizildiğini fark edebilirsiniz.

Saydam veya gizli öğeler

Bir öğe saydam olduğu veya diğer öğelerin arkasında gizlendiği için görünmüyorsa ve düzene katkıda bulunmuyorsa, öğeyi silin. Öğe ilk görsel durumunda görünmüyorsa, ama diğer görsel durumlarında görünüyorsa, durumunu kontrol etmek için x:Load kullanın veya öğenin kendisinde Görünürlük değerini Daraltılmış olarak ayarlayın ve uygun durumlarda bu değeri Görünür olarak değiştirin. Bu heuristik yöntemin istisnaları olacaktır: Genel olarak, görsel durumların çoğunda bir özelliğin değeri en iyi şekilde unsur üzerinde yerel olarak ayarlanır.

Bileşik öğeler

Etki oluşturmak için birden çok öğeyi katmanlama yerine bileşik öğe kullanın. Bu örnekte sonuç, üst yarısı siyah (Kılavuzarka planından) ve alt yarısı gri olan iki tonlu bir şekildir. Gri renk, yarı saydam beyaz Dikdörtgen'ün siyah Kılavuzarka planı üzerinde alfa karıştırılmasıyla elde edilmiştir. Burada, sonucu elde etmek için gereken piksellerin 150% dolduruluyor.

Verimsiz.

<!-- NOTE: EXAMPLE OF INEFFICIENT CODE; DO NOT COPY-PASTE. -->
<Grid Background="Black">
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Rectangle Grid.Row="1" Fill="White" Opacity=".5"/>
</Grid>

Verimli.

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Rectangle Fill="Black"/>
    <Rectangle Grid.Row="1" Fill="#FF7F7F7F"/>
</Grid>

Düzenleme panelleri

Düzen panelinin iki amacı olabilir: bir alanı renklendirmek ve alt öğeleri yerleştirme. Z düzenindeki bir öğe zaten bir alanı renklendiriyorsa, öndeki düzen panelinin bu alanı boyaması gerekmez: bunun yerine yalnızca alt öğelerini yerleştirmeye odaklanabilir. İşte bir örnek.

Verimsiz.

<!-- NOTE: EXAMPLE OF INEFFICIENT CODE; DO NOT COPY-PASTE. -->
<GridView Background="Blue">
    <GridView.ItemTemplate>
        <DataTemplate>
            <Grid Background="Blue"/>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

Verimli.

<GridView Background="Blue">
    <GridView.ItemTemplate>
        <DataTemplate>
            <Grid/>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

Grid isabet sınaması yapılması gerekiyorsa, arka planını saydam olacak şekilde ayarlayın.

Sınır -ları

Nesnenin çevresine kenarlık çizmek için Border öğesi kullanın. Bu örnekte, Grid, TextBoxçevresinde geçici kenarlık olarak kullanılır. Ancak ortadaki hücredeki tüm pikseller fazla çizilmiş.

Verimsiz.

<!-- NOTE: EXAMPLE OF INEFFICIENT CODE; DO NOT COPY-PASTE. -->
<Grid Background="Blue" Width="300" Height="45">
    <Grid.RowDefinitions>
        <RowDefinition Height="5"/>
        <RowDefinition/>
        <RowDefinition Height="5"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="5"/>
        <ColumnDefinition/>
        <ColumnDefinition Width="5"/>
    </Grid.ColumnDefinitions>
    <TextBox Grid.Row="1" Grid.Column="1"></TextBox>
</Grid>

Verimli.

<Border BorderBrush="Blue" BorderThickness="5" Width="300" Height="45">
    <TextBox/>
</Border>

Kenar boşlukları

Kenar boşluklarını dikkate alın. Negatif kenar boşlukları başka bir öğenin işleme sınırlarına genişletildiğinde ve fazla çizime neden olduğunda, iki komşu öğe çakışabilir (muhtemelen yanlışlıkla).

Statik içeriği önbelleğe alma

Başka bir fazla çizim kaynağı da birçok çakışan öğeden yapılmış bir şekildir. CacheMode'yi bileşik şekli içeren UIElement üzerinde BitmapCache olarak ayarlarsanız, platform, öğeyi bir kez bir bitmap olarak işler ve ardından her karede bu bitmap'i tekrar tekrar kullanır, bu sayede üzerine yeniden çizmeye gerek kalmaz.

Verimsiz.

<Canvas Background="White">
    <Ellipse Height="40" Width="40" Fill="Blue"/>
    <Ellipse Canvas.Left="21" Height="40" Width="40" Fill="Blue"/>
    <Ellipse Canvas.Top="13" Canvas.Left="10" Height="40" Width="40" Fill="Blue"/>
</Canvas>

Üç dolu daire Venn diyagramı

Yukarıdaki görüntü sonuçtur, ancak burada fazla çizili bölgeler haritası bulunmaktadır. Koyu kırmızı, aşırı çizimin daha yüksek miktarını gösterir.

Çakışan alanları gösteren Venn diyagramı

Verimli.

<Canvas Background="White" CacheMode="BitmapCache">
    <Ellipse Height="40" Width="40" Fill="Blue"/>
    <Ellipse Canvas.Left="21" Height="40" Width="40" Fill="Blue"/>
    <Ellipse Canvas.Top="13" Canvas.Left="10" Height="40" Width="40" Fill="Blue"/>
</Canvas>

CacheModekullanımına dikkat edin. Alt şekillerden herhangi biri animasyona dahil oluyorsa, bit eşlem önbelleği muhtemelen her karede yeniden oluşturulması gerektiğinden ve bu durum amacını boşa çıkaracağından, bu tekniği kullanmayın.

XBF2 kullanma

XBF2, çalışma zamanında tüm metin ayrıştırma maliyetlerini önleyen XAML işaretlemesinin ikili gösterimidir. Ayrıca, ikili dosyanızı yükleme ve ağaç oluşturma için optimize eder ve yığın ve nesne oluşturma maliyetlerini iyileştirmek için XAML türleri için "fast-path" sağlar; örneğin, VSM, ResourceDictionary, Stiller, vb. Tamamen belleğe eşlendiği için, bir XAML Sayfasını yüklemek ve okumak için herhangi bir yığın yükü yoktur. Buna ek olarak, appx'te depolanan XAML sayfalarının disk ayak izini azaltır. XBF2 daha kompakt bir gösterimdir ve karşılaştırmalı XAML/XBF1 dosyalarının disk ayak izini 50%kadar azaltabilir. Örneğin, yerleşik Fotoğraflar uygulaması XBF2'ye dönüştürüldükten sonra yaklaşık 1 mb XBF1 varlığından ~400 kb XBF2 varlığına düştükten sonra yaklaşık 60% azalma gördü. Ayrıca uygulamaların CPU'da 15 ila 20% ve Win32 yığınında 10 ile 15% arasında avantaj sağladığını gördük.

Çerçevenin sağladığı XAML yerleşik denetimleri ve sözlükleri zaten tamamen XBF2 etkindir. Kendi uygulamanız için proje dosyanızın TargetPlatformVersion 8.2 veya üzerini bildirdiğinden emin olun.

XBF2'nizin olup olmadığını denetlemek için uygulamanızı ikili düzenleyicide açın; XBF2'niz varsa 12. ve 13. baytlar 00 02 olur.