![Насколько быстрее стали терминалы в GNOME 46? - 1 Насколько быстрее стали терминалы в GNOME 46? - 1](https://www.pvsm.ru/images/2024/04/24/naskolko-bystree-stali-terminaly-v-GNOME-46.jpg)
VTE (Virtual TErminal library) — это библиотека, лежащая в основе различных эмуляторов терминала GNOME. Она предоставляет GTK-виджет, отображающий элемент терминала, используемый в приложениях наподобие GNOME Terminal, Console, Black Box, Tilix, Terminator, Ptyxis и других. Также она используется во встроенных терминалах Builder и Workbench.
На протяжении цикла GNOME 46 в VTE было внесено множество улучшений производительности. Кристиан Хергерт говорил о некоторых из них в своих постах о VTE и о своей работе в GNOME 46. Но насколько же улучшилась производительность? Чего стоит ожидать вам, пользователю, от установки свежего обновления Fedora 40 и запуска любимого терминала?
Давайте измерим и разберёмся!
Что мы измеряем?
У понятия «производительность» есть множество определений, особенно когда дело касается эмуляторов терминала. Одна из самых осязаемых метрик — это задержка ввода. Грубо говоря, она показывает скорость реакции программы на ваши действия: время, проходящее между нажатием кнопки на клавиатуре и изменением цвета пикселей на мониторе.
Приложения с низкой задержкой ввода кажутся быстрыми, а с высокой — тормозными.
Если задержка ввода достаточно низка, то вы можете привыкнуть к ней и вам будет казаться, что это нормально. Однако сравнение высокой и низкой задержки ввода (например, при переключении между двумя приложениями и вводом в обоих) может сделать её достаточно заметной. Наверно, вы слышали, что некоторые люди не могут вернуться к мониторам с частотой обновления 60 Гц, попробовав частоту 144 Гц; здесь эффект примерно такой же (и за это частично ответственна задержка ввода).
Как её измерить?
▍ Измеряем задержку ввода
Существуют инструменты наподобие Typometer, измеряющие задержку в ПО, распознавая события нажатия клавиш и выполняя захват экрана для определения изменений цвета пикселя. Они работают достаточно хорошо, но требуют настройки системы, чтобы случайно не внести искажений. Например, API захвата экрана может возвращать цвета пикселей несколькими миллисекундами раньше или позже их реального отображения на экране; это необходимо иметь в виду, когда вы пытаетесь замерить что-то с точностью до миллисекунд.
У меня есть нечто более интересное: аппаратный тестер задержки ввода! Он состоит из оптического датчика, соединённого с платой Teensy, которая, в свою очередь, подключена к компьютеру по USB.
![Насколько быстрее стали терминалы в GNOME 46? - 2 Насколько быстрее стали терминалы в GNOME 46? - 2](https://www.pvsm.ru/images/2024/04/24/naskolko-bystree-stali-terminaly-v-GNOME-46-2.jpg)
Мне стоит написать целый пост, посвящённый этому тестеру задержек, но пока вам следует прочитать этот пост Тристана Хуме о создании похожего устройства. Я использовал его как инструкцию для создания своего устройства, но написал собственную прошивку и скрипты анализа (которые я не буду выкладывать, пока они не превратятся во что-то более удобочитаемое).
Основное преимущество такого устройства заключается в том, что оно позволяет нам замерять полную сквозную задержку ввода, в том числе время обработки в ядре, композиторе, приложении, а затем и время отклика самого монитора.
Мы замеряем именно то, что видим и чувствуем, если не считать прошивки клавиатуры (так как тестер задержек отправляет события нажатия на клавиши напрямую через USB). Кроме того, тестер накладывает очень небольшую дополнительную нагрузку на систему, особенно по сравнению с чем-то наподобие API захвата экрана.
Ниже представлено краткое описание его работы.
Оптический датчик направлен на небольшую область монитора, на которую влияет нажатие на клавишу (в нашем случае это ячейка конкретного символа в терминале). Плата отправляет нажатие клавиши (например, пробела) по USB и начинает мониторить показания оптического датчика. Как только она распознаёт скачок в величине освещённости, она отпускает клавишу. Затем она нажимает вторую клавишу (например, Backspace) и ждёт, пока освещённость изменится обратно. Мы вернулись к тому, с чего начинали; прошивка ожидает случайный промежуток времени (чтобы предотвратить попадание в частоту обновления монитора) и повторяет эксперимент.
В течение всего этого процесса плата максимально быстро сбрасывает все показания оптического датчика на последовательный порт (на текущей плате и с имеющейся прошивкой я получаю примерно 35,5 тысяч показаний в секунду). На компьютере я сохраняю все эти данные в файл для офлайн-анализа с помощью кода на Python. Этот код анализа находит метку времени, где начинает меняться освещённость, и вычитает её из метки времени нажатия клавиши, получая задержку ввода.
Затем я выполняю агрегацию измерений и строю их график при помощи seaborn. Вот пример результата:
![Насколько быстрее стали терминалы в GNOME 46? - 3 Насколько быстрее стали терминалы в GNOME 46? - 3](https://www.pvsm.ru/images/2024/04/24/naskolko-bystree-stali-terminaly-v-GNOME-46-3.png)
▍ Графики задержки ввода
Давайте посмотрим, что мы можем извлечь из этого графика задержек.
![Насколько быстрее стали терминалы в GNOME 46? - 4 Насколько быстрее стали терминалы в GNOME 46? - 4](https://www.pvsm.ru/images/2024/04/24/naskolko-bystree-stali-terminaly-v-GNOME-46-4.png)
Маленькие чёрные точки — это отдельные измерения. То есть каждая точка — это величина времени между одним нажатием на клавишу и соответствующим изменением освещённости в датчике. Таких точек 120, потому что я повторял каждый тест 120 раз.
Судя по точкам, данные выглядят логично. Мы ожидаем, что основная часть измерений равномерно распределится по интервалу, примерно равному размеру одного цикла перерисовки монитора. Это вызвано тем, что мониторы обычно выполняют перерисовку с постоянной частотой, а при нажатии на клавишу в случайный момент времени мы попадём в случайную точку цикла перерисовки. Мы получаем наименьшую задержку, если приложение отрисовывает новый кадр в ответ прямо в тот момент, когда монитор должен его показать. Наибольшая задержка получается, когда приложение завершает рендеринг нового кадра, чуть-чуть пропустив «дедлайн» монитора, и вынуждено ждать ещё один цикл перерисовки для изменения цвета пикселя.
В приведённом выше примере точки распределены в интервале 7-8 мс, что примерно равно циклу обновления (около 6,94 мс) моего монитора с частотой обновления 144 Гц.
Высокие выбросы в точках или более широкое распределение указывают на задержку или торможение тестируемого приложения: некоторые нажатия на клавиши обрабатываются дольше, чем другие.
Мы не ожидаем увидеть никаких пробелов между кластерами точек. Они обычно говорят об алиасинге с циклом перерисовки монитора или о каком-то баге планировщика кадров в композиторе.
[Несколько недель назад сделанные мной измерения показали подозрительный пробел в точках длиной в один кадр. Оказалось, что это баг планировщика кадров в моём композиторе, винить за который можно было только меня. К счастью, устранить его было несложно, и я легко удостоверился в его отсутствии, проведя тот же тест повторно.]
Ящик демонстрирует статистику для отдельных измерений:
- медиану (измерение, находящееся «ровно посередине»; половина измерений ниже него, а вторая половина — выше),
- самое нижнее и верхнее измерение,
- 25-й и 75-й перцентили (25% и 75% измерений ниже соответствующей линии).
В целом мы можем сравнивать приложения по их разбросу, по медианной задержке, а также изучить наличие выбросов.
После всего этого мы почти готовы к изучению результатов. Мне только нужно сказать вам, задержку чего же я измерял.
Тестовая система
Я провёл все тесты на следующей системе:
- Lenovo Legion 7 Gen 7 AMD с CPU Ryzen 7 6800H и dGPU Radeon RX 6700M (использующим dGPU исключительно через переключатель MUX).
- Монитор: Acer Nitro XV320QU, 2560×1440, 144 Гц, масштабирование 100%.
- Хост: Fedora 40 Silverblue Beta, Mesa 24.0.4.
- Композитор: raw Mutter 46.0.
Возможно, вы спросите, что такое raw Mutter? Mutter — это композитор, поверх которого собирается GNOME Shell. Оказалось, можно запустить самостоятельный Mutter без GNOME Shell, переключившись на другой VT и запустив команду вида mutter --display-server -- alacritty
. Так вы получите практически «голое» окружение, предназначенное только для тестирования. Однако оно довольно полезно для бенчмаркинга, так как представляет собой нечто близкое к идеальному случаю GNOME Shell с нулевой дополнительной нагрузкой.
Я протестировал несколько приложений терминала. На графиках они встречаются в следующем порядке:
- Alacritty: не на основе VTE; служит своего рода точкой начала отсчёта, потому что по всем моим предыдущим тестам стабильно оказывается одним из самых быстрых терминалов.
- Console: GTK 4, терминал GNOME по умолчанию. [У вашего дистрибутива может быть другое представление о том, какой терминал должен применяться по умолчанию в GNOME. Например, в Fedora по-прежнему по умолчанию применяется GNOME Terminal.]
- VTE Test App: GTK 4, тестовый терминал, находящийся в репозитории VTE.
- GNOME Terminal: GTK 3, раньше использовался в GNOME по умолчанию и по-прежнему распространяется в стандартном наборе многих дистрибутивов. [Для GNOME 47 GNOME Terminal будет портирован на GTK 4, но GNOME 46 это всё ещё приложение GTK 3.]
Так как мы хотим сравнить GNOME 45 и GNOME 46, для установки и запуска всех представленных выше терминалов я воспользовался контейнерами toolbx с Fedora 39 и Fedora 40; никакие дополнительные настройки терминалов не выполнялись.
Я по порядку запускал терминалы и перемещал их окна в левый верхний угол монитора. Во всех тестах курсор мыши находился вне пределов окна. [Чтобы избежать искажения результатов из-за срабатывания логики ссылки под курсором.]
Тесты задержки ввода
Первый тест прост: я запускаю cat > /dev/null
, чтобы получить поле ввода без readline и другой подобной обработки, а затем измеряю время, необходимое терминалу для перемещения курсора блока на одну ячейку вправо после нажатия на пробел.
Это необходимо для тестирования наилучшего для терминала сценария с наименьшими дополнительными затратами.
Вот как выглядит процесс теста:
А вот результаты:
![Насколько быстрее стали терминалы в GNOME 46? - 5 Насколько быстрее стали терминалы в GNOME 46? - 5](https://www.pvsm.ru/images/2024/04/24/naskolko-bystree-stali-terminaly-v-GNOME-46-5.png)
Как и ожидалось, показатели Alacritty никак не изменились при переходе с F39 на F40.
Но взгляните на огромное улучшение у всех терминалов VTE! Они совершили скачок с «плохо» до почти уровня Alacritty; даже GNOME Terminal на GTK 3 очень к нему близок.
Скорее всего, главное изменение, ставшее причиной этого — вот этот коммит Кристиана, благодаря которому произошёл переход от таймера перерисовки VTE на 40 Гц к отрисовке в каждом кадре, синхронизованной с монитором, как и должен вести себя любой уважающий себя виджет GTK.
У Console есть несколько выбросов, которые возможно вызваны её отслеживанием процессов, но в этом нет ничего нового (вероятно, этой проблемой займутся в GNOME 47).
Для следующего теста я создал более реалистичный сценарий. Я сделал снэпшот моей системы с neovim и открыл README из Ptyxis. Затем я заменил квадрат текста полноблочными символами Unicode, чтобы у оптического датчика было яркое пятно для распознавания.
![Насколько быстрее стали терминалы в GNOME 46? - 6 Насколько быстрее стали терминалы в GNOME 46? - 6](https://www.pvsm.ru/images/2024/04/24/naskolko-bystree-stali-terminaly-v-GNOME-46-6.png)
Тест заключается во многократном нажатии на Ctrl+D и Ctrl+U для скроллинга вверх и вниз текстового буфера в neovim. Оптический датчик попеременно считывает пустую строку (тёмную) и полноблочную область (яркую). В neovim есть множество изысков, поэтому терминалу приходится отрисовывать различные подчёркивания прямыми и волнистыми линиями, значки gutter и statusline.
Вот как выглядит процесс тестирования:
А вот результаты:
![Насколько быстрее стали терминалы в GNOME 46? - 7 image](https://www.pvsm.ru/images/2024/04/24/naskolko-bystree-stali-terminaly-v-GNOME-46-7.png)
В этом тесте тоже очевидны огромные улучшения: терминалы GNOME 46 по-прежнему имеют почти одинаковые показатели с Alacritty!
Теперь давайте внимательнее изучим все результаты Fedora 40 на одном графике:
![Насколько быстрее стали терминалы в GNOME 46? - 8 Насколько быстрее стали терминалы в GNOME 46? - 8](https://www.pvsm.ru/images/2024/04/24/naskolko-bystree-stali-terminaly-v-GNOME-46-8.png)
На этом графике видно, какой задержкой приходится расплачиваться в тесте neovim по сравнению с простым cat
, но рост задержки схож у всех терминалов.
vtebench
Я провёл бенчмаркинг vtebench Alacritty для того же набора приложений и конфигураций. Это полностью автоматизированный бенчмарк, измеряющий не задержку ввода, а нечто совершенно иное: производительность считывания и парсинга PTY.
Вот что написано в README vtebench:
Этого бенчмарка недостаточно для того, чтобы получить общее представление о производительности эмулятора терминала. В нём отсутствуют такие критически важные факторы, как частота кадров и задержка. Этот бенчмарк выполняет только стресс-тест скорости чтения терминалом из PTY. Если вы не понимаете, что это значит, то не стоит делать поспешные выводы из результатов этого бенчмарка.
Длительность перерисовки может влиять и влияет на результаты этого теста, особенно в случае терминалов, считывающих и парсящих PTY в том же потоке, в котором выполняют свою логику перерисовки, например, в случае VTE.
Вот как выглядит один из бенчмарков vtebench:
![Насколько быстрее стали терминалы в GNOME 46? - 9 Насколько быстрее стали терминалы в GNOME 46? - 9](https://www.pvsm.ru/images/2024/04/24/naskolko-bystree-stali-terminaly-v-GNOME-46-9.jpg)
А вот результаты:
![Насколько быстрее стали терминалы в GNOME 46? - 10 Насколько быстрее стали терминалы в GNOME 46? - 10](https://www.pvsm.ru/images/2024/04/24/naskolko-bystree-stali-terminaly-v-GNOME-46-10.png)
Чтобы не перегружать график, я нарисовал зелёные стрелки только на одном из бенчмарков. Как видите, все остальные бенчмарки демонстрируют схожий тренд.
VTE из GNOME 46 и здесь демонстрирует долгожданные улучшения, хотя и более переменчивые и не совсем совпадающие с Alacritty (который выполняет рендеринг в отдельном от чтения и парсинга потоке). Эти улучшения, скорее всего, вызваны множеством других оптимизаций, произошедших с VTE в цикле разработки GNOME 46.
Стоит отметить, что я исключил из этих результатов два бенчмарка: dense_cells
и unicode
. Это два основных стресс-теста vtebench, очень сильно нагружающие терминал. К сожалению, VTE по-прежнему испытывает с ними проблемы и демонстрирует огромный разброс, снижающий остальные результаты и ухудшающий читаемость графика.
![Насколько быстрее стали терминалы в GNOME 46? - 11 Насколько быстрее стали терминалы в GNOME 46? - 11](https://www.pvsm.ru/images/2024/04/24/naskolko-bystree-stali-terminaly-v-GNOME-46-11.png)
Заключение
В GNOME 46 выполнена большая работа по улучшению производительности VTE, действительно ощущаемая при обычной работе с терминалом. Задержка ввода снизилась и опустилась почти до показателей самых быстрых терминалов, даже при нетривиальной конфигурации neovim со сложной структурой экрана.
Оставшаяся разница, по крайней мере, в этих тестовых случаях, практически несущественна. Частично её можно объяснить тем, что VTE выполняет намного больше дополнительной работы для обеспечения accessibility (включённой в GNOME Terminal и пока отключённой в терминалах GTK 4), вычисление полос прокрутки и другие функции.
Если вы избегали пользоваться терминалами на основе VTE из-за их тормознутости и задержки ввода, то настало время дать им ещё один шанс. Только учтите, что все эти плюсы появились в VTE 0.76.
Выражаю огромную благодарность мейнтейнерам и контрибьюторам VTE и поздравляю их с потрясающим релизом!
P.S. Если вам любопытен Ptyxis или сравнение поведения рендереров GTK NGL, NVK и GL, то могу сказать, что их производительность примерно схожа с показанными выше результатами F40 VTE Test App. Месяц назад я выполнил их более подробные бенчмарки, которые можно найти здесь.
Автор: ru_vds