Типы профилей и когда каждый из них полезен

В Android можно записывать несколько типов профилей производительности. Создание профиля помогает отлаживать проблемы, связанные со скоростью работы приложения, объемом используемой памяти, энергопотреблением и многим другим.

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

Системные трассировки

Пример трассировки системы
Рисунок 1. Пример трассировки системы.

Трассировка системы — это мощный профиль, содержащий информацию о процессах, потоках, временных параметрах, работе ЦП и выполнении задач, а также системных или определяемых пользователем событиях.

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

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

  • Срезы трассировки: отображают временные промежутки между различными точками в вашем коде. Их можно добавить с помощью API-функций Trace.beginSection и Trace.endSection .
  • Счетчики трассировки: числовые значения, представляющие метрики, например, размер кучи. Их можно добавить с помощью API Trace.setCounter .

Системные трассировки также содержат метрики, которые можно создавать с помощью запросов PerfettoSQL и использовать для проведения анализа или сравнения трассировок.

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

  • Диагностика проблем с задержкой. Системные трассировки отлично подходят для выявления проблем с задержкой, вызванных задержками, ожиданиями или проблемами планирования. Другие профилировщики, например, профилировщики на основе выборок, не предоставляют информацию о времени, которую предоставляют системные трассировки.

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

  • Диагностика проблем, связанных с конкуренцией за блокировки. Информация о состоянии потоков и срезах, показывающая, когда ресурсы заблокированы, позволяет определить, вызывают ли блокировки (например, synchronized блоки) задержки в работе пользователей.

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

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

Системная трассировка также поддерживает запросы с использованием PerfettoSQL . Эта мощная функция позволяет:

  • Извлеките конкретные данные.
  • Преобразуйте данные трассировки в пользовательские метрики.
  • Создавайте отладочные дорожки на основе запросов, чтобы упростить визуализацию наиболее важных для вас элементов в пользовательском интерфейсе Perfetto.
  • Выполняйте сложные анализы непосредственно в пользовательском интерфейсе Perfetto.

Профили образцов стека

Пример стека пример профиля
Рисунок 2. : Пример профиля образца стека.

Профили стека вызовов работают путем записи фрагментов выполнения кода и сохранения информации о стеке вызовов с заданной частотой, пока поток выполняет задачи на ЦП. Это позволяет получить представление о том, что делает ваш код во время выполнения.

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

  • Оптимизируйте проблемные участки. Анализ стека помогает выявить части кода с высокой загрузкой ЦП, то есть поток часто находится в состоянии "выполнения".
  • Разберитесь в выполнении кода. Примеры кода на Stack Overflow помогут вам понять общее поведение вашей кодовой базы.
  • Выявите код, который не должен выполняться. Вы можете обнаружить стеки вызовов, которые вообще не должны были выполняться, что указывает на непосредственные возможности для оптимизации.

Дампы кучи

Пример дампа кучи
Рисунок 3. Пример дампа кучи.

Дампы кучи Java показывают снимок памяти кучи Java вашего приложения. Этот снимок включает в себя все объекты и то, как они ссылаются друг на друга на момент создания дампа.

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

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

Профили кучи

Пример профилирования кучи
Рисунок 4. : Пример профилирования кучи.

Профили кучи доступны как в нативной, так и в Java-версиях и отлично подходят для отладки проблем с памятью. Они похожи на выборку данных из стека вызовов, но вместо измерения циклов ЦП, они берут данные при выделении памяти.

Мы рекомендуем использовать профили кучи для достижения следующих целей:

  • Уменьшите объем используемой памяти. Профили кучи предоставляют примеры с указанием мест выделения памяти в коде. Это помогает выявить области, создающие множество временных объектов, что может способствовать частым сборкам мусора (GC) в вашем приложении.
  • Выявляйте утечки памяти. Профили кучи можно использовать вместе с другими профилями памяти для диагностики и устранения утечек памяти. Они помогают точно определить места, которые выделяют значительно больше памяти, чем ожидалось.

Объединить профили

Часто для анализа производительности используется один профиль. Однако сбор данных из нескольких профилей или использование одного объединенного профиля зачастую позволяет получить более полную картину и выявить сложные проблемы, которые невозможно диагностировать с помощью одного профиля.

Рассмотрим следующие сценарии, в которых объединение профилей может быть выгодно:

  • Сценарий 1: Исследование неинструментированного кода. Трассировка системы может показать задержку для операций, которые вы уже инструментировали. Однако вам может потребоваться дополнительная информация о неинструментированных частях вашего кода, выполняющихся в это время. Для исследования создайте профиль стека вызовов, чтобы понять выполняемый код. Эта информация затем поможет вам улучшить трассировку, добавив больше фрагментов трассировки.

  • Сценарий 2: Анализ утечек памяти и сборок мусора. Представьте, что трассировка системы показывает постоянное увеличение объема памяти в куче Java из-за выделений, что приводит к частым сборкам мусора (GC). Чтобы понять, какие объекты были выделены, сделайте профилирование кучи или дамп кучи. Этот комбинированный подход помогает определить способы снижения использования памяти. Например, сокращение неэффективных или оптимизируемых выделений с помощью кэширования может предотвратить сборку мусора.