Для оптимизации приложений Android требуется глубокое понимание параллельных рабочих процессов и приостановок сопрограмм.
Хотя локальное профилирование дает полезную информацию, масштабирование этих данных до рабочей среды без дополнительных затрат остается сложной задачей.
На этом занятии вы узнаете, как создать архитектурный план для непрерывного цикла обратной связи по эффективности.
androidx.tracing 2.0: динамическое переключение бэкендов и распространение контекстов сопрограмм (потоков Perfetto) между потоками.
Умное инструментирование. Используйте локальную трассировку ART, чтобы находить горячие точки, а затем автоматизируйте внедрение точек трассировки с низкими накладными расходами.
Макротестирование. Отслеживайте регрессии и проверяйте повышение производительности на физических устройствах в CI.
Трассировка в полевых условиях. Выйдите за рамки локальной трассировки и трассировки непрерывной интеграции с помощью ProfilingManager.
traceCoroutine или передавать токены распространения в код на основе обратных вызовов.Расшифровка
Рахул Равикумар (Rahul Ravikumar)
Добрый день!
Меня зовут Рахул.
Я инженер в команде Android Developer Experience.
Я занимаюсь производительностью приложений и библиотек, и этот доклад посвящен трассировке.
Прежде чем мы углубимся в трассировку, я хочу установить общий словарь, чтобы вы могли следить за ним.
Поэтому, когда я говорю о трассировке, я имею в виду явную трассировку, то есть ручное инструментирование кода, чтобы вы знали, что делает приложение.
Я не говорю об автоматических профилировщиках, о которых я расскажу.
Так что ручная трассировка – это искусство оставлять хлебные крошки в базе кода, чтобы вы могли разобраться в ней позже, когда у вас возникнет проблема с производительностью или любая другая проблема.
Обычно это намного лучше, чем журналы.
Не знаю, видели ли вы вывод Logcat для большого приложения.
Обычно это гигантская стена текста, в которой не так-то просто разобраться.
А вот трассировка – это совсем другое дело.
Это проще визуализировать.
У вас есть продолжительность.
У вас есть некоторая структура.
У вас есть инструменты, позволяющие анализировать данные и точно определять, что и когда произошло.
и это намного приятнее.
И вы можете, знаете, указать своим агентам на трассировку и сказать: задавайте вопросы.
Вы можете использовать такие инструменты, как Trace Processor, тесты производительности и даже преобразование трассировок в показатели.
Итак, это все, что вы можете делать с трассировками, что сложно сделать с помощью Logcat.
Профилирование, с другой стороны, и я говорю об автоматическом профилировании, обычно является ответом на проблему, о которой вы знаете.
Например, вы заметили, что приложение запускается медленно или работает с задержками, и хотите выяснить, в чем дело.
Если у вас нет трассировок, созданных вручную, вам поможет автоматическое профилирование.
Например, можно использовать трассировку методов ART, которая позволяет отслеживать вход в каждый метод и выход из него.
или выборку стека с помощью таких инструментов, как Simpleperf.
Поэтому вместо того, чтобы использовать каждый вход и выход метода и иметь высокие накладные расходы, вы смотрите на образцы стека вызовов и видите, что находится на горячем пути вашего приложения.
В 2026 году ОЗУ – это проблема везде, поэтому вы можете изучать память, утечки памяти и профили кучи.
Итак, это ещё один профилировщик, которым вы можете воспользоваться.
Вы можете посмотреть пути удержания кучи.
Вы можете посмотреть, какой код выделяет память, и это все виды анализа, которые вы можете сделать с помощью этого.
Справа.
Теперь у нас есть этот словарь.
Теперь давайте поговорим о том, почему мы создали новую библиотеку.
API трассировки версии 1.0 были представлены в Android Jelly Bean.
Это было в 2012 году.
Это было более 14 лет назад.
С тех пор API не так уж сильно изменились.
Мы добавили несколько расширений.
Асинхронные события и счетчики были добавлены в Android 10.
Это было в 2019 году.
и готово.
С тех пор API не менялся.
Однако за это время экосистема сильно изменилась.
Итак, трассировка платформы значительно улучшилась, но ничего из этого не было передано вам в виде дополнений API.
Мы хотим это изменить.
Другая большая проблема заключается в том, что трассировка имеет фиксированный бэкенд трассировки в версии 1.0, что означает, что каждый раз, когда вы добавляете раздел трассировки в свой код, он всегда оказывается в буфере трассировки системы.
Atrace – это подсистема трассировки Android, которая владеет этими данными.
Поэтому, если вы хотите взять свои трассировки и преобразовать их в полевую телеметрию, это действительно очень сложно, потому что теперь, во-первых, вы должны понять, как atrace хранит эти данные.
Это хорошо документированный, но потенциально сложный для восприятия формат.
Это нужно исправить.
Поэтому мы хотим предоставить вам инструменты, позволяющие переносить данные трассировки куда угодно.
Кроме того, в Tracing 1.0 длина ярлыков была ограничена 128 символами.
В 2012 году это ограничение было разумным, но в 2026 году оно кажется странным.
Что ещё хуже, вы не можете добавить в трассировку дополнительные метаданные, что создает дополнительные проблемы.
И, наконец, накладные расходы.
Поэтому, когда вы отслеживаете свое приложение, вы должны быть очень внимательны к накладным расходам, потому что акт наблюдения за системой не должен менять то, что система делает под капотом.
Поэтому, если вы хотите воспроизвести состояние гонки, трассировка не должна его устранять.
Поэтому вам нужно убедиться, что вы сохраняете всю семантику, которую вы делаете в противном случае.
Трассировка 1.0 имела относительно высокие накладные расходы, и мы хотели это улучшить.
Окей.
Я много говорил о проблемах.
Теперь давайте посмотрим на некоторые проблемы и на то, как они усугубляются на практике.
Вот трассировка Perfetto.
Это для приложения com.example.app.
У нас есть основной поток и один фрагмент под названием initializeComponent.
Теперь, в идеале, нам нужно больше деталей.
Давайте добавим деталь.
Теперь мы знаем, что initializeComponent вызывает performInitialize.
Мы по-прежнему не знаем, какой компонент инициализируется.
Теперь единственным инструментом в нашем наборе инструментов с Tracing 1 является имя, поэтому мы добавляем его к имени среза.
Помните, что названия фрагментов трассировки ограничены 128 символами, поэтому в трассировке они усекаются.
Теперь, чтобы добавить оскорбление к травме, накладные расходы на усечение также являются накладными расходами, которые вы несете при трассировке.
Итак, вы довольно быстро сталкиваетесь с этой проблемой.
Мы очень хотели это исправить.
Вы видели трассировку Perfetto и знаете, как она выглядит.
Теперь давайте посмотрим на это с точки зрения написания кода для создания этих разделов трассировки.
Опять же, у нас есть initializeComponent API.
Она принимает контекст и имя, вызывает performInitialize.
Пока что неплохо.
Теперь мы хотим добавить трассировку с помощью Tracing 1.0 API. Для этого импортируем androidx.tracing.trace и используем блок трассировки.
Указываете название.
Вот что я нашел: performInitialize.
Но, как и раньше, мы хотим знать название компонента, поэтому мы будем использовать интерполяцию строк Kotlin и добавим название.
И вот первая проблема.
Итак, у нас есть ограничение в 128 символов.
Рахул Равикумар (Rahul Ravikumar)
Это можно исправить с помощью Tracing 2.
Вместо androidx.tracing.trace вы используете Tracer.
API выглядит очень похоже.
Вместо trace у вас Tracer.global.trace.
У вас есть категория.
Позже мы поговорим о категориях подробнее, но в целом у вас есть название.
И у вас по-прежнему есть блок кода, который вы пытаетесь отследить.
Теперь у вас больше нет ограничения на количество символов в 128 символов.
Я говорил о накладных расходах на трассировку.
Давайте подробнее рассмотрим, как мы улучшили этот процесс.
На устройстве Pixel 6a с Android 16 вставка одного начального и конечного раздела заняла около 1200 наносекунд.
Это может показаться незначительным, но если у вас есть действительно горячий код, который добавляет много разделов трассировки, то это время, которое ваше приложение могло бы потратить на рендеринг кадров.
Поэтому мы не хотим отнимать у вас это время.
Мы значительно улучшили ситуацию с помощью AndroidX Perfetto SDK.
Это был экспериментальный SDK, который мы представили для отслеживания композиции, и он действительно значительно улучшил положение дел.
Мы не хотели, чтобы вы его использовали, потому что это Perfetto C SDK с привязками JNI, а C SDK занимает около 4 МБ в APK.
Мы не хотели, чтобы вы отправляли этот товар.
Теперь, с Tracing 2, у нас есть специально созданная библиотека.
Мы значительно снизили накладные расходы, и теперь Tracing 2 работает в семь раз быстрее. Это значит, что у вас будет больше времени на то, что вы хотите сделать, а инфраструктура будет занимать меньше времени.
Что становится возможным благодаря этому, что раньше было невозможно?
Один из примеров – функция отслеживания времени выполнения Metro.
Для тех, кто не знает, Metro – это библиотека внедрения зависимостей.
Поддерживает Kotlin Multiplatform.
Он использует плагин компилятора Kotlin.
Он генерирует весь код для внедрения зависимостей и интегрируется с Tracing 2.0, чтобы упростить визуализацию стоимости каждого @Inject в вашем коде.
Вот пример.
Допустим, у нас есть граф приложения.
В Metro все привязано к графу, поэтому у нас есть одно поле – AnalyticsTracker.
У нас также есть привязка provides.
У нас есть сетевой клиент с реализацией OkHttpClient, а реализация AnalyticsTracker поступает из AnalyticsTrackerImpl, и нам нужен экземпляр сетевого клиента, который граф знает, как предоставить.
Итак, под капотом плагин компилятора генерирует код, который выглядит следующим образом.
Итак, если у вас есть AnalyticsTracker, геттер создает экземпляр сетевого клиента и передает его конструктору AnalyticsTrackerImpl, что хорошо.
Но теперь, когда трассировка включена, вы можете увидеть стоимость создания не только реализации трекера, но и каждой отдельной зависимости, которая ему нужна.
Теперь вы можете увидеть не только стоимость создания экземпляра типа, но и все его зависимости в трассировке, и это действительно мощно.
Используя эту информацию, Wise, финансовое приложение, улучшило запуск своего приложения на 45%.
Они смогли отложить инициализацию ненужных при запуске приложения элементов, а также выявили некоторые неправильно настроенные элементы, которые должны были быть одиночными, но не были ими. Такие проблемы легко обнаружить и исправить в коде.
Если вы посмотрите на их показатели запуска, они действительно впечатляют.
Улучшилось не только время до первого кадра, но и время до полного отображения.
Другой партнер, BandLab, использует ту же информацию о CI.
Таким образом, вы не только знаете стоимость каждой привязки @Inject, но и знаете, какой поток, вы знаете, понес эти затраты.
Итак, как только вы это узнаете, вы сможете найти все дорогостоящие привязки @Inject в основном потоке и в вашей CI, вы можете запустить запрос, чтобы сказать: «Эй, дайте мне список всех дорогостоящих привязок, а затем припишите его обратно к изменению, которое их ввело, и теперь вы можете обвинить фактическое изменение и попытаться его исправить».
Рахул Равикумар (Rahul Ravikumar)
Окей.
До сих пор я говорил обо всем, что мы улучшили по сравнению с Tracing 1, но теперь я собираюсь поговорить о новых функциях, которые есть в Tracing 2, которые ранее были невозможны.
Итак, одна из основных функций называется распространением контекста. Поскольку современные приложения становятся все более сложными, рабочие нагрузки выполняются в нескольких потоках, нескольких сопрограммах и нескольких процессах.
Вы хотите визуализировать, как запрос распространяется между каждым отдельным потоком и процессом.
Именно это и позволяет сделать распространение контекста.
Итак, если бы я просто дал вам список срезов, не рассказывая о том, что чем вызвано, они были бы полезны, но о них было бы не очень легко рассуждать.
Но если бы я сказал вам, что это была причинно-следственная цепочка событий, то вам было бы намного проще понять, что происходит, а затем связать стоимость каждого отдельного фрагмента.
Это то, что делает доступным распространение контекста.
Вы будете рады узнать, что распространение контекста полностью поддерживается, и вот реальный пример.
Вернемся к трассировке Perfetto com.example.app. Предположим, что выполнение performInitialize занимает слишком много времени и вы хотите отложить его или перенести в другой поток.
Это вполне возможно.
Допустим, я переместил performInitialize в другую цепочку.
Теперь вы потеряли иерархическую природу среза.
Теперь вы не сможете определить, что именно initializeComponent вызывает performInitialize, если не посмотрите код.
В идеальном мире вы бы хотели, чтобы стрелка указывала, что А вызвало Б, и тогда вы могли бы рассуждать о причинно-следственной цепочке событий.
Возможно, вы даже видели трассировку системы, в которой мы делаем это для транзакций Binder на платформе.
Здесь вы видите, что тест Compose выполняет транзакцию связывания с system_server, чтобы подготовить кадр.
То есть это то, что всегда было возможно с точки зрения трассировки платформы, но мы никогда не предоставляли эти инструменты разработчикам приложений.
Теперь распространение контекста сопрограмм Kotlin полностью поддерживается в Tracing 2.0.
Вам не придется ничего делать.
Просто достаньте его из коробки.
Итак, у нас есть один вызов метода приостановки, который называется fetchProfile.
Он вызывает client.get, который является другим методом приостановки, а затем переключается на Dispatchers.Default для десериализации ответа.
Это стандартный код сопрограмм, с которым вы, вероятно, сталкиваетесь каждый день.
Теперь предположим, что мы хотим это отследить.
Добавляем раздел трассировки.
Поэтому вместо trace мы будем использовать API traceCoroutine, поскольку это приостанавливающий блок кода, а затем для внутреннего вызова перед переключением контекста на Dispatchers.Default мы добавим ещё один внутренний раздел трассировки, используя тот же API traceCoroutine.
Теперь в трассировке вы увидите примерно следующее.
Вы увидите, что работа началась в worker-1, а затем переключилась на worker-3. На это указывают стрелки в трассировке.
Если увеличить квадрат в центре, можно увидеть, что десериализация началась в worker-1, а вызов withContext привел к переключению контекста, после чего она продолжилась в worker-3, а затем fetchProfile возобновилась в worker-3, потому что механизм сопрограмм стремится минимизировать количество переключений контекста.
Вы можете точно увидеть, когда сопрограмма была приостановлена, когда возобновлена, а также полную причинно-следственную цепочку событий.
Ещё одна возможность, которую предоставляет Tracing 2, – добавление собственных метаданных в трассировку.
Раньше единственным инструментом было название раздела трассировки, а теперь вы можете добавить блок метаданных с любым количеством записей.
И вы можете добавить это в трассировку.
Если вы посмотрите на трассировку, то увидите, что все добавленные вами метаданные действительно находятся в ней и доступны для использования всеми инструментами.
Теперь вы можете встроить все, что знаете, всю дополнительную информацию, которую всегда хотели.
Я рассказал вам о нескольких абстрактных функциях, которые становятся возможными благодаря трассировке, но все это становится по-настоящему полезным в новой функции Jetpack Compose под названием Recomposition Tracing.
Она поставляется в составе Compose 1.13, поэтому вы можете использовать ее уже сегодня.
Вот пример.
Это трассировка композиции, с которой вы, вероятно, все знакомы.
Она существует с первых дней Compose.
Он показывает относительную стоимость composable-функции и всех ее, ну, вы знаете, подсегментов, а также стоимость каждого из них в потоке, в котором они происходили.
Итак, это довольно просто.
Но он не дает контекста.
но не объясняет, почему это произошло.
Он не сообщает вам причину, по которой вещи были перекомпонованы.
Если уменьшить масштаб, мы увидим область, которую рассматривали на предыдущем слайде.
А слева вы можете увидеть, что произошло событие ввода диспетчеризации.
Возможно, именно это изменило какое-то состояние и вызвало рекомпозицию.
Но это неясно.
Вы не знаете наверняка.
Однако теперь, благодаря трассировке рекомпозиции, мы добавляем в трассировку пользовательские метаданные, которые точно сообщают вам, почему произошли рекомпозиции.
Кроме того, теперь вам очень легко сказать, что эти события связаны.
Если вы нажмете на них, то увидите, что именно изменилось.
Он сообщит вам, что это было состояние, это было изменяемое значение состояния, которое было переключено на false, которое ранее было true.
и даже покажет стек вызовов, который к ней привел.
Итак, здесь вы можете видеть, что произошло AbstractClickableNode.performClick, что привело к изменению изменяемого состояния, что привело к рекомпозиции.
Это действительно здорово, раньше мы не могли этого делать.
Эти инструменты также доступны, извините, все эти функции также доступны в новом инструменте Android Performance Analyzer, если вы хотите попробовать некоторые из агентских инструментов.
и вправо.
Итак, я сказал, что распространение контекста полностью поддерживается для сопрограмм Kotlin.
Но что делать, если в коде используются и сопрограммы, и другие конструкции, или вы запускаете потоки самостоятельно, или у вас есть старый код, в котором по какой-то причине используются обратные вызовы?
Окей.
Хорошая новость в том, что вы по-прежнему можете использовать все преимущества распространения контекста.
Допустим, у нас есть API, который использует обратный вызов и исполнитель.
Реализация использует executor.execute, вызывает runCatching, получает ответ и передает его обратному вызову.
Окей.
Теперь, если я хочу отследить это, я делаю Tracer.global.trace, даю ему метку, а затем окружаю блок.
Но поскольку я также хочу сохранить причинно-следственную цепочку событий, я приму новый необязательный тип, который называется токеном распространения.
И я просто передам токен внутреннему API трассировки.
Таким образом, тот, кто вызывает этот метод, может при необходимости передать мне токен распространения, чтобы я мог сохранить причинно-следственную цепочку происходящих событий.
Окей.
Теперь вызывающий объект этого API может быть приостанавливающим API.
Итак, у меня есть функция приостановки profileRequest, которая теперь будет вызывать API, использующий обратный вызов и исполнитель.
Поскольку я соединяю два мира, мир приостановки с миром обратного вызова, я буду использовать конструктор suspendCoroutine.
Я получу продолжение, а затем просто вызову API и возобновлю продолжение в обратном вызове, как только получу ответ.
А вот исполнитель, которого я определяю, называется profileRequestContext.
Это однопоточный исполнитель.
А поскольку traceCoroutine встраивает токен распространения в контекст сопрограммы, я могу получить токен распространения из контекста сопрограммы, а затем передать его в качестве входных данных в API brownfield, чтобы сохранить причинно-следственную цепочку событий.
И в трассировке это становится очевидным.
Итак, здесь у вас есть что-то, что началось в worker-3, которое переключилось на однопоточный исполнитель, как только мы переключили контекст, а затем возобновилось на worker.
Это очень удобно.
Рахул Равикумар (Rahul Ravikumar)
Окей.
Вы также можете настроить Tracer.global.
Пока что Tracing 2.0 API предоставляет вам действительно хорошие значения по умолчанию для того, чем должен быть Tracer.global, но если вы когда-нибудь захотите настроить его, вы можете это сделать.
Кроме того, Tracing 2.0 поддерживает JVM и Android, поскольку мы хотим, чтобы трассировка полностью поддерживалась как для библиотек Java, так и для библиотек Android.
Итак, три шага для инициализации: вы создаете приемник трассировки.
Приемник трассировки – это способ хранения пакетов трассировки.
Он определяет формат передачи и место хранения выходных трассировок.
Мы предоставляем готовую реализацию приемника трассировки, поддерживающего формат Perfetto, но вы можете написать собственный приемник.
Это возвращает нас к попытке решить проблему, заключающуюся в том, что atrace был единственным бэкендом, доступным в Tracing 1.
Мы решили это исправить.
Теперь вы можете написать приемник OpenTelemetry или использовать собственный.
Вы можете переопределить это поведение.
После создания приемника вы можете создать драйвер трассировки и передать ему приемник.
Вы также можете выбрать, какие категории хотите включить.
Вот здесь категории действительно полезны.
Вы можете решить, что в релизе некоторые категории важнее других, и включить только их.
или "Я хочу включить все категории независимо от того, откуда они взялись".
И это совершенно нормально.
Вы также можете добавить настраиваемые атрибуты, которые являются глобальными для вашей трассировки.
Таким образом, вы можете встраивать такие вещи, как версия сборки, разновидность или любые другие метаданные, которые вы хотите прикрепить к трассировке, можно прикрепить с помощью API addAttribute.
Наконец, вы можете зарегистрировать трассировщик, вызвав setGlobalTracer.
Это связывает Tracer.global с этим экземпляром трассировщика, и впоследствии это становится доступно для процесса.
В Android жизненный цикл процессов определен гораздо лучше, поэтому вам нужно лишь реализовать AbstractTraceDriver.Factory, переопределить его метод create и сделать то же, что и раньше.
Итак, вы создаете приемник, а затем создаете драйвер.
Регистрация не требуется.
Мы просто зарегистрируем вас, потому что знаем, что это произошло в первую очередь.
Окей.
Итак, я хочу повторить, что трассировка готова к работе на нескольких платформах.
Это сделано намеренно, поскольку Compose работает на нескольких платформах, и мы хотим, чтобы вы могли выполнять трассировку в как можно большем количестве мест.
Сегодня мы поддерживаем Android и JVM, но наша реализация оставляет его полностью открытым для нас, чтобы поддерживать будущие платформы, если мы захотим.
Рахул Равикумар (Rahul Ravikumar)
R8 – инструмент, который используется для сжатия и оптимизации исходного кода на Android, – использует Tracing 2.0.
Благодаря трассировке мы оптимизировали R8, чтобы он уменьшал и оптимизировал код на 25 % быстрее.
Это означает, что сборка будет выполняться быстрее и вам не придется долго ждать оптимизации.
Я не буду рассказывать обо всех оптимизациях, которые мы сделали в R8, а остановлюсь только на одной, чтобы вы поняли, какие возможности открывает трассировка.
По сути, R8 – это преобразователь исходного кода.
Итак, вы получаете набор JAR-файлов, сжимаете и оптимизируете их, а затем создаете другой набор JAR-файлов, которые можно преобразовать в DEX.
Итак, AGP начинает со считывания JAR-файлов, которые представляют собой не только ваше приложение, но и все его зависимости.
Поэтому он использует рабочие процессы Gradle, чтобы начать чтение всех входных JAR-файлов.
У вас есть много JAR-файлов, которые вы хотите прочитать.
Затем, когда чтение JAR-файлов завершено, R8 начинает анализировать код и строить модель того, что представляет собой ваш код, и всех его точек входа, чтобы начать оптимизацию и сокращение кода.
Теперь это фрагмент, await, который представляет, когда R8 действительно готов фактически начать процесс оптимизации, верно?
Вы можете увидеть некоторое мертвое пространство посередине, и вам может быть интересно, почему у нас есть это, вы знаете, неиспользуемое процессорное время.
Причина в том, что старый API ждал, пока все рабочие процессы прочитают все свои файлы, прежде чем что-либо анализировать.
Очевидно, что мы можем это исправить, что мы и сделали.
В AGP 9 обработка JAR-файлов начинается сразу после их считывания.
И нам не пришлось ждать, пока каждый рабочий закончит читать свои входные данные.
Это позволило значительно сократить время, необходимое для чтения всех входных данных.
Это очевидная оптимизация, которую вы можете увидеть, когда смотрите на трассировку, но не так очевидно, когда вы просто смотрите на исходный код, чтобы увидеть, что стоит оптимизировать.
Ещё один инструмент, который мы используем каждый день как инженеры AndroidX, – это Metalava.
Metalava – это инструмент, который мы используем, чтобы убедиться, что все поставляемые нами API имеют ожидаемые вами гарантии совместимости API и могут полностью использоваться внешними пользователями без каких-либо проблем, которых мы хотим избежать.
Этот инструмент работает с каждым общедоступным и ограниченным API, поэтому любое сэкономленное время – это время, которое мы возвращаем инженерам AndroidX.
Metalava также использовала трассировку, чтобы сократить время после отправки на целых 15 %.
Изучив трассировку, мы можем объяснить, что произошло. Metalava выполняет два типа проверок: сначала проверяет API с ограниченным доступом, а затем – общедоступные API.
Но вы, возможно, заметили закономерность.
Мы выполняем множество настроек, чтобы запустить эти проверки дважды.
Итак, все входные данные программы считываются, и мы создаем PSI, то есть интерфейс структуры программы, или, знаете, точную форму вашего кода, о которой можно рассуждать.
Затем мы строим AST, прежде чем начать применять все проверки lint, которые мы хотим.
И мы делаем эту дорогостоящую работу дважды.
Как мы это исправили?
Мы сделали это один раз.
Поэтому вместо того, чтобы выполнять всю эту работу по настройке дважды, мы сделали это один раз и повторно использовали эти входные данные как для ограниченных, так и для общедоступных проверок, тем самым получив всю эту экономию.
Да.
Окей.
Рахул Равикумар (Rahul Ravikumar)
Теперь, когда я дал вам представление о том, что делает возможным Tracing 2.0, важно знать, что, хотя трассировка важна, знание того, что трассировать, также не менее важно.
Не нужно добавлять трассировки повсюду.
Выбирать нужно очень тщательно, и я постараюсь дать вам несколько рекомендаций о том, что стоит отслеживать.
Поэтому в первую очередь нужно найти необъяснимые пробелы в трассировке.
Поэтому, если вы видите очевидные пробелы в трассировке системы, когда потоки выполняются или готовы к выполнению, и не можете объяснить их, а также не знаете, что делает ваше приложение, возможно, стоит провести расследование.
В этот момент я могу взять трассировку метода, наложенную на трассировку системы, и посмотреть, что стоит трассировать, и я могу добавить эти соответствующие разделы трассировки.
Вы также хотите расставить приоритеты по путям пользователей.
Итак, вы хотите посмотреть на запуск приложения.
Вы хотите посмотреть на основные пути пользователей в приложении и понять, можно ли объяснить их, глядя на трассировку.
Поэтому, если вы не можете что-то объяснить, это стоит отследить.
Также следует обратить внимание на глубокие стеки вызовов или необъяснимое использование ЦП в трассировке и попытаться выяснить, что именно происходит, а затем преобразовать эти части базы кода в трассировки.
Так что вы можете их отследить.
И наконец, если потоки спят, нужно понять, почему это происходит.
Они должны ожидать ввода-вывода, транзакции связывателя или внешних событий ввода, которые вы ожидаете.
Но если у вас, знаете, необъяснимый сон, то это крайне заслуживает изучения, потому что, очевидно, там может что-то скрываться.
И затем, как только вы, знаете, посыпали все разделы трассировки в этом коде, вы должны преобразовать их в контрольные показатели, чтобы вы могли отслеживать изменения в них.
По мере развития базы кода вы можете видеть, меняются ли показатели, отражают ли ваши панели мониторинга большие изменения, потому что тогда вы знаете, что изменилось что-то важное.
Или вы можете пропустить все предыдущие шаги и просто попросить агента сделать это.
Возьмите эти рекомендации, превратите их в навык, а затем укажите на него своему любимому агенту и попросите его попробовать.
Да.
Рахул Равикумар (Rahul Ravikumar)
Если я убедил вас, что трассировка – это полезный инструмент, который стоит использовать, давайте перейдем к настройке проекта.
Это довольно просто.
Трассировка – это просто традиционная библиотека Java, поэтому вы определяете зависимость от androidx.tracing:tracing-wire, которая представляет собой совместимый с Perfetto драйвер трассировки и комбинацию трассировки, а текущая стабильная версия – 2.0.5.
Если вы используете библиотеку Java, то все будет точно так же, поскольку это полностью мультиплатформенный API.
Мы хотим расширить его на другие платформы, когда это будет иметь смысл.
И да, я просто хотел сделать краткий обзор.
Итак, я рассказал обо всех этих новых классных функциях, которые мы добавили.
Так что распространение контекста – это действительно мощный инструмент.
Мы можем встраивать пользовательскую информацию, метаданные, информацию о стеке вызовов и многое другое.
Я не говорил о многих, многих вещах.
Вы можете изменить формат трассировки, изменить приемник трассировки, вы можете, знаете ли, перенести данные трассировки в OpenTelemetry.
Это всё, что вы можете сделать.
Трассировка является мультиплатформенной.
Это было очень осознанное решение, потому что мы хотим, чтобы как можно больше людей могли воспользоваться этим.
И все инструменты, которые мы поставляем, будь то Perfetto, AndroidX Benchmarks, новый анализатор производительности или старый Android Profiler, поддерживают Tracing 2.0.
Спасибо за внимание.
Желаю вам отлично провести саммит разработчиков. Спасибо!