Em que ordem os painéis são os mais eficientes em termos de tempo e desempenho de renderização?

127

Há muitas vezes em que mais de um painel é adequado para o layout que eu quero, mas sei que há uma diferença nos tempos de renderização para diferentes tipos de painéis.

Por exemplo, o MSDN declara que

Um relativamente simples Panel, como, por exemplo Canvas, pode ter desempenho significativamente melhor do que um mais complexo Panel, como Grid.

Então, em termos de tempo e desempenho de renderização, em que ordem os painéis WPF são os mais eficientes?

Painéis WPF:

  • Canvas
  • DockPanel
  • Grid
  • UniformGrid
  • StackPanel
  • WrapPanel
  • VirtualizingPanel / VirtualizingStackPanel

Tenho certeza de que vi uma lista disso em algum lugar on-line, mas não consigo encontrá-la agora.

A resposta ideal que estou procurando me forneceria uma lista de painéis na ordem em que eles renderizariam mais rapidamente. Entendo que o número de filhos é um fator importante na eficiência dos painéis; portanto, para o bem dessa pergunta, suponha que cada painel tenha apenas um Label/ TextBoxpar.

Além disso, eu gostaria de uma lista de exceções, como painéis específicos com desempenho melhor que outros com base em determinadas condições.

Atualizar

Para resumir com base na resposta aceita abaixo, o desempenho do painel é baseado no número e no layout dos itens filhos, no entanto, em geral, a lista do mais rápido para o mais lento é:

  • Canvas
  • StackPanel
  • WrapPanel
  • DockPanel
  • Grid

Além disso, um VirtualizingPanel/ VirtualizingStackPaneldeve sempre ser usado se houver muitos itens que nem sempre cabem na tela.

Eu recomendo que você leia a resposta aceita abaixo para obter mais detalhes antes de escolher um item dessa lista.

Rachel
fonte
É ingênuo assumir que os painéis de virtualização terão sempre um desempenho melhor do que os painéis que não virtualizam?
BoltClock
@BoltClock Acho que depende da quantidade de conteúdo não visível no painel. Se houver muitos itens não visíveis, a VirtualizingStackPaneldefinitivamente terá um desempenho melhor, mas se todos os itens exibidos no painel estiverem visíveis, acho que é melhor usar um painel comum.
Rachel
Obrigado. Faz sentido que seja um desperdício de itens de virtualização, quando todos eles serão exibidos de qualquer maneira.
BoltClock
Além da virtualização, eles têm recursos diferentes ou não seriam controles separados. Eu vou com o que fornece a melhor interface do usuário para o cliente.
paparazzo
1
Você tem certeza de que há uma diferença notável (além da virtualização)? Tudo o que eles precisam fazer é executar um algoritmo de layout relativamente leve. Minúsculo comparado com toda a renderização que se seguirá. Dito isto, a grade provavelmente será a mais lenta (escala ponderada).
Henk Holterman 31/03

Respostas:

130

Eu acho que é mais conciso e compreensível descrever as características de desempenho de cada painel do que tentar oferecer uma comparação absoluta de desempenho relativo.

O WPF faz duas passagens ao renderizar o conteúdo: Medir e Organizar. Cada painel possui características de desempenho diferentes para cada uma dessas duas passagens.

O desempenho da passagem de medida é mais afetado pela capacidade de um painel acomodar o alongamento usando alinhamentos (ou Auto no caso do Grid) e, em seguida, o número de filhos que são esticados ou dimensionados automaticamente. O desempenho do passe Arrange é afetado pela complexidade da interação entre o local do layout de diferentes filhos e, é claro, o número de filhos.

Às vezes, os painéis fornecidos não se prestam facilmente ao layout necessário. Criei um controle que precisava de um número arbitrário de itens para cada um ser posicionado em uma certa porcentagem do espaço disponível. Nenhum dos controles padrão faz isso. Tentar fazê-los fazer isso (através da ligação ao tamanho real do pai) resulta em um desempenho horrível. Criei um painel de layout baseado no Canvas que alcançou o resultado desejado com o mínimo de trabalho (copiei a fonte do canvas e modifiquei cerca de 20 linhas).

