Используйте Simpleperf для оценки производительности устройства. Simpleperf — это собственный инструмент профилирования как для приложений, так и для собственных процессов на Android. Используйте CPU Profiler для проверки использования ЦП приложения и активности потоков в режиме реального времени.
Есть два видимых пользователю показателя производительности:
- Предсказуемая, ощутимая производительность . Пользовательский интерфейс пропускает кадры или постоянно отображается со скоростью 60 кадров в секунду? Звук воспроизводится без артефактов и тресков? Какова задержка между прикосновением пользователя к экрану и эффектом, отображаемым на дисплее?
- Время, необходимое для более длительных операций (например, открытия приложений).
Первое более заметно, чем второе. Пользователи обычно замечают зависания, но они не смогут отличить время запуска приложения 500 мс от 600 мс, если не посмотрят на два устройства рядом. Задержка касания заметна сразу и существенно улучшает восприятие устройства.
В результате в быстром устройстве конвейер пользовательского интерфейса является самой важной вещью в системе, помимо того, что необходимо для поддержания работоспособности конвейера пользовательского интерфейса. Это означает, что конвейер пользовательского интерфейса должен вытеснять любую другую работу, которая не необходима для гибкого пользовательского интерфейса. Чтобы поддерживать гибкий пользовательский интерфейс, фоновую синхронизацию, доставку уведомлений и аналогичную работу необходимо отложить, если работа пользовательского интерфейса может быть запущена. Допустимо жертвовать производительностью более длительных операций (время выполнения HDR+, запуск приложения и т. д.) ради поддержания гибкого пользовательского интерфейса.
Емкость в сравнении с джиттером
При рассмотрении производительности устройства емкость и джиттер являются двумя значимыми показателями.
Емкость
Емкость — это общий объем некоторого ресурса, которым устройство обладает в течение некоторого времени. Это могут быть ресурсы ЦП, ресурсы графического процессора, ресурсы ввода-вывода, сетевые ресурсы, пропускная способность памяти или любой подобный показатель. При изучении производительности всей системы может быть полезно абстрагировать отдельные компоненты и принять единую метрику, определяющую производительность (особенно при настройке нового устройства, поскольку рабочие нагрузки, выполняемые на этом устройстве, скорее всего, будут фиксированными).
Емкость системы варьируется в зависимости от вычислительных ресурсов, находящихся в сети. Изменение частоты ЦП/ГП является основным средством изменения емкости, но есть и другие, например, изменение количества ядер ЦП в режиме онлайн. Соответственно, мощность системы соответствует потребляемой мощности; изменение мощности всегда приводит к аналогичному изменению энергопотребления.
Требуемая в данный момент емкость в подавляющем большинстве определяется работающим приложением. В результате платформа мало что может сделать для регулировки мощности, необходимой для данной рабочей нагрузки, а средства для этого ограничиваются улучшениями во время выполнения (платформа Android, ART, Bionic, компилятор/драйверы графического процессора, ядро).
Джиттер
Хотя требуемую мощность для рабочей нагрузки легко определить, джиттер — более расплывчатое понятие. Хорошее введение в джиттер как препятствие для быстрых систем можно найти в разделе «СЛУЧАЙ ОТСУТСТВУЮЩЕЙ ПРОИЗВОДИТЕЛЬНОСТИ СУПЕРКОМПЬЮТЕРА: ДОСТИЖЕНИЕ ОПТИМАЛЬНОЙ ПРОИЗВОДИТЕЛЬНОСТИ НА 8192 ПРОЦЕССОРАХ ASCl Q» . (Это исследование того, почему суперкомпьютер ASCI Q не достиг ожидаемой производительности, и отличное введение в оптимизацию больших систем.)
На этой странице термин джиттер используется для описания того, что в документе ASCI Q называется шумом . Джиттер — это случайное поведение системы, которое препятствует выполнению заметной работы. Часто это работа, которую необходимо выполнить, но она может не иметь строгих требований к времени, которые заставляют ее выполняться в какое-то конкретное время. Поскольку оно носит случайный характер, крайне сложно опровергнуть существование джиттера при данной рабочей нагрузке. Также крайне сложно доказать, что известный источник джиттера стал причиной конкретной проблемы с производительностью. Инструменты, наиболее часто используемые для диагностики причин джиттера (например, трассировка или журналирование), могут вызывать собственный джиттер.
Источники дрожания, наблюдаемые в реальных реализациях Android, включают:
- Задержка планировщика
- Обработчики прерываний
- Код драйвера работает слишком долго с отключенным вытеснением или прерываниями.
- Длительные программные прерывания
- Конфликт за блокировку (приложение, платформа, драйвер ядра, блокировка связывателя, блокировка mmap)
- Конфликт за файловый дескриптор, когда поток с низким приоритетом удерживает блокировку файла, предотвращая запуск потока с высоким приоритетом.
- Запуск критического для пользовательского интерфейса кода в рабочих очередях, где его выполнение может быть задержано.
- Переходы в режиме простоя процессора
- Ведение журнала
- Задержки ввода-вывода
- Создание ненужного процесса (например, широковещательная рассылка
CONNECTIVITY_CHANGE
) - Перезагрузка кэша страниц из-за недостаточности свободной памяти
Требуемое количество времени для данного периода джиттера может уменьшаться, а может и не уменьшаться по мере увеличения пропускной способности. Например, если драйвер оставляет прерывания отключенными во время ожидания чтения по шине i2c, это займет фиксированное время независимо от того, работает ли процессор на частоте 384 МГц или 2 ГГц. Увеличение емкости не является возможным решением для улучшения производительности при наличии джиттера. В результате более быстрые процессоры обычно не улучшают производительность в ситуациях с ограниченным джиттером.
Наконец, в отличие от пропускной способности, джиттер почти полностью находится в компетенции поставщика системы.
Потребление памяти
Потребление памяти традиционно считается причиной низкой производительности. Хотя потребление само по себе не является проблемой производительности, оно может вызвать дрожание из-за низкой нагрузки на память, перезапуск службы и перегрузку кэша страниц. Уменьшение потребления памяти позволяет избежать прямых причин низкой производительности, но могут быть и другие целевые улучшения, которые также позволяют избежать этих причин (например, закрепление платформы, чтобы предотвратить ее выгрузку, когда она будет выгружена вскоре после этого).
Анализ начальной производительности устройства
Начинать с функциональной, но плохо работающей системы и пытаться исправить поведение системы, рассматривая отдельные случаи видимой пользователем низкой производительности, не является разумной стратегией. Поскольку плохую производительность обычно трудно воспроизвести (то есть дрожание) или это проблема приложения, слишком много переменных во всей системе не позволяют этой стратегии быть эффективной. В результате очень легко ошибочно определить причины и внести незначительные улучшения, упустив при этом системные возможности для улучшения производительности всей системы.
Вместо этого используйте следующий общий подход при создании нового устройства:
- Загрузите систему в пользовательский интерфейс со всеми работающими драйверами и некоторыми базовыми настройками регулятора частоты (если вы измените настройки регулятора частоты, повторите все шаги, описанные ниже).
- Убедитесь, что ядро поддерживает точку трассировки
sched_blocked_reason
, а также другие точки трассировки в конвейере отображения, которые обозначают, когда кадр доставляется на дисплей. - Выполняйте длинные трассировки всего конвейера пользовательского интерфейса (от получения входных данных через IRQ до окончательного сканирования), одновременно выполняя легкую и согласованную рабочую нагрузку (например, UiBench или тест мяча в TouchLatency) .
- Исправьте пропадание кадров, обнаруженное при облегченной и последовательной рабочей нагрузке.
- Повторяйте шаги 3–4, пока не сможете работать без пропущенных кадров в течение 20+ секунд за раз.
- Перейдите к другим видимым пользователям источникам мусора.
Другие простые вещи, которые вы можете сделать на ранних этапах запуска устройства, включают:
- Убедитесь, что в вашем ядре установлен патч трассировки sched_blocked_reason . Эта точка трассировки включается с помощью категории запланированной трассировки в systrace и предоставляет функцию, отвечающую за переход в режим сна, когда поток переходит в режим непрерывного сна. Это имеет решающее значение для анализа производительности, поскольку непрерывный сон является очень распространенным индикатором джиттера.
- Убедитесь, что у вас есть достаточная трассировка для конвейеров графического процессора и дисплея. В последних SOC Qualcomm точки трассировки включаются с помощью:
adb shell "echo 1 > /d/tracing/events/kgsl/enable"
adb shell "echo 1 > /d/tracing/events/mdss/enable"
Эти события остаются включенными при запуске systrace, поэтому вы можете увидеть дополнительную информацию о конвейере отображения (MDSS) в разделе mdss_fb0
. На процессорах Qualcomm SOC вы не увидите никакой дополнительной информации о графическом процессоре в стандартном представлении systrace, но результаты присутствуют в самой трассировке (подробнее см. в разделе «Понимание systrace »).
От такого типа трассировки дисплея вы хотите получить одно событие, которое прямо указывает на то, что кадр был доставлен на дисплей. Оттуда вы можете определить, успешно ли вы достигли установленного времени кадра; если событие X n происходит менее чем через 16,7 мс после события X n-1 (при условии, что дисплей имеет частоту 60 Гц), то вы знаете, что не дернулись. Если ваш SOC не предоставляет таких сигналов, обратитесь к своему поставщику, чтобы получить их. Отладка джиттера чрезвычайно сложна без четкого сигнала о завершении кадра.
Используйте синтетические тесты
Синтетические тесты полезны для проверки наличия основных функций устройства. Однако рассматривать тесты как показатель воспринимаемой производительности устройства бесполезно.
Судя по опыту использования SOC, различия в производительности синтетических тестов между SOC не коррелируют с аналогичной разницей в ощутимой производительности пользовательского интерфейса (количество пропущенных кадров, время кадра 99-го процентиля и т. д.). Синтетические тесты — это тесты только мощности; Джиттер влияет на измеряемую производительность этих тестов только за счет кражи времени у основной операции теста. В результате результаты синтетических тестов практически не имеют значения в качестве показателя производительности, воспринимаемой пользователями.
Рассмотрим два SOC, на которых выполняется Benchmark X, который отображает 1000 кадров пользовательского интерфейса и сообщает общее время рендеринга (чем ниже балл, тем лучше).
- SOC 1 визуализирует каждый кадр теста Benchmark X за 10 мс и набирает 10 000 баллов.
- SOC 2 обрабатывает 99% кадров за 1 мс, но 1% кадров за 100 мс и набирает 19 900 баллов, что значительно лучше.
Если тест показывает реальную производительность пользовательского интерфейса, SOC 2 будет непригоден для использования. Если предположить, что частота обновления составляет 60 Гц, у SOC 2 будет неровный кадр каждые 1,5 секунды работы. Между тем, SOC 1 (более медленный SOC согласно Benchmark X) будет совершенно гибким.
Используйте отчеты об ошибках
Отчеты об ошибках иногда полезны для анализа производительности, но из-за того, что они настолько тяжелы, они редко полезны для отладки спорадических проблем с зависанием. Они могут дать некоторые подсказки о том, что система делала в данный момент, особенно если зависание было связано с переходом приложения (который регистрируется в отчете об ошибке). Отчеты об ошибках также могут указывать на то, что с системой что-то не так в более широком смысле, что может снизить ее эффективную производительность (например, тепловое регулирование или фрагментация памяти).
Используйте TouchLatency
Несколько примеров плохого поведения связаны с TouchLatency — предпочтительной периодической рабочей нагрузкой, используемой для Pixel и Pixel XL. Он доступен по адресу frameworks/base/tests/TouchLatency
и имеет два режима: задержка касания и прыгающий мяч (чтобы переключить режимы, нажмите кнопку в правом верхнем углу).
Тест с прыгающим мячом так же прост, как кажется: мяч постоянно прыгает по экрану, независимо от действий пользователя. Обычно это самый сложный тест для идеального выполнения, но чем ближе он к выполнению без пропущенных кадров, тем лучше будет ваше устройство. Тест с прыгающим мячом сложен, потому что это тривиальная, но совершенно последовательная рабочая нагрузка, которая выполняется на очень низкой тактовой частоте (при этом предполагается, что устройство имеет регулятор частоты; если вместо этого устройство работает с фиксированными тактовыми частотами, уменьшите тактовую частоту процессора/графического процессора почти до минимума). при первом запуске теста с прыгающим мячом). По мере того, как система переходит в состояние покоя и тактовые частоты приближаются к состоянию простоя, требуемое время ЦП/ГП на кадр увеличивается. Вы можете наблюдать за мячом и видеть, что что-то дергается, а также вы сможете увидеть пропущенные кадры в systrace.
Поскольку рабочая нагрузка настолько единообразна, вы можете гораздо легче выявить большинство источников дрожания, чем в большинстве видимых пользователем рабочих нагрузок, отслеживая, что именно выполняется в системе во время каждого пропущенного кадра, а не конвейер пользовательского интерфейса. Более низкие тактовые частоты усиливают эффект джиттера, повышая вероятность того, что любой джиттер приведет к потере кадра. В результате, чем ближе TouchLatency к 60FPS, тем меньше вероятность плохого поведения системы, вызывающего спорадические, трудно воспроизводимые зависания в больших приложениях.
Поскольку джиттер часто (но не всегда) не зависит от тактовой частоты, используйте тест, который выполняется на очень низких тактовых частотах, для диагностики джиттера по следующим причинам:
- Не весь джиттер не зависит от тактовой частоты; многие источники просто потребляют процессорное время.
- Губернатору следует приблизить среднее время кадра к крайнему сроку, сократив время, чтобы время, потраченное на работу, не связанную с пользовательским интерфейсом, могло привести к потере кадра.