Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Analisar a marcação XAML para construir objetos na memória é demorado para uma interface do usuário complexa. Aqui estão algumas coisas que você pode fazer para melhorar o tempo de análise e carregamento da marcação XAML e a eficiência de memória do seu aplicativo.
Na inicialização do aplicativo, limite a marcação XAML carregada apenas para o que você precisa para sua interface do usuário inicial. Examine a marcação em sua página inicial (incluindo recursos de página) e confirme se você não está carregando elementos extras que não são necessários imediatamente. Esses elementos podem vir de uma variedade de fontes, como dicionários de recursos, elementos inicialmente colapsados e elementos desenhados sobre outros elementos.
Otimizar seu XAML para obter eficiência requer fazer compensações; nem sempre há uma única solução para cada situação. Aqui, analisamos alguns problemas comuns e fornecemos diretrizes que você pode usar para fazer as compensações certas para seu aplicativo.
Minimizar a contagem de elementos
Embora a plataforma XAML seja capaz de exibir um grande número de elementos, você pode fazer seu aplicativo definir e renderizar mais rapidamente usando o menor número de elementos para alcançar os visuais desejados.
As escolhas que você faz na forma como você define seus controles de interface do usuário afetarão o número de elementos de interface do usuário que são criados quando seu aplicativo é iniciado. Para obter informações mais detalhadas sobre como otimizar o layout, consulte Otimizar o layout XAML.
A contagem de elementos é extremamente importante em modelos de dados porque cada elemento é criado novamente para cada item de dados. Para obter informações sobre como reduzir a contagem de elementos em uma lista ou grade, consulte
Aqui, analisamos algumas outras maneiras de reduzir o número de elementos que seu aplicativo precisa carregar na inicialização.
Adiar a criação do item
Se a marcação XAML contiver elementos que você não mostrar imediatamente, você poderá adiar o carregamento desses elementos até que eles sejam mostrados. Por exemplo, você pode atrasar a criação de conteúdo não visível, como uma guia secundária em uma interface do usuário semelhante a uma guia. Alternativamente, você pode mostrar itens em uma visualização em grade por padrão, mas oferecer uma opção para que o usuário possa exibir os dados em uma lista. Você pode atrasar o carregamento da lista até que ela seja necessária.
Use o atributo x:Load em vez da propriedade Visibility para controlar quando um elemento é mostrado. Quando a visibilidade de um elemento é definida como recolhido, ele é ignorado durante o processo de renderização, mas você ainda paga os custos da instância de objeto na memória. Quando você usa x:Load em vez disso, a estrutura não cria a instância de objeto até que seja necessária, portanto, os custos de memória são ainda menores. A desvantagem é que você paga uma pequena sobrecarga de memória (aproximadamente 600 bytes) quando a interface do usuário não é carregada.
Observação
Você pode adiar o carregamento de elementos usando o atributo x:Load ou x:DeferLoadStrategy. O atributo x:Load está disponível a partir do Windows 10 Creators Update (versão 1703, build 15063 do SDK). A versão mínima direcionada ao seu projeto do Visual Studio deve ser o Windows 10 Creators Update (10.0, Build 15063) para usar x:Load. Para direcionar versões anteriores, use x:DeferLoadStrategy.
Os exemplos a seguir mostram a diferença na contagem de elementos e no uso de memória quando diferentes técnicas são usadas para ocultar elementos da interface do usuário. Um ListView e um GridView contendo itens idênticos são colocados na grade raiz de uma página. O ListView não está visível, mas o GridView é mostrado. O XAML em cada um desses exemplos produz a mesma interface do usuário na tela. Usamos as ferramentas de do Visual Studio para perfilagem e análise de desempenho, a fim de verificar a contagem de elementos e o uso da memória.
Opção 1 – Ineficiente
Aqui, o ListView é carregado, mas não está visível porque sua largura é 0. O ListView e cada um de seus elementos filho são criados na árvore visual e carregados na memória.
<!-- 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>
Árvore visual dinâmica com o ListView carregado. A contagem total de elementos para a página é 89.
ListView e seus filhos são carregados na memória.
Opção 2 – Melhor
Aqui, a Visibilidade do ListView está definida como colapsada (o outro XAML é idêntico ao original). O ListView é criado na árvore visual, mas seus elementos filho não são. No entanto, eles são carregados na memória, portanto, o uso de memória é idêntico ao exemplo anterior.
<ListView x:Name="List1" Visibility="Collapsed">
Árvore de visualização dinâmica com o ListView recolhido. A contagem total de elementos para a página é 46.
ListView e seus filhos são carregados na memória.
Opção 3 – Mais eficiente
Aqui, o ListView tem o atributo x:Load definido como False (o outro XAML é idêntico ao original). O ListView não é criado na árvore visual ou carregado na memória na inicialização.
<ListView x:Name="List1" Visibility="Collapsed" x:Load="False">
Árvore visual dinâmica com o ListView não carregado. A contagem total de elementos para a página é 45.
ListView e seus filhos não são carregados na memória.
Observação
As contagens de elementos e o uso de memória nesses exemplos são muito pequenos e são mostrados apenas para demonstrar o conceito. Nesses exemplos, a sobrecarga de uso de x:Load é maior do que a economia de memória, portanto, o aplicativo não se beneficiaria. Você deve usar as ferramentas de criação de perfil em seu aplicativo para determinar se seu aplicativo se beneficiará ou não do carregamento adiado.
Usar propriedades do painel de layout
Os painéis de layout têm uma propriedade Background, assim não é necessário colocar um retângulo na frente de um painel apenas para colori-lo.
ineficiente
<!-- NOTE: EXAMPLE OF INEFFICIENT CODE; DO NOT COPY-PASTE. -->
<Grid>
<Rectangle Fill="Black"/>
</Grid>
eficiente
<Grid Background="Black"/>
Os painéis de layout também têm propriedades de borda internas, portanto, você não precisa colocar um elemento Border em torno de um painel de layout. Consulte Otimizar o layout XAML para obter mais informações e exemplos.
Usar imagens no lugar de elementos baseados em vetor
Se você reutilizar o mesmo elemento baseado em vetor vezes o suficiente, se torna mais eficiente usar um elemento Image em vez disso. Elementos baseados em vetor podem ser mais caros porque a CPU deve criar cada elemento individual separadamente. O arquivo de imagem precisa ser decodificado apenas uma vez.
Otimizar recursos e dicionários de recursos
Normalmente, você usa dicionários de recursos para armazenar, em um nível um pouco global, recursos que você deseja referenciar em vários lugares em seu aplicativo. Por exemplo, estilos, pincéis, modelos e assim por diante.
Em geral, nós otimizamos ResourceDictionary para não instanciar recursos, a menos que sejam solicitados. Mas há situações que você deve evitar para que os recursos não sejam instanciados desnecessariamente.
Recursos com x:Name
Use o atributo x:Key para referenciar seus recursos. Qualquer recurso com o atributo x:Name não se beneficiará da otimização da plataforma; em vez disso, ele é instanciado assim que o ResourceDictionary é criado. Isso acontece porque x:Name informa à plataforma que seu aplicativo precisa de acesso de campo a esse recurso, portanto, a plataforma precisa criar algo para criar uma referência.
ResourceDictionary em um UserControl
Um ResourceDictionary definido dentro de um UserControl carrega uma penalidade. A plataforma cria uma cópia de tal ResourceDictionary para cada instância do UserControl. Se você tiver um UserControl muito usado, mova o ResourceDictionary para fora do UserControl e coloque-o no nível da página.
Escopo de Resource e de ResourceDictionary
Se uma página fizer referência a um controle de usuário ou a um recurso definido em um arquivo diferente, a estrutura também analisará esse arquivo.
Aqui, porque InitialPage.xaml usa um recurso de ExampleResourceDictionary.xaml, todo o ExampleResourceDictionary.xaml deve ser analisado durante a inicialização.
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.
<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>
Se você usar um recurso em muitas páginas em todo o aplicativo, armazená-lo em App.xaml é uma boa prática e evita a duplicação. Mas App.xaml é analisado na inicialização do aplicativo para que qualquer recurso usado em apenas uma página (a menos que essa página seja a página inicial) seja colocado nos recursos locais da página. Este exemplo mostra App.xaml contendo recursos que são usados por apenas uma página (essa não é a página inicial). Isso aumenta desnecessariamente o tempo de inicialização do aplicativo.
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>
Para tornar este exemplo mais eficiente, mova SecondPageTextBrush para SecondPage.xaml e mova ThirdPageTextBrush para ThirdPage.xaml.
InitialPageTextBrush pode permanecer no App.xaml porque os recursos do aplicativo devem ser analisados na inicialização do aplicativo em qualquer caso.
Consolidar vários pincéis que têm a mesma aparência em um recurso
A plataforma XAML tenta armazenar em cache objetos comumente usados para que eles possam ser reutilizados o mais frequentemente possível. Mas o XAML não consegue identificar facilmente se um pincel declarado em um trecho de código markup é o mesmo que um pincel declarado em outro. O exemplo aqui usa SolidColorBrush para demonstrar, mas o caso é mais provável e mais importante com GradientBrush. Verifique também se há pincéis que usam cores predefinidas; por exemplo, "Orange" e "#FFFFA500" são da mesma cor.
Ineficiente.
<!-- 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>
Para corrigir a duplicação, defina o pincel como um recurso. Se os controles em outras páginas usarem o mesmo pincel, mova-o para App.xaml.
eficiente.
<Page ... >
<Page.Resources>
<SolidColorBrush x:Key="BrandBrush" Color="#FFFFA500"/>
</Page.Resources>
<StackPanel>
<TextBlock Foreground="{StaticResource BrandBrush}" />
<Button Content="Submit" Foreground="{StaticResource BrandBrush}" />
</StackPanel>
</Page>
Minimizar a substituição
A sobreposição ocorre quando mais de um objeto é desenhado nos mesmos pixels da tela. Observe que, às vezes, há uma troca entre essa orientação e o desejo de minimizar a contagem de elementos.
Use DebugSettings.IsOverdrawHeatMapEnabled como um diagnóstico visual. Você pode encontrar objetos sendo desenhados que você não sabia que estavam na cena.
Elementos transparentes ou ocultos
Se um elemento não estiver visível porque ele é transparente ou oculto atrás de outros elementos e não está contribuindo para o layout, exclua-o. Se o elemento não estiver visível no estado visual inicial, mas estiver visível em outros estados visuais, use x:Load para controlar seu estado ou defina Visibility para Collapsed no próprio elemento e altere o valor para Visible nos estados apropriados. Haverá exceções a essa heurística: em geral, o valor que uma propriedade tem na maioria dos estados visuais é melhor definido localmente no elemento.
Elementos compostos
Use um elemento composto em vez de colocar vários elementos em camadas para criar um efeito. Neste exemplo, o resultado é uma forma de dois tons em que a metade superior é preta (do fundo do Grid ) e a metade inferior é cinza (do Retângulo branco semitransparente aplicado em alfa sobre o fundo preto do Grid ). Aqui, 150% dos pixels necessários para obter o resultado estão sendo preenchidos.
Ineficiente.
<!-- 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>
eficiente.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Rectangle Fill="Black"/>
<Rectangle Grid.Row="1" Fill="#FF7F7F7F"/>
</Grid>
Painéis de layout
Um painel de layout pode ter duas finalidades: colorir uma área e organizar elementos filhos. Se um elemento anterior na ordem z já estiver colorindo uma área, um painel de layout na frente não precisará pintar essa área: em vez disso, ele pode apenas se concentrar na organização de seus elementos filhos. Aqui está um exemplo.
Ineficiente.
<!-- NOTE: EXAMPLE OF INEFFICIENT CODE; DO NOT COPY-PASTE. -->
<GridView Background="Blue">
<GridView.ItemTemplate>
<DataTemplate>
<Grid Background="Blue"/>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
eficiente.
<GridView Background="Blue">
<GridView.ItemTemplate>
<DataTemplate>
<Grid/>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
Se o Grid precisar ser testado por clique, defina um valor em segundo plano de transparente nele.
Fronteiras
Use um elemento Border para desenhar uma borda em torno de um objeto. Neste exemplo, um Grid é usado como uma borda improvisada em torno de um TextBox. Mas todos os pixels na célula central estão superpostos.
Ineficiente.
<!-- 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>
eficiente.
<Border BorderBrush="Blue" BorderThickness="5" Width="300" Height="45">
<TextBox/>
</Border>
Margens
Esteja ciente das margens. Dois elementos vizinhos se sobreporão (possivelmente de forma acidental) se as margens negativas se estenderem para os limites de renderização de outro elemento e causarem excesso de desenho.
Armazenar conteúdo estático em cache
Outra fonte de sobredesenho é uma forma composta por muitos elementos sobrepostos. Se você definir CacheMode para BitmapCache no UIElement que contém a forma composta, a plataforma renderizará o elemento em um bitmap uma vez e usará esse bitmap a cada quadro em vez de redesenhar.
Ineficiente.
<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>
diagrama venn 
A imagem acima é o resultado, mas aqui está um mapa das regiões excedidas. Vermelho mais escuro indica maiores quantidades de overdraw.
diagrama venn 
eficiente.
<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>
Observe o uso de CacheMode. Não use essa técnica se alguma das subformas se animar porque o cache de bitmap provavelmente precisará ser regenerado a cada quadro, anulando seu propósito.
Usar XBF2
XBF2 é uma representação binária da marcação XAML que evita todos os custos de análise de texto em runtime. Ele também otimiza seu binário para a criação de carga e árvore e permite "caminho rápido" para tipos XAML melhorarem os custos de criação de heap e objeto, por exemplo VSM, ResourceDictionary, Styles e assim por diante. Ele é completamente mapeado para memória, portanto, não há nenhum volume de heap para carregar e ler uma página XAML. Além disso, reduz o volume de disco de páginas XAML armazenadas em um appx. O XBF2 é uma representação mais compacta e pode reduzir o espaço ocupado em disco por arquivos comparativos XAML/XBF1 em até 50%. Por exemplo, o aplicativo fotos interno viu cerca de 60% redução após a conversão para XBF2 caindo de cerca de cerca de 1 mb de ativos XBF1 para ~400kb de ativos XBF2. Também observamos aplicativos se beneficiarem entre 15 a 20% na CPU e entre 10 a 15% no Win32 heap.
Os controles e dicionários internos XAML que a estrutura fornece já estão totalmente habilitados para XBF2. Para seu próprio aplicativo, verifique se o arquivo de projeto declara TargetPlatformVersion 8.2 ou posterior.
Para verificar se você tem XBF2, abra seu aplicativo em um editor binário; o 12º e o 13º bytes serão 00 02 se você tiver XBF2.