Учет времени работы HWUI на Android: как измерить и проанализировать отрисовку интерфейса

Когда приложение на Android подтормаживает при прокрутке списка, первое, что стоит проверить, — время работы HWUI, системного компонента, отвечающего за аппаратно-ускоренную отрисовку интерфейса. Именно превышение бюджета кадра (около 16 мс при 60 Гц) в конвейере HWUI чаще всего проявляется как видимые рывки анимации и «выпадающие» кадры.

HWUI (Hardware UI) — это библиотека рендеринга, которая переводит дерево View в команды графического процессора. Учет времени её работы позволяет понять, на каком этапе теряется производительность: построении списка отрисовки, синхронизации с GPU или загрузке текстур. В этой статье разберём доступные инструменты измерения, интерпретацию их вывода и типичные причины перерасхода времени кадра.

Что такое HWUI и почему важно учитывать время его работы

Начиная с ранних версий Android, система перешла на аппаратный рендеринг интерфейса: вместо программной отрисовки через CPU дерево представлений преобразуется в display lists — списки команд, которые выполняет GPU. За этот процесс отвечает поток RenderThread, а сама библиотека называется HWUI.

Каждый кадр проходит несколько стадий: обработка ввода, вызовы анимаций, измерение и компоновка (measure/layout), отрисовка (draw), затем работа RenderThread и синхронизация с SurfaceFlinger. Если суммарное время превышает бюджет кадра, пользователь видит пропуск кадров — jank. Учет времени работы HWUI как раз и показывает, на какой стадии возникает перерасход.

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

Включение профилирования через параметры разработчика

Самый доступный способ — встроенный инструмент Profile HWUI rendering (в русской локализации может называться «Визуализация рендеринга GPU» или похоже; точное название зависит от версии Android и оболочки производителя). Он находится в разделе Настройки → Для разработчиков.

Чтобы активировать параметры разработчика, обычно требуется несколько раз нажать на пункт «Номер сборки» в разделе «О телефоне». Путь может отличаться в зависимости от прошивки — сверьтесь с документацией своего устройства.

  • 📊 On screen as bars — столбцы поверх экрана, каждый столбец — один кадр, цвета соответствуют стадиям рендеринга.
  • 📈 In adb shell dumpsys gfxinfo — вывод числовых данных о времени кадров через ADB для последующего анализа.
  • 🎯 Горизонтальная линия на графике — ориентировочный бюджет кадра; столбцы выше неё означают пропуск кадров.
  • 🔄 Обновление данных происходит в реальном времени при взаимодействии с приложением.
⚠️ Внимание: на некоторых устройствах и версиях Android пункт меню называется «Profile GPU Rendering», а на новых — «Profile HWUI rendering». Это один и тот же инструмент, просто переименованный. Если вы не находите его, воспользуйтесь поиском по настройкам разработчика.
📊 Как вы обычно профилируете отрисовку интерфейса?
Столбцы на экране (Profile HWUI)
dumpsys gfxinfo через ADB
Android Studio Profiler
Пока не профилирую, только планирую

Анализ столбцов на экране: что означают цвета

Режим «On screen as bars» отображает каждый кадр вертикальным столбцом, разбитым на цветные сегменты. Цветовая легенда менялась между версиями Android, поэтому точное соответствие цвета и стадии стоит уточнять в документации для вашей версии ОС. В целом сегменты отражают этапы: обработка ввода, анимации, measure/layout, draw, sync и выполнение команд GPU.

Что искать в первую очередь? Большой сегмент measure/layout указывает на слишком глубокую или сложную иерархию View. Россыпь высоких столбцов при прокрутке — признак того, что отрисовка не успевает за бюджетом кадра. А высокий сегмент синхронизации часто означает, что RenderThread долго ждёт освобождения GPU.

Сбор точных данных через dumpsys gfxinfo

Для числового анализа удобнее вывод dumpsys gfxinfo. После включения соответствующего режима в параметрах разработчика выполните на компьютере команду, указав имя пакета приложения:

adb shell dumpsys gfxinfo <имя_пакета> framestats

Вывод содержит статистику по последним кадрам: временные метки стадий конвейера в наносекундах, а также агрегированные данные — количество кадров, долю медленных кадров и распределение по стадиям. На новых версиях Android доступен флаг framestats, дающий подетальную разбивку каждого кадра, что особенно полезно для автоматизированного анализа в CI.

