[recovery mode] Сравнение производительности UI в WPF, Qt, WinForms и FLTK
Под мерой производительности UI, будем понимать количество откликов на действия пользователя в единицу времени. А под откликом — запрашиваемую пользователем реакцию приложения.
Малым временем отклика, можно объяснить ряд предпочтений пользователя:
1. Предпочтение аналоговых интерфейсов цифровым (когада возникает задержка на обработке цифрового ввода)
2. На заре Windows, — предпочтения пользователей работать с DOS программами в «текстовом режиме», а с не GUI аналогами в Windows (время отклика в текстовом режиме тогда было заметно меньше на сходной платформе)
3. Предпочтение реальных игровых консолей их эмуляторам (эмуляторы часто имеют время отклика отличное от времени отклика оригинальных консолей)
4. Предпочтение пользователей iOS и Android относительно WinCE и Symbian (среди прочего, например в iOS ставилась цель быстрого отклика и поддержки 60 FPS, Android хотя и не ставил таких целей был заметно отзывчивее WinCE и Symbian)
5. В автомобилях — неоднозначное отношение пользователей к автоматическим коробками передач, электронной педали газа и некоторым другим системам вносящим задержку между управляющим воздействием и реакцией на него (это относится к наименее продвинутым версиям этих решений)
Большое время отклика является по сути «обратной связью с запаздыванием», про которую более подробно можно прочитать тут: «Обратная связь с запаздыванием в кране с горячей водой, марсоходе и демографической пирамиде»
Сравнение производительности
Задержка реакции на ввод пользователя в цифровых системах естественна и неизбежна. Однако в UI для восприятия значение имеют только те задержки, которые пользователь в состоянии ощутить. Например, в восприятии визуальной информации среднестатистический пользователь не способен различить задержки менее 1/60 секунды, поэтому дальнейшее уменьшение времени визуального отклика вряд-ли будет оправдано.
Рассмотрим отзывчивость пользовательского интерфейса библиотек WPF, Qt, WinForms и FLTK. Трудоемко измерить отзывчивость всех контролов этих библиотек, и сложно в каждом случае измерить интервал между вводом пользователя и реакцией контрола на этот ввод. Поэтому, немного упростим задачу оценки. Тестировать будем один, но сложный, и в целом показательный контрол, присутствующий во всех библиотеках — DataGrid. Отзывчивость будем мерить по FPS в отклике на скроллинг содержимого этого контрола. Для того чтобы избежать подсчета неполных кадров, будем использовать двойную буферизацию.
Во время скроллинга грида, мы так или иначе мы проверим основные механизмы библиотеки отвечающие за реакцию на ввод, рендеринг контролов, текста, обработку визуального дерева контролов, и отчасти композицию. Это даст нам возможность оценить потенциал библиотеки для работы с нагруженным UI.
Для каждой библиотеки я подготовил по тестовому приложению, заполняющих грид данными одинакового вида. Эти данные — 5000 строк по 20 колонок с некой произвольной информацией (считаю такое количество строк и столбцов близким к реальным максимальным потребностям отображения сложных объектов). Я не оптимизировал заполнение грида, поэтому не стоит придавать значения тому, что для некоторых библиотек он заполняется медленно. Производительность будем мерить уже после того как грид заполнен.
Производительность я проверял только под Windows (хотя библиотеки, за исключением WPF кросплатформенны), для проверки был написан счетчик FPS (только для Windows и 32 битной глубины цвета) определяющий изменения кадра по верхней части основного экрана. Погрешность счетчика может быть около 1 кадра.
Методика измерения производительности:
1. Запускаем счетчик FPSCounter.exe.
2. Запускаем одно из тестовых приложений FltkGrid.exe, FormsGrid.exe, QtGrid.exe или WpfDatagridTest.exe и разворачиваем его на весь основной экран (это необходимо т.к. детектируется только изменение верхней части кадра на основном экране)
3. Двигаем бегунок вертикального скроллера грида вверх и вниз до упора, во время движения бегунка смотрим значение FPS в верхнем левом углу экрана или в окне счетчика. (для получения максимальных значений FPS двигать бегунок надо быстро, иначе мы упремся в собственную «производительность», а не в производительность UI)
Измерения FPS я производил на нескольких, оказавшихся под рукой платформах, почти все платформы на Windows 7×64, другие приложения на время измерений закрывал.
Архив с FPSCounter.exe, FltkGrid.exe, FormsGrid.exe, QtGrid.exe и WpfDatagridTest.exe, а так же Qt библиотеками, необходимыми для тестового приложения на Qt (16 Mb)
Архив с FPSCounter.exe, FltkGrid.exe, FormsGrid.exe (т.е. без Qt, зато очень маленький)
Приложения скомпилированы под х64 платформу. Кроме этого для запуска может потребоваться msvs runtime 2010
Результаты
Ниже приведена таблица с перечнем платформ, на которых запускались измерения и их результатами. В таблице также указана оценка однопоточной производительности платформы (Single Thread Performance) в соответствии с www.cpubenchmark.net
В дополнение к таблице, хочу добавить что приложения Оffice и например браузер Chrome (на «хороших» страницах) показывают FPS примерно равный FLTK или чуть меньше.
Для более наглядной иллюстрации добавлю график зависимости FPS от оценки Single Thread производительности. График построен на основе данных приведенных в таблице.
График стоит немного прокомментировать. На платформе с оценкой 1000 использовалось низкое вертикальное разрешение экрана что сильно уменьшило число видимых ячеек, тем самым существенно повысив FPS вертикального скроллирования. Хочу также добавить, что для компиляции FLTK примеров был отключен ряд оптимизаций, поэтому вполне возможно включив их, можно несколько увеличить оценки примера FLTK на всех платформах (по этой же причине во время старта примера FLTK появляется окно консоли)
В целом же, зависимость FPS от однопоточной производительности процессора достаточно линейна. Есть предположение что многопоточная производительность пока мало применима к UI библиотекам (например, превосходство i7 в многопоточной производительности мало влияет на FPS). Так же измерения показали слабую зависимость FPS в нашем тесте от видеокарты (зависимость безусловно есть, но похоже в данных тестах видеокарта не является узким местом) Еще одной интересной деталью явилось ограничение 30 FPS на ряде платформ. Не уверен связано ли это c драйвером видеокарты или какими-то ее настройками, однако в ряде случаев не удавалось получить более 30 FPS…
Исключительно на основании данных измерений я не могу рекомендовать FLTK, как универсальное средство повышения отзывчивости вашего UI, тем более что писать UI на FLTK весьма трудоемко (на написание FLTK примера у меня ушло около 20ти минут, хотя остальные примеры были написаны заметно быстрее). Однако результаты измерений заставляют задуматься о том, что по многие библиотеки не полностью раскрывают потенциал железа на котором выполняются, делая приложения менее привлекательными для пользователя (с точки зрения отзывчивости по крайней мере).
Буду рад, если подобным образом кто-то протестирует и другие UI библиотеки, предложит вариант оптимизации производительности тестовых примеров (для рассматриваемого случая скроллинга) или же просто расскажет о FPS в тестовых примерах на своей конфигурации.
Прилагаю исходники счетчика и тестов.
Как же получить высокий FPS?
Как видно из теста, стабильные 60 FPS, в случае тяжелого UI мы получим разве что на дорогом железе и наиболее затратной в разработке UI библиотеке (то есть дорогим будет и разработка и железо и потребление этого железа), наверное иногда это того стоит, но пока это скорее исключение. Однако, если не вдаваться в крайности и поставить себе целью получить хотябы 20 FPS в нагруженных информацией интерфейсах. Чего нам это будет стоить?
Для рассмотренных библиотек, вариантов, видимо, не так и много:
1. FLTK + почти самое дешевое железо. На разработку UI мы потратим заметно больше времени, но в текущих ценах сможем сэкономить ~100–200$ на железе на рабочее место пользователя.
2. Qt + среднее железо. На железе сэкономить особо не получится, но зато разработка UI будет дешевле чем в случае FLTK. Вероятно в ряде случаев вариант будет оптимальным.
3. WPF + дорогое железо т.е. дополнительные 200–300$ на рабочее место. Ведь если на i7–3770 мы получаем только 12 кадров, то нужно как минимум железо в полтора раза мощнее. Вероятно i7–5930K или возможно i7–4790K в паре с хорошей видеокартой справятся с задачей 20 FPS. Однако вряд ли это будет эффективное решение, да и справятся ли… к сожалению нет такого железа под рукой чтобы проверить, но если экстраполировать однопоточную производительность то ее оценка должна быть свыше 3000, для получения 20 FPS при 1280×1024… такого железа просто не существует, по крайней мере тут…
4. Облегчать UI, до тех пор пока не уложимся в 20 FPS. Например, если используя WPF, вместо 20ти колонок в гриде оставить только 6, то на i7–3770 мы получим стабильные 20 FPS, если же оставить всего 3–4 колонки, то получим 20 FPS и на бюджетном железе. Уменьшение размера самого грида также должно дать положительный эффект (правда на разных библиотеках он разный, и как ни странно для случая WPF эффект наименее выражен). Приемлемы ли такие решения? Применимы далеко не везде, но все-таки покрывают ряд задач, не фокусирующихся на представлении данных.
P.S.: Идея сравнить производительность гридов появилась после того как я столкнулся с низкой производительностью грида WPF. В комментариях к моей предыдущей статье Выбор между C++ и C# я, в частности, разбирал эту проблему.
Далее мне стало интересно, как с задачей отображения грида справляются альтернативные библиотеки, так появились тестовые приложения и результаты изложенные в этой статье.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.