Почему код GUI так дорог в вычислительном отношении? - PullRequest
13 голосов
/ 02 февраля 2009

Все, что вы храните,

Мне было интересно, почему код GUI отвечает за высасывание множества циклов ЦП. В принципе, графический рендеринг гораздо менее сложен, чем Doom (хотя большинство корпоративных графических интерфейсов вводят много витрин). Уровень обработки событий также, по-видимому, требует больших затрат, однако, похоже, что хорошо написанная реализация должна эффективно переключаться между контекстами на современных процессорах с большим объемом памяти / кэша.

Если кто-то запустил профилировщик в своем большом приложении с графическим интерфейсом или сам общий API, меня интересует, где находятся узкие места.

Возможные объяснения (которые я представляю) могут быть:

  1. Высокие уровни абстракции между оборудованием и интерфейсом приложения
  2. Множество уровней косвенности для правильного кода для выполнения
  3. Низкий приоритет (по сравнению с другими процессами)
  4. Неправильно работающие приложения, переполняющие API с вызовами
  5. Чрезмерная ориентация объекта?
  6. Полный неудачный выбор дизайна в API (не только проблемы, но и философия дизайна)

Некоторые структуры GUI намного лучше, чем другие, поэтому я хотел бы услышать различные перспективы. Например, система Unix / X11 сильно отличается от Windows и даже от WinForms.

Редактировать: Теперь вики сообщества - пойти на это. У меня есть еще одна вещь, которую я хочу добавить - я учусь на алгоритмов в школе, и мне было бы интересно, если в коде GUI есть неэффективные алгоритмы и какие они есть. С другой стороны, это, вероятно, просто накладные расходы на реализацию.

Ответы [ 5 ]

9 голосов
/ 02 февраля 2009

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

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

Добавлено:

В комментариях я нашел это:

Я тоже очень заинтересован в этом. Не может быть так, чтобы графический интерфейс отображался с использованием только процессора, потому что, если у вас нет подходящих драйверов для вашей gfx-карты, настольная графика отображает невероятно медленно. Если у вас есть gfx-драйверы, то desktop-gfx работает довольно быстро, но не так быстро, как приложение DirectX / OpenGL.

Вот, как я понимаю, соглашение: каждая графическая карта сегодня поддерживает универсальный интерфейс для рисования. Я не уверен, что это называется "VESA", "SVGA" или это просто старые имена из прошлого. В любом случае, этот интерфейс подразумевает выполнение всего через прерывания. Для каждого пикселя есть вызов прерывания. Или что-то типа того. Тем не менее, правильный драйвер VGA может использовать преимущества DMA и других улучшений, которые делают весь процесс менее нагружающим ЦП.

Добавлено 2: А, а для OpenGL / DirectX - это еще одна особенность современных видеокарт. Они оптимизированы для 3D операций в эксклюзивном режиме. Вот почему скорость. Обычный графический интерфейс использует только базовые процедуры 2D-рисования. Таким образом, он получает возможность отправлять содержимое всего экрана каждый раз, когда ему требуется обновление. Однако 3D-приложения отправляют множество текстур и определений треугольников в VRAM (видео-RAM), а затем просто повторно используют их для рисования. Они просто говорят что-то вроде «возьмите набор треугольников № 38 с набором текстур № 25 и нарисуйте их». Все эти вещи кэшируются в VRAM, так что это снова намного быстрее.

Я не уверен, но я подозреваю, что современные графические интерфейсы с 3D-ускорением (Vista Aero, compiz в Linux и т. Д.) Также могут воспользоваться этим. Они могут отправлять обычные растровые изображения на VGA, а затем просто повторно использовать их непосредственно из VRAM. Однако любые поверхности, нарисованные приложением, все равно необходимо отправлять непосредственно каждый раз для обновления.

Добавлено 3: Больше идей. :) Современный графический интерфейс для Windows, Linux и т. Д. Ориентирован на виджеты (это ориентировано на управление для динамиков Windows). Проблема заключается в том, что каждый виджет имеет свой собственный код для рисования и связанную поверхность для рисования (более или менее). Когда окно необходимо перерисовать, оно вызывает код рисования для всех своих дочерних виджетов, которые, в свою очередь, вызывают код рисования для своих дочерних виджетов и т. Д. Каждый виджет перерисовывает всю свою поверхность, даже если некоторая его часть затемнена другими виджетами. С вышеупомянутыми методами отсечения некоторая часть этой извлеченной информации немедленно отбрасывается, чтобы уменьшить мерцание и другие артефакты. Но все же это большой ручной код рисования, который включает растровое растяжение, растяжение, наклон, рисование линий, текст, заливку и т. Д. И все это транслируется в серию вызовов putpixel, которые фильтруются через фильтры / маски отсечения и другие вещи. Ах да, и альфа-смешение стало сегодня популярным благодаря хорошим эффектам, что означает еще больше работы. Так что ... да, вы могли бы сказать, что это из-за большого количества абстракции и косвенности. Но ... ты мог бы сделать это лучше? Я так не думаю. Могут помочь только трехмерные методы, поскольку они используют преимущества графического процессора для альфа-вычислений и отсечения.

