In quale ordine i pannelli sono i più efficienti in termini di tempo di rendering e prestazioni?


127

Ci sono molte volte in cui più di un pannello è adatto al layout che desidero, tuttavia so che c'è una differenza nei tempi di rendering per diversi tipi di pannelli.

Ad esempio, MSDN afferma che

Un relativamente semplice Panel, ad esempio Canvas, può avere prestazioni significativamente migliori di un più complesso Panel, come ad esempio Grid.

Quindi, in termini di tempo di rendering e prestazioni, in quale ordine i pannelli WPF sono i più efficienti?

Pannelli WPF:

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

Sono abbastanza sicuro di aver visto un elenco di questo da qualche parte online, ma non riesco a trovarlo ora.

La risposta ideale che sto cercando mi fornirebbe un elenco di pannelli nell'ordine in cui renderebbero più velocemente. Capisco che il numero di bambini è un fattore determinante per quanto siano efficienti i pannelli, quindi per il bene di questa domanda, supponiamo che ogni pannello abbia solo una Label/ TextBoxcoppia.

Inoltre, vorrei un elenco di eccezioni, come pannelli specifici che funzionano meglio di altri in base a determinate condizioni.

Aggiornare

Per riassumere in base alla risposta accettata di seguito, le prestazioni del pannello si basano sul numero e sulla disposizione degli elementi figlio, tuttavia in generale l'elenco dal più veloce al più lento è:

  • Canvas
  • StackPanel
  • WrapPanel
  • DockPanel
  • Grid

Inoltre, un VirtualizingPanel/ VirtualizingStackPaneldovrebbe sempre essere usato se ci sono molti oggetti che non si adattano sempre allo schermo.

Consiglio vivamente di leggere la risposta accettata di seguito per maggiori dettagli prima di scegliere un elemento da questo elenco.


È ingenuo presumere che i pannelli di virtualizzazione funzionino invariabilmente meglio dei pannelli non di virtualizzazione?
BoltClock

@BoltClock Penso che dipenda dalla quantità di contenuto non visibile presente nel pannello. Se ci sono molti oggetti non visibili, VirtualizingStackPanelsicuramente funzionerà meglio, ma se tutti gli elementi visualizzati nel pannello sono visibili di quanto penso sia meglio usare un pannello normale.
Rachel,

Grazie. Ha senso che sarebbe uno spreco di oggetti di virtualizzazione, quando tutti verranno comunque visualizzati.
BoltClock

Oltre alla virtualizzazione hanno caratteristiche diverse o non sarebbero controlli separati. Vado con ciò che fornisce la migliore interfaccia utente al cliente.
paparazzo,

1
Sei sicuro che ci sia una notevole differenza (a parte la virtualizzazione)? Tutto quello che devono fare è eseguire un algoritmo di layout relativamente leggero. Minuscolo rispetto a tutto il rendering che seguirà. Detto questo, la griglia sarà probabilmente la più lenta (ridimensionamento ponderato).
Henk Holterman,

Risposte:


130

Penso che sia più conciso e comprensibile descrivere le caratteristiche prestazionali di ciascun pannello piuttosto che cercare di dare un confronto assoluto delle prestazioni relative.

WPF esegue due passaggi durante il rendering del contenuto: Misura e Disponi. Ogni pannello ha caratteristiche prestazionali diverse per ciascuno di questi due passaggi.

Le prestazioni del passaggio di misura sono maggiormente influenzate dalla capacità di un pannello di adattarsi allo stretching usando gli allineamenti (o Auto nel caso del Grid) e quindi il numero di bambini che sono allungati o dimensionati automaticamente. Le prestazioni del pass Arrange sono influenzate dalla complessità dell'interazione tra la posizione del layout di diversi bambini e quindi ovviamente il numero di bambini.

