Обнаружение зависания пользовательского интерфейса

Android визуализирует пользовательский интерфейс, генерируя кадр из вашего приложения и отображая его на экране. Если ваше приложение страдает от медленного рендеринга пользовательского интерфейса, система вынуждена пропускать кадры. Когда это происходит, пользователь замечает на экране повторяющееся мерцание, которое называется джанк .

Когда происходит зависание, это обычно происходит из-за некоторого замедления или блокировки асинхронного вызова в потоке пользовательского интерфейса (в большинстве приложений это основной поток). Вы можете использовать системные трассировки, чтобы определить, где находится проблема.

Обнаружение мусора на Android 12 и более поздних версиях

Для устройств, использующих Android 12 (уровень API 31) или более поздней версии, захваченная трассировка отображается на дорожке кадров Janky под панелью «Дисплей» в профилировщике ЦП.

Чтобы обнаружить джанк,

  1. В Android Studio выберите «Просмотр» > «Окна инструментов» > «Профилировщик» или нажмите «Профиль». на панели инструментов.

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

  2. Щелкните в любом месте временной шкалы ЦП , чтобы открыть профилировщик ЦП.

  3. Выберите «Трассировка системы» в меню конфигурации в «Профилировщике ЦП» и нажмите «Запись» . Завершив взаимодействие с приложением, нажмите «Стоп» .

  4. Вы должны увидеть дорожку кадров Janky в разделе Display . По умолчанию профайлер показывает только некачественные кадры как кандидаты на расследование. В каждом дерганном кадре красная часть показывает, сколько времени прошло с момента окончания рендеринга кадра. Скриншот трека Janky Frames

  5. Как только вы найдете неуклюжую рамку, нажмите на нее; при желании вы можете нажать M , чтобы отрегулировать масштаб и сфокусироваться на выбранном кадре. В этих потоках выделяются соответствующие события: основной поток, RenderThread и завершение GPU . Снимок экрана Profiler, отображающий фреймы Janky и основные потоки

  6. При желании вы можете просмотреть все кадры или разбивку времени рендеринга, установив флажки «Все кадры» и «Жизненный цикл» соответственно. Снимок экрана профилировщика, как указано выше, но с установленными флажками «Все кадры» и «Жизненный цикл».

Обнаружение мусора на Android 11

Для устройств, использующих Android 11 (уровень API 30), записанная трассировка отображается в разделе «Жизненный цикл кадра» в профилировщике ЦП.

Раздел жизненного цикла рамы с различными треками

Раздел «Жизненный цикл кадра» содержит имя слоя и четыре дорожки. Каждая дорожка представляет один этап конвейера рендеринга кадров. Элементы жизненного цикла фрейма следующие:

  1. Жизненный цикл кадра (имя слоя) : заголовок раздела содержит имя слоя в круглых скобках. Слой — это единая единица композиции.
  2. Приложение : этот трек показывает время с момента, когда буфер был исключен из очереди приложением, до момента, когда он был снова поставлен в очередь. Обычно это соответствует событиям трассировки в RenderThread .
  3. Ожидание графического процессора : этот трек показывает, как долго буфер принадлежал графическому процессору. Это время с момента отправки буфера в графический процессор до завершения работы графического процессора с буфером. Это не означает, что графический процессор в это время работал только с этим буфером. Для получения подробной информации о том, над чем работает графический процессор в течение определенного времени, вы можете использовать Android GPU Inspector .
  4. Композиция : этот трек показывает время, начиная с момента, когда SurfaceFlinger фиксирует буфер и отправляет его на композицию, до момента отправки буфера на дисплей.
  5. Кадры на дисплее : этот трек показывает, как долго кадр находился на экране.

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

Android Studio также отображает все кадры трассировки в виде таблицы на вкладке «Все кадры» .

Таблица всех кадров в трассировке на вкладке «Все кадры».

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

Таблицу кадров можно отсортировать по любому столбцу, чтобы быстро найти самый короткий или самый длинный кадр. Таблица также поддерживает элементы управления нумерацией страниц, которые помогают перемещаться по сотням кадров.

