Имя элемента против.Относительный ресурс?
-
29-09-2019 - |
Вопрос
Какая из следующих привязок 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
набор.
FindAncestor
:- Будет перебирать только предков, а не братьев и сестер, «дядей», «кузенов» и т. д.
- Скорее всего использует
GetType
определить тип предка;GetType требует большей производительности, чем простойName
метод получения свойств (может быть, DP разные?)
Решение
Обычно это ужасная идея — пытаться ответить на подобные вопросы, споря о том, что, по вашему мнению, будет быстрее.Гораздо лучше построить эксперимент для его измерения.
Я немного изменил вашу настройку - я поместил соответствующий Xaml в UserControl и привязал его к Name
собственность с тех пор UserControl
не имеет Title
свойство.Затем я написал код для создания нового экземпляра элемента управления и добавления его в пользовательский интерфейс, а также использовал метод Stopwatch
для измерения времени, затраченного на его постройку и загрузку.(Я запускаю отсчет времени непосредственно перед созданием пользовательского элемента управления и прекращаю сразу после того, как пользовательский элемент управления поднимает Loaded
событие.)
Я запускаю этот код из DispatcherTimer
20 раз в секунду, чтобы я мог проводить множество измерений в надежде уменьшить экспериментальную ошибку.Чтобы свести к минимуму искажения из-за отладочного и диагностического кода, я запускаю сборку Release и вычисляю и печатаю среднее значение только после завершения 2000 итераций.
После 2000 итераций ElementName
подход составляет в среднем 887us.
После 2000 итераций RelativeSource
подход составляет в среднем 959us.
Так ElementName
в этом конкретном эксперименте немного быстрее, чем RelativeSource
.Загрузка тривиальной UserControl
всего лишь с Grid
и один TextBlock
где есть только один именованный элемент, ElementName
Похоже, что на загрузку этого подхода уходит 92 % времени. RelativeSource
подход требует.
Конечно, я здесь измеряю небольшой искусственный пример.Производительность подхода ElementName может варьироваться в зависимости от того, сколько именованных элементов находится в области действия.Могут быть и другие непредвиденные факторы, которые в реальных сценариях могут привести к совершенно другим результатам.Поэтому я бы рекомендовал провести аналогичные измерения в контексте реального приложения, если вы хотите получить более полную картину.
Я повторил эксперимент с 10 TextBlocks вместо 1. ElementName
затем составило в среднем 2020 г., в то время как RelativeSource
В среднем подход составил 2073 мкс, то есть снова более 2000 итераций для обоих тестов.Как ни странно, здесь разница меньше, не только в относительном, но и в абсолютном выражении: примеры с одним элементом показали разницу в 72 мкс, тогда как примеры из десяти элементов показали разницу в 53 мкс.
Я начинаю подозревать, что вызываю большую вариативность, выполняя тесты на своей основной машине, а не на той, которая тщательно настроена с минимальным количеством вещей, чтобы минимизировать шум.
Еще одна вариация:по-прежнему имея 10 связанных текстовых блоков, я добавил в пользовательский элемент управления еще десять пустых несвязанных текстовых блоков с именами.Идея заключалась в том, чтобы ввести больше именованных вещей - ElementName
теперь ему нужно найти названный предмет среди 11 названных предметов.Среднее значение для ElementName
сейчас 2775us.А RelativeSource
подход с этими дополнительными 10 именованными элементами появился в 3041us.
Опять же, я подозреваю здесь изменчивость на моем настольном компьютере - кажется странным, что RelativeSource
здесь результаты оказались значительно хуже, чем в сценарии, который должен был быть более ElementName
преимущество.
В любом случае, что делает Кажется достаточно очевидным, что стоимость загрузки здесь гораздо более чувствительна к количеству элементов, чем к тому, какой стиль привязки вы используете.Видимо, есть небольшое преимущество ElementName
но достаточно мал (и с достаточно странными результатами), чтобы вызвать подозрение в обоснованности вывода о том, что это обязательно быстрее.
Поэтому мы могли бы провести более тщательные эксперименты, чтобы получить лучшую картину.Но, на мой взгляд, если вы не можете убедительно продемонстрировать существенную разницу в производительности при работе на обычном компьютере, то споры о том, что быстрее, — это, по сути, пустая трата времени.
Итак, в заключение:Производительность — это не тот предмет, на котором стоит здесь фокусироваться.Выбирайте тот, который делает код более читабельным.
Другие советы
Чем позднее двух нужно пройти визуальное дерево, ищущее определенный тип предка, где, как преждевременно к NameScope окна для зарегистрированного объекта с таким именем ... мое предположение было бы позже незначительно медленнее ... Это сказано, я не думаю, что будет значительная разница в производительности.
Надеюсь, поможет,
Aj.