☑️ Порядок сбора данных о времени HWUI

Выполнено: 0 / 5

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

Типичные причины перерасхода времени кадра

Анализ сотен профилей показывает, что причины повторяются. Вот наиболее распространённые источники проблем, которые видны при учете времени работы HWUI:

  • 🧱 Слишком глубокая иерархия View — вложенные контейнеры увеличивают время measure/layout.
  • 🖼️ Тяжёлые bitmap — загрузка больших изображений в кадре вызывает долгую загрузку текстур в GPU.
  • 🔁 Лишние перерисовки — invalidate() на больших областях заставляет перестраивать display lists без необходимости.
  • 🎨 Сложные операции рисования — тени, обрезка по пути (clipPath), прозрачные слои удорожают стадию draw.
  • 📜 Тяжёлая работа в onBindViewHolder — при прокрутке списков данные должны быть готовы заранее.
⚠️ Внимание: не оптимизируйте вслепую. Сначала снимите профиль и определите, какая стадия действительно занимает время. Оптимизация draw не поможет, если перерасход идёт на стадии синхронизации из-за перегруженного GPU.
Почему столбцы высокие даже в «пустом» приложении

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

Сравнение инструментов учета времени рендеринга

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

ИнструментФормат данныхКогда использоватьТребования
Profile HWUI (столбцы)Визуальный, на экранеБыстрая оценка прямо на устройствеТолько параметры разработчика
dumpsys gfxinfoЧисловой, текстТочный анализ стадий кадраADB и включённое профилирование
Android Studio ProfilerГрафики и трейсыКомплексный анализ с CPU и памятьюПодключённое устройство, debug-сборка
System tracing (systrace/Perfetto)Трассы по потокамГлубокая диагностика RenderThreadЗапись трейса, анализ в вьюере

Для повседневной проверки достаточно столбцов на экране, а для поиска конкретной причины jank наиболее информативен системный трейс: он показывает работу RenderThread и HWUI на временной шкале вместе с событиями всей системы.

Как сократить время работы HWUI: практические меры

После того как узкое место найдено, действуйте точечно. Упрощение иерархии — первый кандидат: замена вложенных LinearLayout на ConstraintLayout или переход на декларативный UI часто заметно сокращает время measure/layout. Для списков используйте RecyclerView с корректным переиспользованием View и лёгким биндингом данных.

Изображения подготавливайте заранее: масштабируйте bitmap под размер отображения и загружайте асинхронно, вне кадра отрисовки. Проверьте, не создаются ли объекты (Paint, Path) внутри onDraw() — выделение памяти в кадре провоцирует сборку мусора и рывки.

Если перерасход идёт на стадии синхронизации, проблема может быть вне вашего приложения — например, в фоновых процессах, нагружающих GPU. В таком случае повторите замер в «чистых» условиях и на другом устройстве, чтобы отделить системную нагрузку от проблем кода.

⚠️ Внимание: результаты профилирования зависят от устройства, частоты экрана, температуры (троттлинг) и версии Android. Выводы, сделанные на одном смартфоне, проверяйте минимум на нескольких моделях из целевой аудитории.

Частые вопросы

Чем HWUI отличается от RenderThread?

HWUI — это библиотека аппаратного рендеринга, а RenderThread — выделенный поток, в котором она выполняется. В статистике gfxinfo и в трейсах вы видите работу HWUI, разбитую по потокам: UI-поток строит display lists, RenderThread исполняет их на GPU.

Почему столбцы профиля не появляются на экране?

Возможные причины: профилирование включено только в режим dumpsys (без отображения на экране), приложение использует собственный рендеринг вне стандартного конвейера View, либо производитель изменил поведение функции в своей оболочке. Проверьте выбранный режим в параметрах разработчика.

Можно ли собирать статистику gfxinfo без ADB?

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

Какой бюджет кадра считать нормой?

Бюджет определяется частотой обновления экрана: при 60 Гц это около 16 мс, при более высокой частоте — меньше. Ориентируйтесь на горизонтальную линию в графике профиля и на долю пропущенных кадров в статистике gfxinfo.

Помогает ли профилирование HWUI для игр?

Ограниченно. Игры обычно рендерят через OpenGL/Vulkan напрямую, минуя конвейер View, поэтому для них нужны профилировщики GPU от производителя чипа. HWUI-профиль полезен для интерфейсной части игры — меню, HUD на базе View.