Чтобы обнаружить и исследовать спам на Android 11, выполните следующие действия:

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

    Столбец приложения отсортирован по убыванию

  2. Найдите самые продолжительные кадры и выберите строку таблицы. Это увеличит выбранный кадр на временной шкале слева.

    Просмотр временной шкалы рядом с таблицей кадров

  3. Найдите соответствующие темы в разделах «Жизненный цикл фрейма» и «Потоки» .

    Разделы «Жизненный цикл фрейма» и «Потоки»

Обнаружение мусора на Android 10 и более ранних версиях

Для устройств, использующих Android 10 (уровень API 29) и более ранних версий, соответствующая информация о графическом конвейере ОС отображается в одном разделе системной трассировки CPU Profiler под названием Display .

Окно пользовательского интерфейса дисплея

  • Кадры : в этом разделе показаны поток пользовательского интерфейса и события трассировки RenderThread в вашем приложении. События длительностью более 16 мс окрашиваются в красный цвет, чтобы выделить потенциальные некачественные кадры, поскольку они превышают крайний срок рендеринга со скоростью 60 кадров в секунду (fps).
  • SurfaceFlinger : в этом разделе показано, когда SurfaceFlinger обрабатывает буферы кадров. SurfaceFlinger — это системный процесс, отвечающий за отправку буферов на отображение.
  • VSYNC : в этом разделе отображается VSYNC, сигнал, который синхронизирует конвейер отображения. Трек отображает сигнал VSYNC-приложения, который показывает, когда ваше приложение запускается слишком поздно. Обычно это происходит из-за занятости потока пользовательского интерфейса. Это вызывает видимое мерцание на экране во время анимации и увеличивает задержку ввода до завершения анимации или прокрутки. Это особенно важно учитывать для дисплеев с высокой частотой обновления, поскольку они могут возникать чаще, чем 60 раз в секунду, или с переменной частотой.
  • BufferQueue : в этом разделе показано, сколько буферов кадров поставлено в очередь и ожидает использования SurfaceFlinger. Для приложений, развернутых на устройствах под управлением Android 9 (уровень API 28) или выше, эта дорожка показывает количество буферов поверхности приложения BufferQueue ( 0 , 1 или 2 ). BufferQueue может помочь вам понять состояние буферов изображений при их перемещении между графическими компонентами Android. Например, значение 2 означает, что приложение в настоящее время имеет тройную буферизацию, что приводит к дополнительной задержке ввода.

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

Раздел «Темы» в разделе «Отображение»

На рисунке выше в разделе «Потоки» показаны поток пользовательского интерфейса ( java.com.google.samples.apps.iosched ), RenderThread и поток GPU completion . Это потоки, относящиеся к рендерингу пользовательского интерфейса, и они могут способствовать зависанию.

Чтобы обнаружить подтормаживание на Android 10 или более ранней версии, выполните следующие действия:

  1. Посмотрите на дорожку «Кадры» в «Дисплей» . Красные рамки — кандидаты на расследование.

    Раздел «Кадры» в разделе «Дисплей»

  2. Как только вы обнаружите потенциально неровный кадр, увеличьте масштаб, нажав W или прокрутив колесо мыши, удерживая клавишу Control ( Command в macOS). Продолжайте увеличивать масштаб, пока не начнете видеть события трассировки в потоке пользовательского интерфейса и RenderThread .

    Трассировка событий в потоке пользовательского интерфейса и RenderThread.

    На рисунке выше Choreographer#doFrame показано, когда поток пользовательского интерфейса вызывает Choreographer для координации анимации, макета представления, рисования изображений и связанных процессов. DrawFrames показывает, когда формируется RenderThread , и передает фактические команды рисования графическому процессору.

  3. Если вы видите особенно длинное событие трассировки, вы можете увеличить масштаб и выяснить, что могло способствовать медленному рендерингу. На рисунке выше показано inflate в потоке пользовательского интерфейса, что означает, что приложение тратит время на раздувание макета. Когда вы увеличите масштаб одного из событий inflate , вы сможете точно узнать, сколько времени занимает каждый компонент пользовательского интерфейса, как показано ниже.

    Меню, показывающее точную продолжительность компонента пользовательского интерфейса.

Узнать больше

Чтобы узнать больше о том, как уменьшить задержку, см. раздел «Распространенные источники задержек» .