Используйте Simpleperf для оценки производительности устройства. Simpleperf — это встроенный инструмент профилирования как приложений, так и собственных процессов Android. Используйте CPU Profiler для анализа использования процессора приложениями и активности потоков в режиме реального времени.
Существует два видимых пользователю показателя производительности:
- Предсказуемая, ощутимая производительность . Пропускает ли пользовательский интерфейс (UI) кадры или стабильно отображает их с частотой 60 кадров в секунду? Воспроизводится ли звук без артефактов и треска? Какова задержка между касанием экрана пользователем и отображением эффекта на дисплее?
- Продолжительность времени, необходимая для длительных операций (например, открытие приложений).
Первое более заметно, чем второе. Пользователи обычно замечают подтормаживания, но они не смогут отличить время запуска приложения 500 мс от 600 мс, если не будут смотреть на два устройства рядом. Задержка сенсорного экрана заметна сразу и существенно влияет на восприятие устройства.
В результате на быстром устройстве конвейер пользовательского интерфейса (UI) является наиболее важным компонентом системы, помимо того, что необходимо для поддержания его функциональности. Это означает, что конвейер пользовательского интерфейса должен вытеснять любую другую работу, не требующую гибкого пользовательского интерфейса. Для поддержания гибкого пользовательского интерфейса фоновая синхронизация, доставка уведомлений и подобные задачи должны быть отложены, если работа пользовательского интерфейса может быть выполнена. Допускается жертвовать производительностью более длительных операций (время выполнения HDR+, запуск приложения и т. д.) ради поддержания гибкого пользовательского интерфейса.
Емкость против джиттера
При рассмотрении производительности устройства значимыми показателями являются емкость и джиттер .
Емкость
Емкость — это общий объём ресурсов, которыми устройство располагает в течение определённого периода времени. Это могут быть ресурсы ЦП, графического процессора, ресурсы ввода-вывода, сетевые ресурсы, пропускная способность памяти или любая аналогичная метрика. При анализе производительности всей системы может быть полезно абстрагироваться от отдельных компонентов и использовать единую метрику, определяющую производительность (особенно при настройке нового устройства, поскольку рабочие нагрузки на нём, вероятно, фиксированы).
Мощность системы зависит от доступных вычислительных ресурсов. Основной способ изменения мощности — изменение частоты процессора/видеокарты, но существуют и другие способы, например, изменение количества ядер процессора в режиме онлайн. Соответственно, мощность системы соответствует энергопотреблению; изменение мощности всегда приводит к аналогичному изменению энергопотребления.
Требуемая в данный момент мощность в значительной степени определяется запущенным приложением. В результате платформа практически не может регулировать мощность, необходимую для конкретной рабочей нагрузки, и возможности для этого ограничены улучшениями среды выполнения (фреймворк Android, ART, Bionic, компилятор/драйверы графических процессоров, ядро).
Джиттер
Хотя требуемую для рабочей нагрузки мощность легко оценить, джиттер — понятие более расплывчатое. Для хорошего введения в тему джиттера как препятствия для быстрых систем мы рекомендуем прочитать статью «Дело о недостающей производительности суперкомпьютера: достижение оптимальной производительности на 8192 процессорах ASCI Q» . (В этой статье рассматривается, почему суперкомпьютер ASCI Q не достиг ожидаемой производительности, и она служит отличным введением в оптимизацию больших систем.)
На этой странице термин «джиттер» используется для описания того, что в документе ASCI Q называется «шумом» . Джиттер — это случайное поведение системы, препятствующее выполнению заметной работы. Часто это работа, которая должна быть выполнена, но может не иметь строгих временных ограничений, обуславливающих её выполнение в определённое время. Поскольку джиттер является случайным, крайне сложно опровергнуть его наличие для данной рабочей нагрузки. Также крайне сложно доказать, что известный источник джиттера стал причиной конкретной проблемы с производительностью. Инструменты, наиболее часто используемые для диагностики причин джиттера (например, трассировка или логирование), могут вносить свой собственный джиттер.
Источники дрожания, наблюдаемые в реальных реализациях Android, включают в себя:
- Задержка планировщика
- Обработчики прерываний
- Код драйвера выполняется слишком долго с отключенным приоритетом или прерываниями
- Длительно работающие отложенные прерывания
- Конфликт блокировок (приложение, фреймворк, драйвер ядра, блокировка связующего компонента, блокировка mmap)
- Конфликт файлового дескриптора, при котором поток с низким приоритетом блокирует файл, не давая потоку с высоким приоритетом выполняться.
- Выполнение критически важного для пользовательского интерфейса кода в рабочих очередях, где его выполнение может быть отложено
- Переходы в режим ожидания ЦП
- Ведение журнала
- Задержки ввода-вывода
- Создание ненужных процессов (например, широковещательных сообщений
CONNECTIVITY_CHANGE
) - Переполнение кэша страниц из-за недостатка свободной памяти
Требуемое время для заданного периода джиттера может уменьшаться или не уменьшаться с увеличением емкости. Например, если драйвер отключит прерывания, ожидая чтения по шине I2C, это займет фиксированное время независимо от того, работает ли процессор на частоте 384 МГц или 2 ГГц. Увеличение емкости не является эффективным решением для повышения производительности при наличии джиттера. В результате более быстрые процессоры обычно не повышают производительность в ситуациях с ограничением джиттера.
Наконец, в отличие от емкости, джиттер практически полностью находится в сфере ответственности поставщика системы.
Потребление памяти
Традиционно считается, что низкая производительность вызвана потреблением памяти. Хотя само по себе потребление памяти не влияет на производительность, оно может вызывать дрожание памяти из-за накладных расходов lowmemorykiller, перезапусков служб и перегрузки кэша страниц. Сокращение потребления памяти может устранить прямые причины низкой производительности, но существуют и другие целенаправленные улучшения, позволяющие избежать этих причин (например, закрепление фреймворка, чтобы предотвратить его выгрузку при последующей загрузке).
Анализ первоначальной производительности устройства
Начинать с работающей, но неэффективной системы и пытаться исправить её поведение, анализируя отдельные случаи низкой производительности, заметные пользователю, — неразумная стратегия. Поскольку низкая производительность обычно не воспроизводится (то есть вызывается дрожанием) или является проблемой приложения, слишком большое количество переменных во всей системе препятствует эффективности этой стратегии. В результате очень легко ошибочно определить причины и внести незначительные улучшения, упустив системные возможности для улучшения производительности всей системы.
Вместо этого используйте следующий общий подход при подключении нового устройства:
- Загрузите систему в пользовательский интерфейс со всеми запущенными драйверами и некоторыми базовыми настройками регулятора частоты (если вы изменяете настройки регулятора частоты, повторите все шаги, указанные ниже).
- Убедитесь, что ядро поддерживает точку трассировки
sched_blocked_reason
, а также другие точки трассировки в конвейере дисплея, которые обозначают момент доставки кадра на дисплей. - Выполняйте длинные трассировки всего конвейера пользовательского интерфейса (от получения входных данных через IRQ до окончательного сканирования) при выполнении легкой и последовательной рабочей нагрузки (например, UiBench или теста с шариком в TouchLatency) .
- Исправление пропусков кадров, обнаруженных при легкой и стабильной рабочей нагрузке.
- Повторяйте шаги 3–4, пока не сможете работать без пропущенных кадров в течение 20 и более секунд подряд.
- Переходим к другим видимым пользователю источникам мусора.
Другие простые действия, которые вы можете выполнить на раннем этапе настройки устройства, включают в себя:
- Убедитесь, что в вашем ядре установлен патч для точки трассировки sched_blocked_reason . Эта точка трассировки включается в категории трассировки sched в systrace и обеспечивает функцию, отвечающую за переход потока в режим непрерывного сна. Это критически важно для анализа производительности, поскольку непрерывный сон — очень распространённый индикатор джиттера.
- Убедитесь, что у вас достаточно трассировки для графического процессора и конвейеров дисплея. В последних однокристальных системах Qualcomm точки трассировки включаются с помощью:
adb shell "echo 1 > /d/tracing/events/kgsl/enable"
adb shell "echo 1 > /d/tracing/events/mdss/enable"
Эти события остаются включенными при запуске systrace, поэтому вы можете увидеть дополнительную информацию о конвейере дисплея (MDSS) в разделе mdss_fb0
. В системах на кристалле Qualcomm дополнительная информация о графическом процессоре не отображается в стандартном представлении 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
и имеет два режима: задержка касания и прыгающий мяч (для переключения режимов нажмите кнопку в правом верхнем углу).
Тест с прыгающим мячом настолько прост, насколько кажется: мяч бесконечно скачет по экрану, независимо от действий пользователя. Обычно это самый сложный для идеального выполнения тест, но чем ближе он к выполнению без пропусков кадров, тем лучше будет ваше устройство. Тест с прыгающим мячом сложен, поскольку представляет собой тривиальную, но совершенно стабильную нагрузку, работающую на очень низкой тактовой частоте (предполагается, что устройство имеет регулятор частоты; если устройство работает на фиксированной тактовой частоте, понизьте частоту CPU/GPU почти до минимума при первом запуске теста с прыгающим мячом). По мере того, как система переходит в состояние покоя, а тактовая частота падает ближе к состоянию бездействия, требуемое время CPU/GPU на кадр увеличивается. Вы можете наблюдать за мячом и видеть, как он подтормаживает, а также видеть пропущенные кадры в systrace.
Благодаря такой постоянной нагрузке, выявить большинство источников джиттера гораздо проще, чем в большинстве рабочих нагрузок, видимых пользователю, отслеживая, что именно выполняется в системе во время каждого пропущенного кадра, а не конвейер пользовательского интерфейса. Более низкие тактовые частоты усиливают эффект джиттера, повышая вероятность того, что любое джиттер приведет к потере кадра. В результате, чем ближе TouchLatency к 60 FPS, тем меньше вероятность возникновения проблем с поведением системы, приводящих к спорадическим, трудновоспроизводимым подтормаживаниям в крупных приложениях.
Поскольку джиттер часто (но не всегда) не зависит от тактовой частоты, используйте тест, работающий на очень низких тактовых частотах, чтобы диагностировать джиттер по следующим причинам:
- Не все колебания тактовой частоты не зависят от нее; многие источники просто потребляют процессорное время.
- Регулятор должен приблизить среднее время кадра к крайнему сроку, снижая тактовую частоту, поэтому время, потраченное на выполнение задач, не связанных с пользовательским интерфейсом, может привести к потере кадра.