Painéis disponíveis:

  • Tela de pintura

    Define uma área na qual você pode posicionar explicitamente elementos filho por coordenadas em relação à área da Tela.

    O Canvas tem o melhor desempenho de todos os painéis para o passe de organização, já que cada item recebe estaticamente um local. O passe de medida também possui excelente desempenho, pois não há conceito de alongamento neste painel; cada criança simplesmente usa seu tamanho nativo.

  • DockPanel

    Define uma área na qual você pode organizar elementos filhos horizontal ou verticalmente, um em relação ao outro.

    O Dockpanel possui um esquema de layout muito simples, onde os itens são adicionados um a um em relação ao item anterior adicionado. Por padrão, a altura ou a largura são determinadas pelo tamanho nativo do item (com base em Superior / Inferior vs Esquerda / Direita, respectivamente) e a outra direção é determinada pela Dockpropriedade se a largura ou a altura não forem definidas. Passe de medição médio a rápido e passe de arranjo médio a rápido.

  • Rede

    Define uma área de grade flexível que consiste em colunas e linhas.

    Esse pode ser o painel com maior desempenho se for utilizado o dimensionamento proporcional ou o dimensionamento automático. Calcular o tamanho do item filho pode ser uma combinação complexa do tamanho nativo do item e do layout especificado pela grade. O layout também é o mais complicado de todos os painéis. Desempenho lento a médio para o passe de medida e desempenho lento a médio para o passe de arranjo.

  • StackPanel

    Organiza os elementos filhos em uma única linha que pode ser orientada horizontal ou verticalmente.

    O StackPanel mede seus filhos usando o dimensionamento nativo ou relativo na direção oposta à sua orientação e o dimensionamento nativo na direção de sua orientação (o alinhamento não faz nada nessa direção). Isso o torna um artista de nível médio nessa área. O passe de arranjo é simples, apenas colocando os itens em ordem. Provavelmente, o segundo melhor desempenho para este passe. Desempenho médio para o passe de medida e desempenho rápido para o passe de layout.

  • VirtualizingPanel

    Fornece uma estrutura para os elementos do painel que virtualizam sua coleta de dados filho. Esta é uma classe abstrata.

    Uma classe base para implementar seu próprio painel de virtualização. Carrega apenas itens visíveis para evitar o uso desnecessário de memória e processador. MUITO mais desempenho para conjuntos de itens. Provavelmente um pouco menos desempenho para itens que cabem na tela devido à verificação de limites. O SDK fornece apenas uma subclasse disso, a VirtualizingStackPanel.

  • WrapPanel

    Posiciona elementos filho na posição sequencial da esquerda para a direita, quebrando o conteúdo para a próxima linha na borda da caixa que o contém. A ordem subsequente ocorre sequencialmente de cima para baixo ou da direita para a esquerda, dependendo do valor da propriedade Orientação.

    A passagem de medida é uma passagem um pouco complexa, em que o maior item de uma linha específica determina a altura da linha e, em seguida, cada item dessa linha usa sua altura nativa (se houver) ou a altura da linha. A aprovação do layout é simples, colocando cada item um após o outro em uma linha e continuando na próxima linha quando não houver espaço suficiente para o próximo item. Passe de medida de desempenho médio. Desempenho médio a rápido para o passe do arranjo.

Referências:

Use o painel mais eficiente sempre que possível

A complexidade do processo de layout é baseada diretamente no comportamento do layout dos elementos derivados do painel que você usa. Por exemplo, um controle Grid ou StackPanel fornece muito mais funcionalidade que um controle Canvas. O preço desse aumento maior na funcionalidade é um aumento maior nos custos de desempenho. No entanto, se você não precisar da funcionalidade fornecida por um controle de grade, use as alternativas menos caras, como uma tela ou um painel personalizado.

Do Otimizando o Desempenho: layout e design

O sistema de layout completa dois passes para cada membro da coleção Children, um passe de medida e um passe de organização. Cada painel filho fornece seus próprios métodos MeasureOverride e ArrangeOverride para atingir seu próprio comportamento de layout específico.

Durante a aprovação da medida, cada membro da coleção Children é avaliado. O processo começa com uma chamada para o método Measure. Esse método é chamado na implementação do elemento Panel pai e não precisa ser chamado explicitamente para que o layout ocorra.

Primeiro, são avaliadas as propriedades de tamanho nativo do UIElement, como Clip e Visibility. Isso gera um valor chamado constraintSize que é passado para o MeasureCore.

Em segundo lugar, as propriedades da estrutura definidas no FrameworkElement são processadas, o que afeta o valor de constraintSize. Essas propriedades geralmente descrevem as características de dimensionamento do UIElement subjacente, como Altura, Largura, Margem e Estilo. Cada uma dessas propriedades pode alterar o espaço necessário para exibir o elemento. MeasureOverride é então chamado com constraintSize como um parâmetro.

