- PVSM.RU - https://www.pvsm.ru -

Использование фронтенда профилировщика Chrome в собственных проектах

Возможно, вы знаете, что у браузере Google Chrome есть встроенный профилировщик [1]. Но даже из тех людей, кто его видел, большинство считает, что использовать его можно только для отладки Javascript или отрисовки кадров в браузере. Но на самом деле его весьма просто можно прикрутить в качестве средства визуализации данных профилирования в вашем проекте.

Я не открою здесь каких-то уникальных секретов, например, Colt McAnlis [2] писал о подобном применении профилировщика Chrome в игровых проектах ещё в 2012 году [3]. Всё, написанное там, всё ещё является правдой, а я напишу ещё один материал — просто для лучшего распространения знаний о столь полезном инструменте.

Предыстория

Для некоторой части нашей системы сборки кода мы когда-то написали простенький профилировщик (называется TinyProfiler). Он достаточно тривиален — замеряет время выполнения определенных блоков кода и создаёт набор HTML+SVG файлов, которые визуализируют эти данные в стиле flame-графов [4]:

image

Это, в принципе, неплохо работало, но полученный HTML был не очень интерактивным. Можно было подвести мышку к определенному блоку и увидеть его название во всплывающей подсказке, но на этом все удобства и заканчивались. Не было ни зума, ни фильтрации, ни скрола, ни поиска — в общем ничего, чего хотелось бы получить от более-менее профессионального инструмента. Всё это можно было, конечно, сесть и написать, но… зачем же это делать, если можно этого не делать? Ведь уже есть кто-то (разработчики Chrome), кто всё это уже сделал.

Использование Chrome Tracing

Всё, что нам нужно сделать, это:

  1. Создать JSON-файл определенного формата [5], содержащий данные о профилируемых событиях
  2. Открыть в Chrome страницу chrome://tracing
  3. Перетащить JSON-файл на эту страницу

Результат визуально достаточно похож на картинку нашего мини-профилировщика:

image

Преимущества данного подхода:

  • Значительно улучшенный UI: зум, скрол, фильтрация, статистика и т.д.
  • Нам больше не нужно писать свой (пусть даже простой) код для UI
  • Значительно упростившийся код по сбору и обработке данных (JSON создать проще, чем SVG)

Но есть и несколько недостатков:

  • Нет простого способа «кликнуть на файле отчёта для его открытия». Chrome не позволяет открывать файлы с trace-данными из командной строки. Приходится каждый раз открывать страницу chrome://tracing и уже только с неё открывать нужный файл.
  • Это можно исправить, если взять утилиту trace2html из репозитория [6] Chrome — она умеет создавать готовый HTML со всем необходимым. Но для этого придётся утянуть к себе, хранить и собирать 1 ГБ исходников (там ведь не одна эта утилита). А это как-то слишком много для подобной задачи. Возможно, получилось бы вырезать из репозитория только то, что необходимо для сборки данной утилиты — но на это ушло бы время, да и с дальнейшей поддержкой совместимости возникли бы проблемы.
  • Мы завязываемся на ещё один сторонний инструмент. Однако он, по всей видимости, достаточно стабилен (например, упомянутая выше статья [3] 2012 года всё ещё дословно верна сейчас в 2017 году), открыт [6] и его уже используют некоторые серьёзные инструменты (вроде Facebook Buck [7]).

Мне кажется, что преимущества перевешивают недостатки.

Формат JSON-файла

Этот формат достаточно прост сам по себе, а также хорошо документирован [5]. Базовая структура выглядит вот так:

{
"traceEvents": [
{ "pid":1, "tid":1, "ts":87705, "dur":956189, "ph":"X", "name":"Jambase", "args":{ "ms":956.2 } },
{ "pid":1, "tid":1, "ts":128154, "dur":75867, "ph":"X", "name":"SyncTargets", "args":{ "ms":75.9 } },
{ "pid":1, "tid":1, "ts":546867, "dur":121564, "ph":"X", "name":"DoThings", "args":{ "ms":121.6 } }
],
"meta_user": "aras",
"meta_cpu_count": "8"
}

traceEvents — это события, которые будут показаны в UI. Всё, что не является событиями, считается «метаданными», которые будут показаны в диалоге метаданных (в данном случае это meta_user и meta_cpu_count). Вышеуказанный JSON-файл будет выглядеть в Chrome Tracing вот так:

image

События, которые описаны в нём, достаточно просты. Они называются «завершенными» (тип ph:X) — для их описания нам потребуется указать время начала и длительность в микросекундах (аттрибуты ts и dur). Ещё указываются аттрибуты ID процесса и ID потока, а также имя события. Необходимости указывать отношение родитель-ребёнок нет — UI определит его сам на основе времени начала и длительности каждого события.

К событиям также можно прикреплять какие-небудь данные (аттрибут args), которые при выборе данного события будут отображаться на нижней панели. Есть небольшой нюанс — чтобы событие вообще можно было выбрать, у него должен быть непустой args. То есть хотя бы что-нибудь (пусть даже ненужное) туда лучше положить. Не можете придумать что — продублируйте там длительность события (возможно, преобразовав его из микросекунд в милисекунды или секунды).

Вот и всё, что я хотел рассказать по базовому использованию этого инструмента. Возможно, статья получилась несколько простоватой — но это потому, что и сам инструмент простой и удобный. Для продвинутых вариантов его использования читайте документацию [5]. Удачного профилирования.

Автор: Владимир

Источник [8]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/google-chrome-2/262915

Ссылки в тексте:

[1] встроенный профилировщик: http://dev.chromium.org/developers/how-tos/trace-event-profiling-tool

[2] Colt McAnlis: https://twitter.com/duhroach

[3] ещё в 2012 году: http://www.gamasutra.com/view/news/176420/Indepth_Using_Chrometracing_to_view_your_inline_profiling_data.php

[4] flame-графов: http://queue.acm.org/detail.cfm?id=2927301

[5] определенного формата: https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit

[6] репозитория: https://github.com/catapult-project/catapult/tree/master/tracing

[7] Facebook Buck: https://buckbuild.com/about/performance_tuning.html

[8] Источник: https://habrahabr.ru/post/336584/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best