レンダリング時間とパフォーマンスの観点から、Panelsはどの順序で最も効率的ですか?


127

必要なレイアウトに複数のパネルが適していることはよくありますが、パネルの種類によってレンダリング時間が異なることは知っています。

たとえば、MSDNは次のように述べています。

比較的単純なPanel、などCanvas、より複雑なよりも有意に優れた性能を持つことができるPanel、などGrid

レンダリング時間とパフォーマンスの観点から、WPFパネルはどの順序で最も効率的ですか?

WPFパネル:

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

これのリストをオンラインでどこかで見たと確信していますが、今は見つかりません。

私が探している理想的な答えは、最も速くレンダリングされる順序でパネルのリストを提供することです。子の数がパネルの効率性の大きな要因であることを理解しているので、この質問のために、各パネルにはLabel/ TextBoxペアしかないと仮定します。

さらに、特定の条件に基づいて他のパネルよりも優れたパフォーマンスを発揮する特定のパネルなど、例外のリストをお願いします。

更新

以下の承認された回答に基づいて要約すると、パネルのパフォーマンスは子アイテムの数とレイアウトに基づいていますが、一般に、最も速いものから最も遅いものまでのリストは次のとおりです。

  • Canvas
  • StackPanel
  • WrapPanel
  • DockPanel
  • Grid

さらに、常に画面に収まらないアイテムが多数ある場合は、常にVirtualizingPanel/ VirtualizingStackPanelを使用する必要があります。

このリストからアイテムを選択する前に、以下の承認済みの回答を読んで詳細を確認することを強くお勧めします。


仮想化パネルは常に非仮想化パネルよりも優れたパフォーマンスを発揮すると想定するのはナイーブですか?
BoltClock

@BoltClockパネルに表示されている非表示のコンテンツの量に依存すると思います。非表示のアイテムがたくさんある場合は、VirtualizingStackPanel確実にパフォーマンスが向上しますが、パネルに表示されているすべてのアイテムが表示されている場合は、通常のパネルを使用する方が良いと思います。
Rachel

ありがとう。いずれにせよそれらすべてが表示される場合、それは無駄な仮想化アイテムになることは理にかなっています。
BoltClock

仮想化以外は、機能が異なるか、個別のコントロールではありません。私はお客様に最高のUIを提供するものを採用します。
パパラッツォ2012年

1
(仮想化を除いて)顕著な違いがあると確信していますか?彼らがしなければならないのは、比較的軽量なレイアウトアルゴリズムを実行することだけです。続くすべてのレンダリングと比較して非常に小さい。そうは言っても、グリッドはおそらく最も遅くなります(加重スケーリング)。
Henk Holterman、2012年

回答:


130

絶対的な相対的なパフォーマンス比較を行うよりも、各パネルのパフォーマンス特性を説明する方が簡潔で理解しやすいと思います。

コンテンツをレンダリングするとき、WPFは測定と配置の2つのパスを作成します。各パネルには、これら2つのパスのそれぞれに対して異なるパフォーマンス特性があります。

メジャーパスのパフォーマンスは、配置を使用したスト​​レッチ(またはの場合は自動)に対応するパネルの機能と、Gridストレッチまたは自動サイズ調整される子の数によって最も影響を受けます。アレンジパスのパフォーマンスは、さまざまな子のレイアウト位置と子の数の間の相互作用の複雑さに影響されます。

時々、与えられたパネルは必要なレイアウトに簡単に向いていません。それぞれが使用可能なスペースの特定の割合に配置されるように、任意の数のアイテムを必要とするコントロールを作成しました。デフォルトのコントロールはこれを行いません。(親の実際のサイズにバインドすることによって)これを実行しようとすると、恐ろしいパフォーマンスが発生します。キャンバスに基づいてレイアウトパネルを作成し、最小限の作業で目的の結果を達成しました(キャンバスのソースをコピーして、20行ほど変更しました)。