Nota Há uma diferença entre as propriedades de Altura e Largura e ActualHeight e ActualWidth. Por exemplo, a propriedade ActualHeight é um valor calculado com base em outras entradas de altura e no sistema de layout. O valor é definido pelo próprio sistema de layout, com base em um passo de renderização real e, portanto, pode ficar um pouco atrás do valor definido das propriedades, como Altura, que são a base da alteração de entrada. Como ActualHeight é um valor calculado, você deve estar ciente de que pode haver várias mudanças relatadas ou incrementais nele, como resultado de várias operações do sistema de layout. O sistema de layout pode estar calculando o espaço de medida necessário para elementos filho, restrições pelo elemento pai e assim por diante. O objetivo final do passe de medida é que a criança determine seu DesiredSize, que ocorre durante a chamada MeasureCore. O valor DesiredSize é armazenado pelo Measure para uso durante o passe de organização do conteúdo.

O passe de organização começa com uma chamada para o método Arrange. Durante o passe de organização, o elemento Panel pai gera um retângulo que representa os limites do filho. Este valor é passado para o método ArrangeCore para processamento.

O método ArrangeCore avalia o DesiredSize do filho e avalia quaisquer margens adicionais que possam afetar o tamanho renderizado do elemento. ArrangeCore gera um organizeSize, que é passado para o método ArrangeOverride do Painel como parâmetro. ArrangeOverride gera o finalSize do filho. Por fim, o método ArrangeCore faz uma avaliação final das propriedades de deslocamento, como margem e alinhamento, e coloca o filho no seu slot de layout. A criança não precisa (e freqüentemente não) preenche todo o espaço alocado. O controle é retornado ao painel pai e o processo de layout é concluído.

De Medir e Organizar Crianças

N / D
fonte
1
Em resposta a um comentário agora excluído: não incluí métricas porque elas não seriam úteis. Existem muitas combinações para uma planilha ser útil. Um método mais útil para otimizar o desempenho seria usar um entendimento geral para escolher os painéis de layout inicial e otimizar conforme necessário a partir daí, usando uma análise da situação real.
N
Obrigado, sua explicação como painéis de WPF realmente ser prestados, e Medida de cada painel / Organizar desempenho é muito melhor do que o que eu estava pedindo :)
Rachel
@mydogisbox Eu não vejo UniformGridna sua lista em lugar algum. Você seria capaz de atualizar sua resposta com esse painel e estima-se medir / organizar o desempenho em relação aos outros tipos de painel?
Rachel
1
@ Rachel O UniformGridnão se destina ao uso no layout do aplicativo. Consulte "Elementos do painel derivado" aqui: msdn.microsoft.com/en-us/library/ms754152.aspx para obter mais informações. Em termos de velocidade, deve ser um pouco mais rápido que um DockPanele um pouco mais lento que um Canvas.
N_A
12

Talvez isso ajude você.

Não apenas para painéis, mas também para todos os aplicativos que você deseja criar no WPF.

Conclui o desenho do WPF e a medição do desempenho.

Ele também possui um aplicativo de teste de desenho, resultados e informações de conclusões para diferentes sistemas operacionais que você deseja direcionar.

mike_sev
fonte
8

Os painéis mencionados são painéis de layout, portanto, uma breve visão geral do sistema de layout sugere que provavelmente não será apenas uma lista simples dos painéis mais eficientes, mas como você usa os painéis que têm o maior efeito na eficiência e no desempenho.

LayoutSystem_Overview :

Na sua forma mais simples, o layout é um sistema recursivo que leva a que um elemento seja dimensionado, posicionado e desenhado. Mais especificamente, o layout descreve o processo de medir e organizar os membros da coleção Children de um elemento Panel. O layout é um processo intensivo. Quanto maior a coleção Children, maior o número de cálculos que devem ser feitos. A complexidade também pode ser introduzida com base no comportamento do layout definido pelo elemento Panel que possui a coleção. Um painel relativamente simples, como o Canvas, pode ter um desempenho significativamente melhor do que um painel mais complexo, como o Grid.

Cada vez que um UIElement filho muda de posição, ele pode acionar uma nova passagem pelo sistema de layout. Portanto, é importante entender os eventos que podem invocar o sistema de layout, pois invocações desnecessárias podem levar a um desempenho ruim do aplicativo. A seguir, descreve o processo que ocorre quando o sistema de layout é chamado.

1. Um UIElement filho inicia o processo de layout, primeiro medindo suas propriedades principais.

2. As propriedades de dimensionamento definidas no FrameworkElement são avaliadas, como Largura, Altura e Margem.

3. A lógica específica do painel é aplicada, como direção da doca ou orientação de empilhamento.

4. O conteúdo é organizado após todas as crianças terem sido medidas.

5. A coleção Children é desenhada na tela.

6. O processo é chamado novamente se Filhos adicionais forem adicionados à coleção, um LayoutTransform for aplicado ou o método UpdateLayout for chamado.

Consulte LayoutSystem_Measure_Arrange para obter mais informações sobre a medição e organização de crianças.

