Pull to refresh

Миллион и один день INotifyPropertyChanged

Reading time2 min
Views12K
Оптимизации пользовательского интерфейса посвящается.

image
Пользовательский интерфейс должен быть быстрым, очень быстрым, невероятно быстрым.

В попытках сэкономить наносекунды зачастую упускаются места где можно экономить секунды. Забавно, однажды на мое возмущение о двух секундной отрисовке небольшого списка, я получил ответ «Дабпиэф ничего не поделаешь», серьезно? Изучая всевозможные варианты реализации INotifyPropertyChanged habrahabr.ru/post/281294 возникает вопрос об идеальном балансе производительности пользовательского интерфейса и разработчика, который занимается этим интерфейсом. Захотелось понять как повлияет на работу интерфейса выбор конкретной реализации.

Наши атлеты:


  1. image OnPropertyChanged(string) — класический вызов с передачей имени свойства
  2. image OnPropertyChanged(nameof) — то же что и предыдущий, но...
  3. image OnPropertyChanged([CallerMemberName]) — автоматической определение имени свойства
  4. image OnPropertyChanged(()=>Expression) — передача выражения со свойством
  5. image SetProperty&ltT&gt(ref T storage, T value, [CallerMemberName]) — гибрид
  6. image ObservableObject&ltT&gt — об этом нам поведал astudent
  7. image АОП — прокси сгенерированный Unity, реализация из прошлого топика


(Раскраска улиток — самое интересное, пагубное влияние ухода во frontend)
Бег будет происходить в мешках, для этого каждый из участников будет подписан на PropertyChanged (пустой статический метод), а так же будет реализовать общий интерфейс, на этом этапе особое внимание уделяется участнику №6, в силу его врожденных мутаций. Если интерфейс еще можно вкарячить, то подписываться придется через DependencyPropertyDescriptor, он решил выпендриться. Трасса — цикл в 10 миллионов, для каждого участника.

На старт! Внимание! Го!


Дело то не быстрое, придется подождать.


image
Эксперимент проводился несколько раз и результаты примерно не отличаются.
10 000 000 1. string 2. nameof 3. CallerMemberName 4. Expression 5. SetProperty 6. ObservableObject 7. AOP
Seconds 0,129 0,13 0,121 9,016 0,372 4,248 22,643


Награждение.


Первое место заслуженно получают улитки 1,2,3!
Второе улитка №5, не много не дотянула
Бронза заслужено достается нестандартному решению №6
Далее идут выражения
И замыкает все это дело улиточный мастер спорта, его сгубила рефлексия.

Подведение итогов.


Очевидно, что для достижения максимальной скорости нужно брать инструменты из семейства 1,2,3. Использование аоп тормознет приложение напрочь, ну конечно использовалось неоптимальное решение, можно оптимизировать рефлект насоздавав делегатов, с экономив секунды 3, но общей картины это не изменит.
А теперь по факту! Использование любой из реализаций никак не влияет на производительность. 10 миллионов вызовов занимают 25 секунд, это значит для зависона на секунду нужно сделать 400к вызовов! 400к, если вдруг такое случиться VM нужно растворить в кислоте, без горя и сожалений.

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

Следующее без слов...
image
Tags:
Hubs:
+12
Comments21

Articles

Change theme settings