Google снизила частоту подтормаживаний при прокрутке в Chrome для Android на 48%

Компания Google сегодня рассказала о том, как ей удалось сократить количество подтормаживаний (дженка) при прокрутке в Chrome для Android на 48% в период с 2023 по 2026 год.

Под дженком (jank) при прокрутке понимаются внезапные подтормаживания или рывки страницы. Это происходит, когда «устройство не успевает вовремя подготовить кадр с обновленным смещением прокрутки». Работа над устранением «одной из главных проблем, портящих впечатление от мобильного интернета», началась в 2023 году.

Плавная прокрутка (слева) против прокрутки с рывками (справа)

У Chrome есть строгий дедлайн на отрисовку каждого кадра до обновления экрана. Если из-за задержки обработка кадра затягивается и выходит за рамки этого дедлайна, экран вынужден отображать устаревшее смещение прокрутки на протяжении всего цикла обновления — около 16,7 миллисекунд для дисплея с частотой 60 Гц. Человеческий глаз воспринимает этот пропущенный кадр как резкое и неприятное подтормаживание.

Изменение частоты подтормаживаний при прокрутке в Chrome на Android в период с 2023 по 2026 год

Чтобы избежать этого, передача данных от ввода к кадру в Chrome должна быть стабильной, то есть «каждое обновление прокрутки должно занимать одинаковое время для отображения на экране». По сравнению с обычным приложением для Android, у Chrome есть раздельные процессы браузера, отрисовщика (рендер-процесс) и GPU, которые повышают стабильность, безопасность и производительность, но при этом усиливают подтормаживания при прокрутке.

Когда пользователь касается экрана в Chrome, аппаратная часть генерирует событие ввода, которое попадает не просто в один поток или даже один процесс. Сначала оно поступает в процесс браузера для хит-тестирования (hit testing) и перенаправляется в процесс рендеринга для вычисления нового смещения прокрутки. Сигналы VSync идут по другому пути, также пересекающему несколько процессов. Они поступают в композиторный поток Viz в процессе GPU и перенаправляются в процесс рендеринга, который сопоставляет их с событиями ввода для отрисовки нового кадра. Затем кадр отправляется в процесс GPU для формирования пикселей в буфере GPU, которые ОС в конечном итоге выводит на экран. Ситуация усложняется еще и тем, что Chrome обрабатывает небуферизованный ввод напрямую от оборудования. Это означает, что события ввода поступают в Chrome через нерегулярные интервалы времени, зачастую по несколько раз за один цикл обновления экрана.

Учитывая многопроцессорный конвейер, Google запустила несколько проектов по снижению дженка с помощью «автоматизированных эвристик, адресных оптимизаций и глубоких архитектурных изменений». В числе предпринятых мер:


  • Прогнозирование ввода (Input prediction): Событие ввода от ОС иногда может задерживаться настолько сильно, что даже льготного периода Input Framer оказывается недостаточно. Дальнейшее увеличение этого периода не рассматривается, так как это повысит риск того, что Chrome не успеет вовремя подготовить кадр. Вместо этого, если к моменту дедлайна ОС не доставила ни одного события ввода, Chrome создает собственное синтетическое обновление прокрутки и прогнозирует будущую позицию прокрутки на основе уже зафиксированной кривой прокрутки.
  • Элементы управления браузера в Viz: Когда пользователь начинает прокручивать веб-сайт на Android вниз, элементы управления браузера скрываются за пределами области просмотра синхронно со скроллингом страницы. Раньше такое синхронизированное движение двух поверхностей задействовало основной поток браузера для каждого отдельного кадра, что создавало множество предпосылок для визуальных сбоев. Мы изменили архитектуру так, чтобы процесс GPU мог применять смещение прокрутки каждого кадра к скриншоту элементов управления браузера без взаимодействия с основным потоком браузера.
  • Приоритет потоков ввода Android: Цепь сильна настолько, насколько силен ее слабейший звено. Конвейер работает ровно так же быстро, как его самая низкоприоритетная зависимость. Мы выяснили, что события ввода иногда доходили до Chrome слишком долго, поскольку соответствующие потоки ОС вытеснялись другими задачами с более низким приоритетом. Мы поработали совместно с командой Android, чтобы убедиться, что все потоки, отвечающие за передачу аппаратного ввода в Chrome, имеют достаточный приоритет.