Название имеет значение: как получить оптимизацию, переименовав браузер

Всем привет! Меня зовут Максим Смирнов, я руковожу командой, которая работает над производительностью Яндекс Браузера и отвечает за его графическую подсистему. В этой статье я расскажу об одном неочевидном улучшении, которое наша команда внедрила в Браузер для Windows. Если описать его в двух словах, то нам удалось улучшить стабильность и производительность браузера, убедив драйверы видеокарт, что наше приложение — это Google Chrome.

Что мы знаем о взаимодействии драйверов с программами

Приложения обычно используют драйверы через API операционной системы. Так они могут обращаться к функциям, которые предоставляет железо. Например, видеоигры через программный интерфейс Direct3D или OpenGL обращаются к драйверам видеокарт, которые отрисовывают графику с максимальным использованием возможностей современных видеоускорителей.

А еще не секрет, что производители видеокарт сильно вовлечены в индустрию геймдева и зачастую оптимизируют свои драйверы под конкретные игры. Об очередной прибавке fps или починке бага в том или ином тайтле любят рассказать как AMD, так и Nvidia. 

Критерием для применения определённых оптимизаций при этом иногда может выступать не что иное, как название исполняемого файла программы. Хрестоматийный пример — Quake III. При переименовании экзешника quake3.exe в quaff3.exe в игре изменялись производительность и качество текстур. 

Применение workaround по названию исполняемого файла не ограничивается только играми. Когда-то наша команда столкнулась с одним багом: на ноутбуках Lenovo в Яндекс Браузере скроллинг веб-страниц с тачпада был слишком резким, но при этом в других браузерах (Chrome и Edge) такой проблемы не наблюдалось. 

Посмотрев код, мы поняли, что логика обработки событий тачпада у нас не отличается от опенсорсного Chromium, на котором основан и наш браузер, и Google Chrome. Значит, проблема крылась в чём-то другом. 

Интереса ради мы попробовали переименовать исполняемый файл нашего браузера из browser.exe в chrome.exe — и вуаля! Скачки при скроллинге починились. Вероятно, в драйверах тачпада был «захардкожен» определённый список названий файлов приложений, для которых применялся фикс этой проблемы. 

Как нам пришла в голову идея переименовать браузер

Мы регулярно ищем новые способы для оптимизации производительности Яндекс Браузера и улучшения стабильности его работы. Некоторые оптимизации даже прорастают в Chromium. 

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

На одном из стендапов мы обсуждали идеи по улучшению стабильности работы GPU-процесса и вспомнили об описанном выше случае с тачпадом, а ещё о практике производителей видеокарт внедрять оптимизации для конкретных игр. Возникло логичное предположение:, а не может ли в драйверах GPU быть каких-то фиксов или оптимизаций для Google Chrome? Мы решили проверить это на практике. 

Проверяем гипотезу

Чтобы проверить нашу гипотезу про оптимизации, мы воспользовались особенностью архитектуры Chromium. GPU-процесс в браузере работает в специальной песочнице. Она предназначена для обеспечения безопасности приложения — ограничивает доступ процесса к ресурсам системы и другим процессам. Такая схема уменьшает потенциальный результат работы зловредного кода, если злоумышленникам каким-то образом удастся внедрить его в процесс. Также песочница позволяет устанавливать хуки для перехватывания вызовов системных API и обрабатывать их в своём коде.

5449605568811ac15bac2ddf342051cf.png

Мы воспользовались этой особенностью, чтобы подменять подстроку browser.exe на chrome.exe в значениях, которые возвращают функции GetModuleFilenameA/GetModuleFilenameW и GetModuleFilenameExA/GetModuleFilenameExW. 

Преимуществом такого решения оказалось то, что подмена наблюдается только внутри самого процесса. В реальности название исполняемого файла остаётся прежним, и в диспетчере задач процессы браузера отображаются по-прежнему как browser.exe

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

Экспериментируем

Дальше дело за малым: завернуть функциональность с подменой названия под отключаемый feature-флаг и провести A/B-эксперимент, то есть включить её в одной группе пользователей и отключить в другой, после чего сравнить полученные технические метрики. 

Результаты нас немало удивили: у пользователей с видеокартами AMD из экспериментальной группы число крэшей GPU-процесса уменьшилось в 5,5 раз, потребление памяти GPU-процессом снизилось в среднем на 8%, а ещё незначительно ускорилось открытие веб-страниц в браузере и отзывчивость интерфейса. 

Это означало, что в драйверах AMD действительно есть код, который применяется в зависимости от названия исполняемого файла приложения — в нашем случае для chrome.exe

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

Но ждать нам не хотелось, поэтому мы включили фичу с мимикрией под Google Chrome в GPU-процессе для всех пользователей на Windows. Если вы хотите проверить, что она работает и у вас, посмотрите в графу Executable Path на служебной странице browser://gpu в Яндекс Браузере (доступно с версии 22.9.0).

Подытожим

Любое ПО всегда работает внутри определённой среды, а не изолированно. Оно взаимодействует с разными контрагентами — ОС, драйверами и другими программами, — поэтому его работу всегда стоит оценивать в связке с ними. Зная особенности работы окружения, можно попробовать подстроить под него свой софт, чтобы получить улучшения подобные тем, которые обнаружила наша команда. Мы полагаем, что это решение может принести пользу и другим chromium-based браузерам, определение которых ещё не встроено в GPU-драйверы.

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

© Habrahabr.ru