A volte i pannelli indicati non si prestano facilmente al layout necessario. Ho creato un controllo che richiedeva che un numero arbitrario di elementi fosse posizionato su una determinata percentuale dello spazio disponibile. Nessuno dei controlli predefiniti lo fa. Tentare di farlo fare (vincolando le dimensioni reali del genitore) si traduce in prestazioni orribili. Ho creato un pannello di layout basato sulla tela che ha ottenuto il risultato desiderato con un lavoro minimo (ho copiato l'origine della tela e ne ho modificato circa 20 righe).

Pannelli disponibili:

  • Tela

    Definisce un'area all'interno della quale è possibile posizionare in modo esplicito elementi figlio mediante coordinate relative all'area di disegno.

    La tela offre le migliori prestazioni di tutti i pannelli per il passaggio di organizzazione poiché a ciascun articolo viene assegnata staticamente una posizione. Anche il passaggio di misura ha prestazioni eccellenti poiché non esiste alcun concetto di allungamento in questo pannello; ogni bambino usa semplicemente la sua dimensione nativa.

  • DockPanel

    Definisce un'area all'interno della quale è possibile disporre gli elementi figlio in orizzontale o in verticale, l'uno rispetto all'altro.

    Dockpanel ha uno schema di layout molto semplice in cui gli elementi vengono aggiunti uno per uno rispetto all'elemento precedente aggiunto. Per impostazione predefinita, l'altezza o la larghezza sono determinate dalle dimensioni native dell'articolo (basate rispettivamente su Alto / Basso vs Sinistra / Destra) e l'altra direzione è determinata dalla Dockproprietà se la larghezza o l'altezza non sono definite. Passaggio di misura medio-veloce e passaggio di disposizione medio-veloce.

  • Griglia

    Definisce un'area della griglia flessibile costituita da colonne e righe.

    Questo può essere il pannello ad alte prestazioni se viene utilizzato il dimensionamento proporzionale o il dimensionamento automatico. Il calcolo della dimensione dell'elemento figlio può essere una combinazione complessa della dimensione nativa dell'elemento e del layout specificato dalla griglia. Il layout è anche il più complicato di tutti i pannelli. Prestazioni da lente a medie per il passaggio di misura e prestazioni da lente a medie per il passaggio di disposizione.

  • StackPanel

    Dispone gli elementi figlio in un'unica linea che può essere orientata in senso orizzontale o verticale.

    StackPanel misura i suoi figli usando il dimensionamento nativo o relativo nella direzione opposta rispetto al suo orientamento e il dimensionamento nativo nella direzione del suo orientamento (l'allineamento non fa nulla in questa direzione). Questo lo rende un artista di medio livello in questo settore. Il pass Arrangiamento è semplicemente, semplicemente disponendo gli articoli in ordine. Probabilmente la seconda migliore prestazione per questo passaggio. Prestazioni medie per il passaggio di misura e prestazioni veloci per il passaggio di layout.

  • VirtualizingPanel

    Fornisce un framework per gli elementi del pannello che virtualizzano la loro raccolta di dati figlio. Questa è una classe astratta.

    Una classe di base per l'implementazione del proprio pannello di virtualizzazione. Carica solo elementi visibili per impedire l'uso non necessario della memoria e del processore. MOLTO più performante per gruppi di articoli. Probabilmente leggermente meno performante per gli elementi che si adattano allo schermo a causa del controllo dei limiti. L'SDK fornisce solo una sottoclasse di questo, il VirtualizingStackPanel.

  • WrapPanel

    Posiziona gli elementi figlio in posizione sequenziale da sinistra a destra, interrompendo il contenuto alla riga successiva sul bordo del riquadro di contenimento. L'ordinamento successivo avviene in sequenza dall'alto verso il basso o da destra a sinistra, a seconda del valore della proprietà Orientamento.

    Il passaggio di misura è un passaggio alquanto complesso in cui l'elemento più grande per una determinata riga determina l'altezza della riga e quindi ogni elemento su quella riga utilizza l'altezza nativa (se ne ha una) o l'altezza della riga. Il passaggio del layout è semplice, posizionando ogni elemento uno dopo l'altro su una riga e proseguendo sulla riga successiva quando non c'è spazio sufficiente per l'elemento successivo. Pass per la misura di prestazioni medie. Prestazioni medio-veloci per il passaggio della disposizione.

Riferimenti:

Utilizzare il pannello più efficiente ove possibile

La complessità del processo di layout si basa direttamente sul comportamento del layout degli elementi derivati ​​dal Pannello che utilizzate. Ad esempio, un controllo Grid o StackPanel offre molte più funzionalità rispetto a un controllo Canvas. Il prezzo per questo maggiore aumento di funzionalità è un maggiore aumento dei costi delle prestazioni. Tuttavia, se non si richiede la funzionalità fornita da un controllo Grid, è necessario utilizzare le alternative meno costose, come una tela o un pannello personalizzato.

Dall'ottimizzazione delle prestazioni: layout e design

Il sistema di layout completa due passaggi per ciascun membro della raccolta Bambini, un passaggio di misure e un passaggio di organizzazione. Ogni pannello figlio fornisce i propri metodi MeasureOverride e ArrangeOverride per ottenere il proprio comportamento di layout specifico.

Durante il passaggio delle misure, viene valutato ciascun membro della raccolta Bambini. Il processo inizia con una chiamata al metodo Measure. Questo metodo viene chiamato nell'implementazione dell'elemento del pannello padre e non deve essere chiamato esplicitamente perché si verifichi il layout.

Innanzitutto, vengono valutate le proprietà della dimensione nativa di UIElement, come Clip e Visibilità. Ciò genera un valore denominato vincoloSize che viene passato a MeasureCore.

In secondo luogo, vengono elaborate le proprietà del framework definite in FrameworkElement, che influisce sul valore di restringSize. Queste proprietà in genere descrivono le caratteristiche di dimensionamento del UIElement sottostante, come altezza, larghezza, margine e stile. Ognuna di queste proprietà può cambiare lo spazio necessario per visualizzare l'elemento. Viene quindi chiamato MeasureOverride con vincoloSize come parametro.

Nota Esiste una differenza tra le proprietà di Height e Width e ActualHeight e ActualWidth. Ad esempio, la proprietà ActualHeight è un valore calcolato basato su altri input di altezza e sul sistema di layout. Il valore viene impostato dal sistema di layout stesso, basato su un passaggio di rendering effettivo, e pertanto potrebbe essere leggermente in ritardo rispetto al valore impostato di proprietà, come Altezza, che sono alla base della modifica dell'input. Poiché ActualHeight è un valore calcolato, è necessario tenere presente che potrebbero esserci modifiche multiple o incrementali segnalate a seguito di varie operazioni da parte del sistema di layout. Il sistema di layout potrebbe calcolare lo spazio di misura richiesto per gli elementi figlio, i vincoli dell'elemento padre e così via. L'obiettivo finale del passaggio di misura è che il bambino determini la sua dimensione desiderata, che si verifica durante la chiamata MeasureCore. Il valore DesiredSize è memorizzato da Measure per l'uso durante il passaggio di organizzazione del contenuto.

Il passaggio organizza inizia con una chiamata al metodo Arrange. Durante il passaggio di disposizione, l'elemento del pannello padre genera un rettangolo che rappresenta i limiti del figlio. Questo valore viene passato al metodo ArrangeCore per l'elaborazione.

Il metodo ArrangeCore valuta DesiredSize del figlio e valuta eventuali margini aggiuntivi che possono influire sulla dimensione di rendering dell'elemento. ArrangeCore genera un arrangiamento, che viene passato al metodo ArrangeOverride del Pannello come parametro. ArrangeOverride genera la dimensione finale del figlio. Infine, il metodo ArrangeCore esegue una valutazione finale delle proprietà di offset, come margine e allineamento, e inserisce il bambino nel suo slot di layout. Il bambino non deve (e spesso non lo fa) riempire l'intero spazio assegnato. Il controllo viene quindi restituito al pannello padre e il processo di layout è completo.

Dalla misurazione e organizzazione dei bambini


1
In risposta a un commento ora cancellato: non ho incluso le metriche perché non sarebbero state utili. Esistono troppe combinazioni per rendere utile un foglio di calcolo. Un metodo più utile per ottimizzare le prestazioni sarebbe quello di utilizzare una comprensione generale per selezionare i pannelli di layout iniziali e quindi ottimizzare, se necessario, da lì utilizzando un'analisi della situazione reale.
N_A,

Grazie, la tua spiegazione su come vengono effettivamente resi i pannelli WPF e le prestazioni di Misura / Disposizione di ciascun pannello sono di gran lunga migliori di quelle che stavo chiedendo :)
Rachel

@mydogisbox Non vedo la UniformGridtua lista da nessuna parte. Saresti in grado di aggiornare la tua risposta con quel pannello e la sua prestazione stimata misura / organizza in relazione agli altri tipi di pannello?
Rachel,

1
@Rachel The UniformGridnon è destinato all'uso nel layout dell'applicazione. Vedere "Elementi del pannello derivati" qui: msdn.microsoft.com/en-us/library/ms754152.aspx per ulteriori informazioni. Per quanto riguarda la velocità, dovrebbe essere leggermente più veloce di a DockPanele leggermente più lento di a Canvas.
N_A,

12

Forse questo ti aiuterà.

Non solo per i pannelli ma anche per ogni applicazione che vuoi realizzare in WPF.

Conclude il disegno WPF e la misurazione delle prestazioni.

Ha anche un'applicazione di test di disegno, risultati e informazioni sulle conclusioni per i diversi sistemi operativi che si desidera targetizzare.


8

I pannelli che menzioni sono pannelli di layout, quindi una breve panoramica del sistema di layout suggerisce che probabilmente non sarà solo un semplice elenco del pannello più efficiente, ma come utilizzi i pannelli che hanno il maggiore effetto su efficienza e prestazioni.

LayoutSystem_Overview :

Nella sua forma più semplice, il layout è un sistema ricorsivo che porta a un elemento dimensionato, posizionato e disegnato. Più specificamente, il layout descrive il processo di misurazione e organizzazione dei membri della collezione Children di un elemento Panel. Il layout è un processo intenso. Maggiore è la raccolta Bambini, maggiore è il numero di calcoli che devono essere effettuati. La complessità può anche essere introdotta in base al comportamento del layout definito dall'elemento Panel proprietario della raccolta. Un pannello relativamente semplice, come Canvas, può avere prestazioni significativamente migliori rispetto a un pannello più complesso, come Grid.

Ogni volta che un UIElement figlio cambia posizione, ha il potenziale per innescare un nuovo passaggio dal sistema di layout. Pertanto, è importante comprendere gli eventi che possono invocare il sistema di layout, in quanto l'invocazione non necessaria può portare a scarse prestazioni dell'applicazione. Di seguito viene descritto il processo che si verifica quando viene invocato il sistema di layout.

1. Un UIElement figlio inizia il processo di layout misurando innanzitutto le sue proprietà principali.

2. Vengono valutate le proprietà di dimensionamento definite su FrameworkElement, come Larghezza, Altezza e Margine.

3. Viene applicata la logica specifica del pannello, come la direzione del dock o l'orientamento dello stacking.

4. Il contenuto è organizzato dopo che tutti i bambini sono stati misurati.

5. La raccolta Bambini viene disegnata sullo schermo.

6. Il processo viene nuovamente richiamato se alla raccolta vengono aggiunti ulteriori elementi secondari, viene applicato un LayoutTransform o viene chiamato il metodo UpdateLayout.

Vedere LayoutSystem_Measure_Arrange per ulteriori informazioni sulla misurazione e l'organizzazione dei bambini

LayoutSystem_Performance :

Il layout è un processo ricorsivo. Ogni elemento figlio in una raccolta Bambini viene elaborato durante ogni invocazione del sistema di layout. Di conseguenza, l'attivazione del sistema di layout dovrebbe essere evitata quando non è necessario. Le seguenti considerazioni possono aiutarti a ottenere prestazioni migliori.

Essere consapevoli di quali modifiche al valore della proprietà forzeranno un aggiornamento ricorsivo da parte del sistema di layout.

Le proprietà di dipendenza i cui valori possono causare l'inizializzazione del sistema di layout sono contrassegnate con flag pubblici. AffectsMeasure e AffectsArrange forniscono utili indicazioni su quali modifiche al valore della proprietà forzeranno un aggiornamento ricorsivo da parte del sistema di layout. In generale, qualsiasi proprietà che può influire sulla dimensione del rettangolo di selezione di un elemento dovrebbe avere un flag AffectsMeasure impostato su true. Per ulteriori informazioni, consultare Panoramica delle proprietà di dipendenza.

Se possibile, utilizzare un RenderTransform anziché un LayoutTransform.

Un LayoutTransform può essere un modo molto utile per influenzare il contenuto di un'interfaccia utente (UI). Tuttavia, se l'effetto della trasformazione non deve influire sulla posizione di altri elementi, è preferibile utilizzare invece RenderTransform, poiché RenderTransform non invoca il sistema di layout. LayoutTransform applica la sua trasformazione e impone un aggiornamento di layout ricorsivo per tenere conto della nuova posizione dell'elemento interessato.

Evita le chiamate non necessarie a UpdateLayout.

Il metodo UpdateLayout impone un aggiornamento del layout ricorsivo e spesso non è necessario. A meno che non si sia sicuri che sia necessario un aggiornamento completo, fare affidamento sul sistema di layout per chiamare questo metodo.

Quando lavori con una grande raccolta di bambini, prendi in considerazione l'utilizzo di un VirtualizingStackPanel invece di un normale StackPanel.

Virtualizzando la raccolta figlio, VirtualizingStackPanel mantiene solo gli oggetti in memoria che si trovano attualmente nel ViewPort del genitore. Di conseguenza, le prestazioni sono notevolmente migliorate nella maggior parte degli scenari.

Ottimizzazione delle prestazioni: layout e progettazione : questo articolo illustra in dettaglio come costruire l'albero in modo efficiente e fornisce un semplice elenco di pannelli in base alla loro complessità

Canvas (meno complext = prestazioni più efficienti e migliori)

Griglia

Altri pannelli (più complessi = prestazioni meno efficienti e peggiori)

Altre considerazioni sulle prestazioni a cui prestare attenzione: Modi per migliorare la velocità di rendering dell'interfaccia utente di WPF

  1. Metti tutto nella cache. Pennelli, colori, geometrie, testi formattati, glifi. (Ad esempio abbiamo due classi: RenderTools e TextCache. Il processo di rendering di ciascuna unità si indirizza all'istanza condivisa di entrambe le classi. Quindi, se due grafici hanno lo stesso testo, la sua preparazione viene eseguita una sola volta.)
  2. Congela Freezable, se hai intenzione di usarlo per molto tempo. Soprattutto le geometrie. Geometrie complesse non ventilate eseguono HitTest estremamente lentamente.
  3. Scegli i modi più veloci di rendering di ogni primitiva. Ad esempio, ci sono circa 6 modi di rendering del testo, ma il più veloce è DrawingContext.DrawGlyphs.
  4. Abilita riciclo container. La virtualizzazione offre molti miglioramenti delle prestazioni, ma i contenitori verranno eliminati e ricreati, questa è l'impostazione predefinita. Ma puoi ottenere maggiori prestazioni riciclando i contenitori impostando VirtualizingStackPanel.VirtualizationMode = "Riciclaggio"
  5. Da qui : non esiste un limite pratico alla quantità di annidamento supportata dall'applicazione, tuttavia è generalmente consigliabile limitare l'applicazione per utilizzare solo i pannelli effettivamente necessari per il layout desiderato. In molti casi, un elemento Grid può essere utilizzato al posto dei pannelli nidificati grazie alla sua flessibilità come contenitore di layout. Ciò può aumentare le prestazioni della tua applicazione mantenendo gli elementi non necessari fuori dalla struttura.

2
Questa risposta consiste quasi interamente nella copia e incolla da altre fonti, alcune non attribuite. Sarebbe molto meglio se lo riducessi alle sole parti pertinenti, attribuissi correttamente tutte le fonti e provassi a rispondere più direttamente alla domanda.
N_A,

2
@mydogisbox La risposta è una raccolta di informazioni, potrei aggiungere molti degli stessi siti che hai usato nella tua risposta. Non prendere in considerazione altri aspetti che cambiano le prestazioni può portare a una risposta incompleta o chi ha ancora domande aggiuntive, quindi ho scelto di includerle. Mentre Rachel con un incredibile rappresentante di 21,7 K e molta esperienza WPF potrebbe già conoscere queste informazioni, altri che stanno esaminando questa domanda potrebbero desiderare queste informazioni aggiuntive e relative alla risposta.
Erick,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.