Оцените производительность

Используйте Simpleperf для оценки производительности устройства. Simpleperf — это собственный инструмент профилирования как для приложений, так и для собственных процессов на Android. Используйте CPU Profiler для проверки использования процессора приложениями и активности потоков в реальном времени.

Существует два видимых пользователю показателя производительности:

  • Предсказуемая, ощутимая производительность . Пользовательский интерфейс (UI) пропускает кадры или постоянно отображает их со скоростью 60 кадров в секунду? Воспроизводится ли звук без артефактов или хлопков? Какова задержка между прикосновением пользователя к экрану и отображением эффекта на дисплее?
  • Время, необходимое для длительных операций (например, открытие приложений).

Первое более заметно, чем второе. Пользователи обычно замечают подтормаживания, но они не смогут отличить время запуска приложения 500 мс от 600 мс, если не смотрят на два устройства рядом. Задержка касания заметна сразу и существенно влияет на восприятие устройства.

В результате в быстром устройстве конвейер пользовательского интерфейса является самой важной частью системы, помимо того, что необходимо для поддержания функциональности конвейера пользовательского интерфейса. Это означает, что конвейер пользовательского интерфейса должен вытеснять любую другую работу, которая не нужна для текучего пользовательского интерфейса. Для поддержания текучего пользовательского интерфейса фоновая синхронизация, доставка уведомлений и подобная работа должны быть отложены, если работа пользовательского интерфейса может быть запущена. Приемлемо жертвовать производительностью более длительных операций (время выполнения HDR+, запуск приложения и т. д.) для поддержания текучего пользовательского интерфейса.

Емкость против джиттера

При рассмотрении производительности устройства значимыми показателями являются емкость и джиттер .

Емкость

Емкость — это общий объем некоторого ресурса, которым обладает устройство в течение некоторого периода времени. Это могут быть ресурсы ЦП, ресурсы ГП, ресурсы ввода-вывода, сетевые ресурсы, пропускная способность памяти или любая подобная метрика. При изучении производительности всей системы может быть полезно абстрагироваться от отдельных компонентов и предположить единую метрику, которая определяет производительность (особенно при настройке нового устройства, поскольку рабочие нагрузки, выполняемые на этом устройстве, скорее всего, фиксированы).

Мощность системы зависит от вычислительных ресурсов в сети. Изменение частоты ЦП/ГП является основным способом изменения мощности, но есть и другие, например, изменение количества ядер ЦП в сети. Соответственно, мощность системы соответствует энергопотреблению; изменение мощности всегда приводит к аналогичному изменению энергопотребления.

Мощность, необходимая в данный момент времени, в подавляющем большинстве определяется запущенным приложением. В результате платформа мало что может сделать для регулировки мощности, необходимой для данной рабочей нагрузки, а средства для этого ограничены улучшениями времени выполнения (фреймворк Android, ART, Bionic, компилятор/драйверы GPU, ядро).

Джиттер

В то время как требуемую емкость для рабочей нагрузки легко увидеть, джиттер — более туманное понятие. Для хорошего введения в джиттер как препятствие для быстрых систем мы рекомендуем прочитать статью под названием Дело о недостающей производительности суперкомпьютера: достижение оптимальной производительности на 8192 процессорах ASCI Q. (Это исследование того, почему суперкомпьютер ASCI Q не достиг своей ожидаемой производительности, и это отличное введение в оптимизацию больших систем.)

На этой странице термин джиттер используется для описания того, что в статье ASCI Q называется шумом . Дрожание — это случайное поведение системы, которое препятствует выполнению заметной работы. Часто это работа, которую необходимо выполнить, но она может не иметь строгих требований по времени, которые заставляют ее выполняться в определенное время. Поскольку она случайна, крайне сложно опровергнуть существование джиттера для данной рабочей нагрузки. Также крайне сложно доказать, что известный источник джиттера стал причиной определенной проблемы с производительностью. Инструменты, наиболее часто используемые для диагностики причин джиттера (такие как трассировка или ведение журнала), могут вносить свой собственный джиттер.