5 голосов
/ 02 февраля 2009

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

Среди библиотек написание библиотеки инструментария GUI является чрезвычайно сложной проблемой. Это связано с тем, что программы, использующие библиотеки GUI, охватывают очень широкий спектр доменов с очень разными потребностями. Мистер Почему и Мартин Демолло недавно обсудили требования, предъявляемые к библиотекам графического интерфейса .

Написание графического интерфейса для самих виджетов затруднительно, потому что пользователи компьютеров очень чувствительны к мелким деталям поведения интерфейса. Не родной виджет никогда не чувствует себя хорошо, не так ли? Чтобы получить правильный неродной виджет - фактически, чтобы получить правильный виджет - вам нужно потратить чрезмерное количество времени на настройку деталей поведения.

Таким образом, GUI работает медленно из-за неэффективности, вносимой механизмами абстракции, используемыми для создания многократно используемых компонентов, что добавляло к нехватке времени, доступного для оптимизации кода, после того, как столько времени было потрачено только для правильного поведения.

2 голосов
/ 02 февраля 2009

Хм, это довольно много.

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

Чтобы установить все вычисления без загрузки в GPU, не обязательно устраните какие-либо проблемы. Графический процессор подобен центральному процессору, за исключением того, что он имеет менее общее назначение и больше параллельный процессор данных. Он может делать графические вычисления исключительно хорошо. Какая бы ни была у вас комбинация графического API / ОС и драйвера, это не имеет большого значения ... хорошо, на примере Vista они изменили механизм компоновки рабочего стола. Этот механизм гораздо лучше компостирует только то, что изменилось, и, поскольку перерисовка номер один для графических приложений перерисовывается, это аккуратная стратегия оптимизации. Эта идея виртуализации ваших вычислительных потребностей и обновления только самых маленьких изменений каждый раз.

Win32 отправляет сообщения WM_PAINT в окна, когда их нужно перерисовать, это может быть результатом того, что окна перекрывают друг друга. Однако это зависит от самого окна, чтобы выяснить, что на самом деле изменилось. Более того, ничего не изменилось, или внесенное изменение было достаточно тривиальным, так что его можно было просто предварительно сформировать поверх самой верхней поверхности, которая у вас была.

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

Что-то, что делает Windows Presentation Foundation (WPF), что, на мой взгляд, намного превосходит большинство других API-интерфейсов GUI, состоит в том, что оно разбивает обновления макета и отображает обновления в два отдельных этапа. И хотя WPF является управляемым кодом, механизм рендеринга - нет. Что происходит с рендерингом, так это то, что управляемый механизм рендеринга WPF создает очередь команд (это то, что делают DirectX и OpenGL), которая затем передается в собственный механизм рендеринга. Что еще более элегантно, так это то, что WPF попытается сохранить любые вычисления, которые не изменили визуальное состояние. Трюк, если можно, когда вы избегаете дорогостоящих рендерингов вызовов для вещей, которые не нужно рендерить (виртуализация).

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

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

WPF может делать некоторые вещи асинхронно, довольно прилично, что очень важно, если вы хотите создать действительно отзывчивый пользовательский интерфейс с низкой задержкой / низким быстродействием. Асинхронные операции - это больше, чем разгрузочная работа в другом потоке.

Подводя итог, можно сказать, что медленный и дорогой GUI означает слишком много перерисовки и перерисовки, что очень дорого, т. Е. Всю площадь поверхности.

0 голосов
/ 02 февраля 2009

Я думаю, что вы можете найти некоторые интересные мысли на эту тему в «Проектировании оконных систем: если бы мне пришлось делать это снова в 2002 году» Джеймса Гослинга (парень из Java, также известный своими работами по созданию окон до X11 системы). Доступно онлайн здесь [pdf] .

Статья фокусируется на положительной стороне (как сделать это быстро), а не на отрицательной стороне (что делает ее медленной), но это все еще хорошее чтение по теме.

0 голосов
/ 02 февраля 2009

Я в какой-то степени зависит от языка. Возможно, вы заметили, что приложения Java и RealBasic немного медленнее, чем их аналоги на основе C (C ++, C #, Objective-C).

Однако приложения с графическим интерфейсом намного сложнее, чем приложения командной строки. В окне «Терминал» нужно только нарисовать простое окно, которое не поддерживает кнопки.

Есть также несколько петель для дополнительных входов и функций.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...