ElementName или RelativeResource? - PullRequest
       26

ElementName или RelativeResource?

15 голосов
/ 30 ноября 2010

Какая из следующих привязок TextBlocks стоит больше производительности:

<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 set.
  • FindAncestor:

    • Будут повторяться только через предков, а не братьев и сестер братьев и сестер,кузены и т. д.
    • Моst, вероятно, использует GetType для определения типа предка;GetType стоит больше производительности, чем простой Name метод получения свойств (может быть, DP разные?)

Ответы [ 2 ]

26 голосов
/ 01 декабря 2010

Обычно ужасно пытаться ответить на подобные вещи, споря о том, что, по вашему мнению, будет быстрее.Гораздо лучше построить эксперимент для его измерения.

Я немного изменил вашу настройку - я поместил соответствующий Xaml в UserControl и привязал к свойству Name, поскольку UserControl не имеет Title собственность.Затем я написал некоторый код для создания нового экземпляра элемента управления и добавления его в пользовательский интерфейс и использовал Stopwatch для измерения времени, необходимого для его создания и загрузки.(Я запускаю синхронизацию непосредственно перед созданием пользовательского элемента управления и останавливаюсь сразу после того, как пользовательский элемент управления вызывает его событие Loaded.)

Я запускаю этот код DispatcherTimer 20 раз в секунду, чтобы я могпроводить много измерений в надежде уменьшить экспериментальную ошибку.Чтобы свести к минимуму искажения из-за кода отладки и диагностики, я запускаю сборку Release и вычисляю и распечатываю среднее значение только после 2000 итераций.

После 2000 итераций подход ElementName в среднем составляет 887us..

После 2000 итераций подход RelativeSource в среднем составляет 959 мкс.

Так что в данном конкретном эксперименте ElementName немного быстрее, чем RelativeSource.Загружая тривиальный UserControl только с Grid и одним TextBlock, где есть только один именованный элемент, подход ElementName требует 92% времени для загрузки, чем подход RelativeSource.

Конечно, я измеряю небольшой, искусственный пример здесь.Производительность подхода ElementName может варьироваться в зависимости от количества именованных элементов в области.И могут быть другие непредвиденные факторы, которые могут привести к совершенно другим результатам в реальных сценариях.Поэтому я бы порекомендовал выполнить аналогичные измерения в контексте реального приложения, если вы хотите получить лучшую картинку.

Я повторил эксперимент с 10 TextBlocks вместо 1. ElementName, затем усреднил 2020us, тогда как RelativeSource подход составил в среднем 2073us, снова более 2000 итераций для обоих тестов.Как ни странно, здесь есть меньшая разница, не только в относительном выражении, но и в абсолютном выражении - примеры с одним элементом показали разницу в 72 мкс, тогда как примеры из десяти элементов показали разницу в 53 мкс.

I 'я начинаю подозревать, что я вызываю большую изменчивость, выполняя свои тесты на моей основной машине, а не на одной, тщательно сконфигурированной с как можно меньшими затратами для минимизации шума.

Еще одна вариация: все еще с 10 связанным текстомблоки, я добавил еще десять пустых, несвязанных, именованных текстовых блоков в пользовательский элемент управления.Идея состояла в том, чтобы ввести больше именованных вещей - ElementName теперь должен найти именованный элемент в 11 именованных вещах.Среднее значение для ElementName сейчас составляет 2775us.Подход RelativeSource с этими дополнительными 10 именованными элементами вышел на 3041us.

Опять же, здесь я подозреваю изменчивость на моем настольном компьютере - кажется странным, что RelativeSource показал себя значительно хуже, чем в сценарии, которыйElementName

В любом случае, то, что делает кажется достаточно ясным, так это то, что стоимость загрузки здесь гораздо более чувствительна к количеству элементов, чем она есть.какой стиль привязки вы используете.Очевидно, у ElementName есть небольшое преимущество, но достаточно маленькое (и с достаточно странными результатами), чтобы вызвать подозрение в правильности заключения о том, что оно обязательно быстрее.

Таким образом, мы могли бы построить более осторожные эксперименты, чтобы получитьлучшая картинка.Но, на мой взгляд, если вы не можете убедительно продемонстрировать существенную разницу в производительности при работе на обычном компьютере, то спорить о том, что быстрее, - просто трата времени.

Итак, в заключение: производительность - этонеправильно здесь фокусироваться.Выберите тот, который делает код более читабельным.

4 голосов
/ 30 ноября 2010

Последнему из двух нужно пройтись по визуальному дереву в поисках определенного типа предка, где, как предыдущий смотрит прямо в область имен окна для зарегистрированного объекта с таким именем ... я думаю, что последний будет немного медленнее ... при этом я не думаю, что будет существенная разница в производительности.

Надеюсь, это поможет,

Aj

...