利用可能なパネル:

  • キャンバス

    Canvas領域を基準にした座標によって子要素を明示的に配置できる領域を定義します。

    Canvasは、各アイテムに静的に位置が割り当てられているため、アレンジパスのすべてのパネルで最高のパフォーマンスを発揮します。このパネルにはストレッチの概念がないため、メジャーパスも優れたパフォーマンスを発揮します。各子は単にそのネイティブサイズを使用します。

  • DockPanel

    相互に相対的に水平または垂直に子要素を配置できる領域を定義します。

    Dockpanelには非常にシンプルなレイアウトスキームがあり、前に追加されたアイテムに対してアイテムが1つずつ追加されます。デフォルトでは、高さまたは幅はアイテムのネイティブサイズによって決定され(それぞれ上/下vs左/右に基づく)Dock、幅または高さが未定義の場合、他の方向はプロパティによって決定されます。中から高速の測定パスと中から高速の配置パス。

  • グリッド

    列と行で構成される柔軟なグリッド領域を定義します。

    プロポーショナルサイジングまたは自動サイジングが使用されている場合、これは最もパフォーマンスを重視するパネルになります。子アイテムのサイズの計算は、アイテムのネイティブサイズとグリッドで指定されたレイアウトの複雑な組み合わせになります。レイアウトもすべてのパネルの中で最も複雑です。メジャーパスの場合は低速から中程度のパフォーマンス、配置パスの場合は低速から中程度のパフォーマンス。

  • StackPanel

    子要素を、水平または垂直に向けることができる単一の行に配置します。

    StackPanelは、その向きとは反対方向のネイティブまたは相対的なサイズと、向きの方向のネイティブのサイズを使用して子を測定します(配置はこの方向では何もしません)。これにより、この分野では中級レベルのパフォーマーになります。アレンジメントパスは、アイテムを順番に配置するだけです。おそらく、このパスで2番目に優れたパフォーマンスです。メジャーパスでは中程度のパフォーマンス、レイアウトパスでは高速なパフォーマンス。

  • VirtualizingPanel

    子データコレクションを仮想化するPanel要素のフレームワークを提供します。これは抽象クラスです。

    独自の仮想化パネルを実装するための基本クラス。メモリとプロセッサの不要な使用を防ぐために、表示アイテムのみをロードします。アイテムのセットのパフォーマンスが大幅に向上しました。境界チェックのため、画面に収まるアイテムのパフォーマンスはおそらく少し低くなります。SDKは、これの1つのサブクラスであるのみを提供しますVirtualizingStackPanel

  • ラップパネル

    子要素を左から右に順番に配置し、内容を含むボックスの端で次の行に分割します。その後の順序付けは、Orientationプロパティの値に応じて、上から下、または右から左に順番に行われます。

    メジャーパスはやや複雑なパスで、特定の行の最大のアイテムが行の高さを決定し、その行の各アイテムはネイティブの高さ(ある場合)または行の高さを使用します。レイアウトパスは単純で、各項目を1行に1つずつ配置し、次の項目のための十分なスペースがない場合は次の行に続きます。中程度のパフォーマンス測定パス。アレンジメントパスのパフォーマンスは中から高速です。

参照:

可能な限り最も効率的なパネルを使用する

レイアウトプロセスの複雑さは、使用するPanel派生要素のレイアウト動作に直接基づいています。たとえば、GridまたはStackPanelコントロールは、Canvasコントロールよりもはるかに多くの機能を提供します。この機能の大幅な増加に対する代償は、パフォーマンスコストの大幅な増加です。ただし、グリッドコントロールが提供する機能を必要としない場合は、キャンバスやカスタムパネルなどの安価な代替手段を使用する必要があります。

パフォーマンスの最適化から:レイアウトとデザイン

レイアウトシステムは、Childrenコレクションのメンバーごとに、メジャーパスとアレンジパスの2つのパスを完了します。各子Panelは、独自のMeasureOverrideメソッドとArrangeOverrideメソッドを提供して、独自の特定のレイアウト動作を実現します。

メジャーパス中に、Childrenコレクションの各メンバーが評価されます。プロセスは、Measureメソッドの呼び出しから始まります。このメソッドは、親Panel要素の実装内で呼び出され、レイアウトを発生させるために明示的に呼び出す必要はありません。

最初に、ClipやVisibilityなど、UIElementのネイティブサイズプロパティが評価されます。これにより、MeasureCoreに渡されるconstraintSizeという名前の値が生成されます。

次に、FrameworkElementで定義されたフレームワークプロパティが処理され、constraintSizeの値に影響します。これらのプロパティは一般に、高さ、幅、マージン、スタイルなど、基になるUIElementのサイズ設定特性を記述します。これらの各プロパティは、要素を表示するために必要なスペースを変更できます。次に、MeasureOverrideが、constraintSizeをパラメーターとして呼び出されます。

注意HeightとWidthのプロパティとActualHeightとActualWidthのプロパティには違いがあります。たとえば、ActualHeightプロパティは、他の高さ入力とレイアウトシステムに基づいて計算された値です。この値は、実際のレンダリングパスに基づいてレイアウトシステム自体によって設定されるため、入力の変更の基礎となるHeightなどのプロパティの設定値よりもわずかに遅れることがあります。ActualHeightは計算値であるため、レイアウトシステムによるさまざまな操作の結果として、レポートされた変更が複数または段階的に報告される可能性があることに注意してください。レイアウトシステムは、子要素に必要なメジャースペース、親要素による制約などを計算している場合があります。メジャーパスの最終的な目標は、子供がそのDesiredSizeを決定することです。これは、MeasureCore呼び出し中に発生します。DesiredSize値は、コンテンツ配置パス中に使用するためにMeasureによって格納されます。

