19

次の TextBlocks の Bindings のうち、より多くのパフォーマンスを犠牲にするものはどれですか:

<Window  
  x:Name="Me"
  x:Class="MainWindow"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
  xmlns:src="clr-namespace:WpfApplication1" 
  Title="MainWindow">
  <StackPanel>
    <TextBlock Text="{Binding Title, ElementName=Me}"/>
    <TextBlock Text="{Binding Title, RelativeSource={RelativeSource AncestorType={x:Type src:MainWindow}}}"/>
  </StackPanel>    
</Window>

TextBlocks が多くの兄弟と祖先を持つ高いネストレベルにある場合、私の質問は異なる場合があると確信しています。

考慮事項

(個人的な考えのみに基づいているため、それぞれの特定の点で間違っている可能性があります!):

  • ElementName:

    • 現在の要素を検索して比較し、そのすべての子、兄弟、叔父、祖先を含む大叔父 (登録されているすべての名前の HashTable があるのではないでしょうか?)
    • コントロールのプロパティを取得するNameと、 を呼び出すよりもパフォーマンスが低下しますGetType
    • 文字列を比較する方が、型を比較す​​るよりも安価です。特に、ほとんどのコントロールにセットがないことがわかっている場合はなおさらNameです。
  • FindAncestor:

    • 兄弟の「叔父」、「いとこ」などではなく、祖先を介してのみ反復します。
    • GetType先祖の型を決定するために使用される可能性が最も高いです。GetType は、単純なNameプロパティ ゲッターよりもパフォーマンスが高くなります (DP が異なる可能性がありますか?)
4

3 に答える 3

31

どちらが速いと思うかについて議論することで、この種のことに答えようとするのは通常、ひどい考えです。それを測定するための実験を構築する方がはるかに優れています。

セットアップを少し変更しました。関連する Xaml を UserControl に入れ、プロパティがないため、Nameプロパティにバインドしました。次に、コントロールの新しいインスタンスを作成して UI に追加するコードをいくつか書き、 を使用して、その作成と読み込みにかかる時間を測定しました。(ユーザー コントロールを構築する直前にタイミングを開始し、ユーザー コントロールがイベントを発生させた直後に停止します。)UserControlTitleStopwatchLoaded

このコードを 1DispatcherTimer秒間に 20 回実行するので、実験誤差を減らすために多くの測定を行うことができます。デバッグおよび診断コードによる歪みを最小限に抑えるために、リリース ビルドで実行しており、2000 回の反復が完了した後にのみ平均を計算して出力しています。

2000 回の反復の後、ElementNameアプローチは平均 887us になります。

2000 回の反復後、RelativeSourceアプローチは平均 959us になります。

そのElementNameため、この特定の実験では、 よりわずかに高速ですRelativeSource。名前付き要素が 1 つしかない単純なものUserControlを aGridと oneだけでロードすると、このアプローチでは、ロードにかかる時間の 92% がかかるように見えます。TextBlockElementNameRelativeSource

もちろん、ここでは小さな人工的な例を測定しています。ElementName アプローチのパフォーマンスは、スコープ内の名前付き要素の数によって異なる場合があります。また、実際のシナリオではまったく異なる結果をもたらす可能性がある、その他の予期しない要因が存在する可能性があります。したがって、より良い画像を取得したい場合は、実際のアプリケーションのコンテキストで同様の測定を実行することをお勧めします.

1 の代わりに 10 の TextBlocks を使用して実験を繰り返したところ、ElementName平均 2020us でしたが、RelativeSourceアプローチは平均 2073us で、両方のテストで 2000 回以上の反復が行われました。奇妙なことに、ここでは相対的にだけでなく絶対的にも小さな差があります。1 素子の例では 72us の差が示されましたが、10 素子の例では 53us の差が示されました。

ノイズを最小限に抑えるためにできるだけ少ないもので慎重に構成されたマシンではなく、メインマシンでテストを実行することで、より多くの変動を引き起こしているのではないかと疑い始めています.

もう 1 つのバリエーション: まだ 10 個のバインドされたテキスト ブロックがあるので、さらに 10 個の空のバインドされていない名前付きテキスト ブロックをユーザー コントロールに追加しました。ここでのアイデアは、より多くの名前付きのものを導入することでしたElementName.11 個の名前付きのものの中から名前付きのアイテムを見つける必要があります. の平均ElementNameは現在 2775us です。これらの追加の 10 個の名前付き要素を使用したRelativeSourceアプローチは、3041us で発表されました。

繰り返しますが、ここで私のデスクトップ マシンの変動性を疑ってRelativeSourceいますElementName

とにかく、ここでロードするコストは、使用するバインディングのスタイルよりも要素の数にはるかに敏感であることは明らかです明らかに小さな利点がありますが、ElementName必然的に高速であるという結論の妥当性に疑いを投げかけるのに十分小さい(そして奇妙な結果を伴う).

そのため、より正確な画像を得るために、より慎重な実験を行うことができました。しかし、私の見解では、通常のコンピューターで実行したときのパフォーマンスの大きな違いを決定的に示すことができない場合、どちらが速いかを議論するのは基本的に時間の無駄です。

結論として、ここでパフォーマンスに焦点を当てるのは間違っています。より読みやすいコードを選択してください。

于 2010-12-01T12:57:31.937 に答える
4

2 つのうちの後者は、ビジュアル ツリーをたどって特定の先祖の型を探す必要があります。前者は、その名前を持つ登録済みオブジェクトのウィンドウの名前スコープを直接参照するため、後者はわずかに遅いと思います...とはいえ、大きなパフォーマンスの違いはないと思います。

それが役に立てば幸い、

アジ

于 2010-11-30T19:48:09.127 に答える
1

一般に、ElementName可能であれば を使用する必要があります。

与えられた例とベンチマークの例は非常に単純です。実際の例では、要素のビジュアル ツリーが大きくなり、FindAncestorバインディングは要素を見つけるためにさらに多くの要素をトラバースする必要があります。

実際のアプリケーションでいくつかのFindAncestorバインディングをバインディングに変更することで、SECONDS を獲得しました。ElementName

IMHOElementNameバインディングも読みやすくなっています。

于 2020-09-23T09:05:58.730 に答える