Источники дрожания, наблюдаемые в реальных реализациях Android, включают в себя:

  • Задержка планировщика
  • Обработчики прерываний
  • Код драйвера выполняется слишком долго с отключенным приоритетом или прерываниями
  • Длительно работающие softirq
  • Конфликт блокировок (приложение, фреймворк, драйвер ядра, блокировка связующего устройства, блокировка mmap)
  • Конфликт файлового дескриптора, когда поток с низким приоритетом блокирует файл, не давая потоку с высоким приоритетом работать
  • Выполнение критически важного для пользовательского интерфейса кода в рабочих очередях, где его выполнение может быть отложено
  • Переходы в режим простоя ЦП
  • Ведение журнала
  • Задержки ввода-вывода
  • Создание ненужных процессов (например, широковещательные передачи CONNECTIVITY_CHANGE )
  • Переполнение кэша страниц из-за недостатка свободной памяти

Требуемое количество времени для заданного периода джиттера может уменьшаться или не уменьшаться по мере увеличения емкости. Например, если драйвер отключает прерывания, ожидая чтения по шине i2c, это займет фиксированное количество времени независимо от того, работает ли процессор на частоте 384 МГц или 2 ГГц. Увеличение емкости не является приемлемым решением для повышения производительности, когда присутствует джиттер. В результате более быстрые процессоры обычно не улучшают производительность в ситуациях, ограниченных джиттером.

Наконец, в отличие от емкости, джиттер практически полностью находится в сфере ответственности поставщика системы.

Потребление памяти

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

Анализ первоначальной производительности устройства

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

Вместо этого используйте следующий общий подход при подключении нового устройства:

  1. Загрузите систему в пользовательский интерфейс со всеми запущенными драйверами и некоторыми базовыми настройками регулятора частоты (если вы изменили настройки регулятора частоты, повторите все шаги, указанные ниже).
  2. Убедитесь, что ядро ​​поддерживает точку трассировки sched_blocked_reason , а также другие точки трассировки в конвейере отображения, которые обозначают момент доставки кадра на дисплей.
  3. Выполняйте длительные трассировки всего конвейера пользовательского интерфейса (от получения входных данных через IRQ до окончательного сканирования) при выполнении легкой и последовательной рабочей нагрузки (например, UiBench или теста с шариком в TouchLatency) .
  4. Исправление пропусков кадров, обнаруженных при легкой и стабильной рабочей нагрузке.
  5. Повторяйте шаги 3–4 до тех пор, пока не сможете работать без пропущенных кадров в течение 20+ секунд за раз.
  6. Переходим к другим видимым пользователям источникам помех.

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

  • Убедитесь, что в вашем ядре есть патч трассировки sched_blocked_reason . Эта трассировка включается с категорией трассировки sched в systrace и обеспечивает функцию, отвечающую за сон, когда поток переходит в непрерываемый сон. Это критически важно для анализа производительности, поскольку непрерываемый сон является очень распространенным индикатором джиттера.
  • Убедитесь, что у вас достаточно трассировки для графического процессора и конвейеров дисплея. В последних Qualcomm SOC точки трассировки включаются с помощью:
  • adb shell "echo 1 > /d/tracing/events/kgsl/enable"
    adb shell "echo 1 > /d/tracing/events/mdss/enable"
    

    Эти события остаются включенными при запуске systrace, поэтому вы можете увидеть дополнительную информацию в трассировке о конвейере дисплея (MDSS) в разделе mdss_fb0 . На Qualcomm SOC вы не увидите никакой дополнительной информации о GPU в стандартном представлении systrace, но результаты присутствуют в самой трассировке (подробнее см. в разделе Understanding 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 к 60FPS, тем меньше вероятность того, что у вас будет плохое поведение системы, вызывающее спорадические, трудно воспроизводимые рывки в больших приложениях.

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

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