アレンジパスは、Arrangeメソッドの呼び出しで始まります。配置パス中に、親のPanel要素は、子の境界を表す長方形を生成します。この値は、処理のためにArrangeCoreメソッドに渡されます。

ArrangeCoreメソッドは、子のDesiredSizeを評価し、要素のレンダリングサイズに影響を与える可能性がある追加のマージンを評価します。ArrangeCoreは、パラメーターとしてPanelのArrangeOverrideメソッドに渡される、arrangeSizeを生成します。ArrangeOverrideは、子のfinalSizeを生成します。最後に、ArrangeCoreメソッドは、マージンや配置などのオフセットプロパティの最終評価を行い、レイアウトスロット内に子を配置します。子は割り当てられたスペース全体を埋める必要はありません(多くの場合は埋めません)。次に、コントロールが親パネルに戻り、レイアウトプロセスが完了します。

子供の測定と配置から


1
削除されたコメントへの対応:役に立たないので、指標を含めませんでした。組み合わせが多すぎて、スプレッドシートが役に立ちません。パフォーマンスを最適化するためのより有用な方法は、一般的な理解を使用して初期レイアウトパネルを選択し、実際の状況の分析を使用してそこから必要に応じて最適化することです。
N_A

ありがとう、WPFパネルが実際にレンダリングされる方法、および各パネルの測定/配置のパフォーマンスは、私が求めていたものよりもはるかに優れています:)
Rachel

@mydogisbox UniformGridどこにもリストに表示されません。そのパネルで回答を更新できますか?それは、他のパネルタイプに関連して測定/配置の推定パフォーマンスです。
レイチェル

1
@Rachel The UniformGridは、アプリケーションレイアウトでの使用を意図していません。詳細については、こちらの「派生パネル要素」:msdn.microsoft.com/en-us/library/ms754152.aspx参照してください。速度に関しては、aよりも少し速く、a DockPanelよりも少し遅いはずCanvasです。
N_A

12

多分これはあなたを助けるでしょう。

パネルだけでなく、WPFで作成するすべてのアプリケーションにも使用できます。

これで、WPFの描画と測定のパフォーマンスは終了です。

また、対象とするさまざまなオペレーティングシステムの図面テストアプリケーション、結果、および結論に関する情報も含まれています。


8

あなたが言及するパネルはレイアウトパネルであるため、レイアウトシステムの簡単な概要は、最も効率的なパネルの単純なリストではなく、効率とパフォーマンスに最大の影響を与えるパネルの使用方法になる可能性が高いことを示唆しています。

LayoutSystem_Overview

最もシンプルなレイアウトは、要素のサイズ設定、配置、描画につながる再帰的なシステムです。より具体的には、レイアウトは、Panel要素のChildrenコレクションのメンバーを測定して配置するプロセスを示します。レイアウトは集中的なプロセスです。Childrenコレクションが大きいほど、実行する必要がある計算の数が多くなります。コレクションを所有するPanel要素によって定義されたレイアウト動作に基づいて複雑さを導入することもできます。Canvasなどの比較的単純なPanelは、Gridなどのより複雑なPanelよりもパフォーマンスが大幅に向上します。

子UIElementがその位置を変更するたびに、レイアウトシステムによって新しいパスをトリガーする可能性があります。したがって、不必要な呼び出しによってアプリケーションのパフォーマンスが低下する可能性があるため、レイアウトシステムを呼び出すことができるイベントを理解することが重要です。次に、レイアウトシステムが呼び出されたときに発生するプロセスについて説明します。

1.子UIElementは、最初にコアプロパティを測定して、レイアウトプロセスを開始します。

2.幅、高さ、マージンなど、FrameworkElementで定義されたサイズ変更プロパティが評価されます。

3.ドックの方向やスタックの向きなど、パネル固有のロジックが適用されます。

4.コンテンツは、すべての子供が測定された後に配置されます。

5. Childrenコレクションが画面に描画されます。

6.コレクションに子がさらに追加された場合、LayoutTransformが適用された場合、またはUpdateLayoutメソッドが呼び出された場合、プロセスは再度呼び出されます。

子の測定と配置の詳細については、LayoutSystem_Measure_Arrangeを参照してください

LayoutSystem_Performance

