Всем привет! Меня зовут Максим Смирнов, я руковожу командой, которая работает над производительностью Яндекс Браузера и отвечает за его графическую подсистему. В этой статье я расскажу об одном неочевидном улучшении, которое наша команда внедрила в Браузер для 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 и обрабатывать их в своём коде.
Мы воспользовались этой особенностью, чтобы подменять подстроку 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-драйверы.
Надеемся, что вам было интересно прочитать разбор этого необычного, на наш взгляд, случая из практики разработки.