LayoutSystem_Performance :

Layout é um processo recursivo. Cada elemento filho em uma coleção Children é processado durante cada chamada do sistema de layout. Como resultado, o acionamento do sistema de layout deve ser evitado quando não for necessário. As considerações a seguir podem ajudá-lo a obter melhor desempenho.

Esteja ciente de quais alterações no valor da propriedade forçarão uma atualização recursiva pelo sistema de layout.

As propriedades de dependência cujos valores podem causar a inicialização do sistema de layout são marcadas com sinalizadores públicos. AffectsMeasure e AffectsArrange fornecem dicas úteis sobre quais alterações no valor da propriedade forçarão uma atualização recursiva pelo sistema de layout. Em geral, qualquer propriedade que possa afetar o tamanho da caixa delimitadora de um elemento deve ter um sinalizador AffectsMeasure definido como true. Para obter mais informações, consulte Visão geral das propriedades da dependência.

Quando possível, use um RenderTransform em vez de um LayoutTransform.

Um LayoutTransform pode ser uma maneira muito útil de afetar o conteúdo de uma interface do usuário. No entanto, se o efeito da transformação não precisar impactar a posição de outros elementos, é melhor usar um RenderTransform, porque RenderTransform não chama o sistema de layout. LayoutTransform aplica sua transformação e força uma atualização recursiva do layout a considerar a nova posição do elemento afetado.

Evite chamadas desnecessárias para UpdateLayout.

O método UpdateLayout força uma atualização de layout recursiva e geralmente não é necessário. A menos que você tenha certeza de que é necessária uma atualização completa, conte com o sistema de layout para chamar esse método para você.

Ao trabalhar com uma coleção Children grande, considere usar um VirtualizingStackPanel em vez de um StackPanel comum.

Ao virtualizar a coleção filho, o VirtualizingStackPanel mantém apenas objetos na memória que estão atualmente no ViewPort do pai. Como resultado, o desempenho é substancialmente aprimorado na maioria dos cenários.

Otimizando o desempenho: layout e design : este artigo detalha como criar a árvore com eficiência e fornece uma lista simples de painéis com base em sua complexidade

Tela (menos complext = desempenho mais eficiente e melhor)

Rede

Outros painéis (mais complexo = menos eficiente e pior desempenho)

Outras considerações de desempenho a serem observadas : Maneiras de melhorar a velocidade de renderização da interface do usuário WPF

  1. Coloque tudo em cache. Pincéis, cores, geometrias, textos formatados, glifos. (Por exemplo, temos duas classes: RenderTools e TextCache. O processo de renderização de cada unidade endereça a instância compartilhada de ambas as classes. Portanto, se dois gráficos tiverem o mesmo texto, sua preparação será executada apenas uma vez.)
  2. Congelar Freezable, se você planeja usá-lo por um longo tempo. Especialmente geometrias. Geometrias não congeladas complexas executam o HitTest extremamente lento.
  3. Escolha as formas mais rápidas de renderização de cada primitivo. Por exemplo, existem cerca de 6 maneiras de renderizar texto, mas a mais rápida é DrawingContext.DrawGlyphs.
  4. Ativar reciclagem de contêineres. A virtualização traz muitas melhorias de desempenho, mas os contêineres serão descartados e recriados, esse é o padrão. Mas você pode obter mais desempenho reciclando contêineres configurando VirtualizingStackPanel.VirtualizationMode = "Recycling"
  5. A partir daqui : não há limite prático para a quantidade de aninhamento que seu aplicativo pode suportar; no entanto, geralmente é melhor limitar seu aplicativo para usar apenas os painéis que são realmente necessários para o layout desejado. Em muitos casos, um elemento Grid pode ser usado em vez de painéis aninhados devido à sua flexibilidade como um contêiner de layout. Isso pode aumentar o desempenho do seu aplicativo, mantendo elementos desnecessários fora da árvore.
Erick
fonte
2
Essa resposta consiste quase inteiramente em copiar e colar de outras fontes, algumas não atribuídas. Seria muito melhor se você aparasse apenas as partes relevantes, atribuísse corretamente todas as fontes e tentasse responder mais diretamente à pergunta.
N
2
@mydogisbox A resposta é uma compilação de informações, muitos dos mesmos sites que você usou na sua resposta, devo acrescentar. Para não levar em consideração outros aspectos que alteram o desempenho, pode levar a uma resposta incompleta ou o solicitante ainda tem perguntas adicionais, por isso escolhi incluí-las. Enquanto Rachel, com um incrível representante de 21,7K e muita experiência no WPF, já conhece essas informações, outras pessoas que estão olhando para essa pergunta podem desejar essas informações adicionais e relevantes, juntamente com a resposta.
Erick