レイアウトは再帰的なプロセスです。Childrenコレクション内の各子要素は、レイアウトシステムを呼び出すたびに処理されます。その結果、レイアウトシステムが不要な場合は、トリガーしないでください。以下の考慮事項は、パフォーマンスの向上に役立ちます。

どのプロパティ値の変更がレイアウトシステムによる再帰的な更新を強制することに注意してください。

値によってレイアウトシステムが初期化される依存関係プロパティは、パブリックフラグでマークされます。AffectsMeasureとAffectsArrangeは、どのプロパティ値の変更がレイアウトシステムによる再帰的な更新を強制するかについて、有用な手がかりを提供します。一般に、要素の境界ボックスのサイズに影響を与える可能性のあるプロパティでは、AffectsMeasureフラグをtrueに設定する必要があります。詳細については、「依存関係プロパティの概要」を参照してください。

可能な場合は、LayoutTransformの代わりにRenderTransformを使用してください。

LayoutTransformは、ユーザーインターフェイス(UI)のコンテンツに影響を与える非常に便利な方法です。ただし、変換の効果が他の要素の位置に影響を与える必要がない場合は、RenderTransformがレイアウトシステムを呼び出さないため、代わりにRenderTransformを使用することをお勧めします。LayoutTransformはその変換を適用し、影響を受ける要素の新しい位置を考慮に入れて再帰的なレイアウト更新を強制します。

UpdateLayoutへの不要な呼び出しを避けます。

UpdateLayoutメソッドはレイアウトの再帰的な更新を強制するため、多くの場合、必要ありません。完全な更新が必要であることが確実でない限り、レイアウトシステムに依存してこのメ​​ソッドを呼び出します。

大規模なChildrenコレクションを操作する場合は、通常のStackPanelではなくVirtualizingStackPanelの使用を検討してください。

子コレクションを仮想化することにより、VirtualizingStackPanelは、現在親のViewPort内にあるオブジェクトのみをメモリに保持します。その結果、ほとんどのシナリオでパフォーマンスが大幅に向上します。

パフォーマンスの最適化:レイアウトとデザイン:この記事では、ツリーを効率的に構築する方法について詳しく説明し、複雑さに基づいてパネルの簡単なリストを提供します

キャンバス(最小複合体=より効率的で優れたパフォーマンス)

グリッド

その他のパネル(より複雑=効率が低く、パフォーマンスが悪い)

注意すべきその他のパフォーマンスの考慮事項: WPF UIレンダリング速度を改善する方法

  1. すべてをキャッシュします。ブラシ、色、ジオメトリ、フォーマットされたテキスト、グリフ。(たとえば、RenderToolsとTextCacheの2つのクラスがあります。各ユニットのレンダリングプロセスは、両方のクラスの共有インスタンスに対応します。したがって、2つのチャートに同じテキストがある場合、その準備は1回だけ実行されます。)
  2. Freeze Freezable(長期間使用する予定の場合)。特にジオメトリ。複雑なフリーズされていないジオメトリは、HitTestの実行を非常に遅くします。
  3. 各プリミティブをレンダリングする最速の方法を選択します。たとえば、テキストレンダリングには6つの方法がありますが、最速はDrawingContext.DrawGlyphsです。
  4. コンテナのリサイクルを有効にします。仮想化により、多くのパフォーマンスが向上しますが、コンテナーは破棄され、再作成されます。これがデフォルトです。ただし、VirtualizingStackPanel.VirtualizationMode = "Recycling"を設定してコンテナーをリサイクルすることで、より多くのパフォーマンスを得ることができます
  5. ここから:アプリケーションがサポートできるネストの量に実際的な制限はありませんが、通常、アプリケーションを制限して、目的のレイアウトに実際に必要なパネルのみを使用することをお勧めします。多くの場合、レイアウトコンテナとしての柔軟性により、ネストされたパネルの代わりにグリッド要素を使用できます。これにより、不要な要素をツリーから除外することで、アプリケーションのパフォーマンスを向上させることができます。

2
この回答は、ほとんどすべてが他のソースからのコピーと貼り付けで構成されています。関連する部分だけに切り詰め、すべてのソースを正しく帰属させて、質問にもっと直接回答しようとすると、はるかに良いでしょう。
N_A

2
@mydogisbox答えは情報の集まりです。答えで使用したのと同じサイトの多くが追加される場合があります。パフォーマンスを変更する他の側面を考慮しないために、回答が不完全になったり、質問者がまだ追加の質問をしたりする可能性があるため、それらを含めることにしました。すばらしい21.7Kの担当者と多くのWPFの経験を持つレイチェルは、すでにこの情報を知っているかもしれませんが、この質問を見ている他の人は、回答とともにこの追加の信頼できる情報を望むかもしれません。
エリック
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.