Как и почему мы создали Performance Insights

В Chrome 102 вы увидите новую экспериментальную панель Performance Insights в DevTools. В этом посте мы обсудим не только то, почему мы работаем над новой панелью, но также технические проблемы, с которыми мы столкнулись, и решения, которые мы приняли на этом пути.

ALT_TEXT_ЗДЕСЬ

Зачем строить еще одну панель?

(Если вы еще не видели его, мы опубликовали видео о том, зачем создавать панель Performance Insights и как с ее помощью можно получить полезную информацию о производительности вашего веб-сайта.)

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

Войдите на панель статистики, где вы по-прежнему можете просмотреть временную шкалу трассировки и проверить данные, а также получить удобный список того, что DevTools считает основными «инсайтами», которые стоит изучить. Insights выявит такие проблемы, как запросы на блокировку рендеринга, изменения макета и длительные задачи, и это лишь некоторые из них, которые могут негативно повлиять на производительность загрузки страниц вашего веб-сайта и, в частности, на показатели Core Web Vital (CWV) вашего сайта. Помимо оповещения о проблемах, Performance Insights предоставит вам практические рекомендации по улучшению ваших показателей CWV, а также предоставит ссылки на дополнительные ресурсы и документацию.

Ссылка на отзыв в панели

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

Как мы создавали Performance Insights

Как и остальные инструменты разработчика, мы создали Performance Insights на TypeScript и использовали веб-компоненты , поддерживаемыеlit -html , для создания пользовательского интерфейса. Отличие Performance Insights заключается в том, что основным интерфейсом пользовательского интерфейса является элемент canvas HTML , а временная шкала рисуется на этом холсте. Большая часть сложности связана с управлением этим холстом: не только рисование нужных деталей в нужном месте, но и управление событиями мыши (например: где пользователь щелкнул холст? Нажали ли они на событие, которое мы нарисовали? ) и убедитесь, что мы эффективно перерисовали холст.

Несколько треков на одном холсте

Для данного веб-сайта существует несколько «дорожек», которые мы хотим отобразить, каждая из которых представляет отдельную категорию данных. Например, на панели Insights по умолчанию отображаются три трека:

И по мере того, как мы продолжаем размещать функции на панели, мы ожидаем, что будут добавлены новые треки.

Наша первоначальная идея заключалась в том, чтобы каждая из этих дорожек отображала свой собственный <canvas> , чтобы основное представление представляло собой несколько элементов холста, расположенных вертикально. Это упростило бы рендеринг на уровне трека, поскольку каждый трек мог бы рендериться изолированно и не было бы опасности рендеринга трека за его пределами, но, к сожалению, у этого подхода есть две основные проблемы:

элементы canvas требуют больших затрат на (повторную) визуализацию; иметь несколько холстов дороже, чем один, даже если этот холст больше. Рендеринг любых наложений, пересекающих несколько дорожек (например, вертикальных линий для обозначения таких событий, как время FCP), становится сложным: нам приходится выполнять рендеринг на нескольких холстах и ​​гарантировать, что все они отображаются вместе и правильно выровнены.

Использование одного canvas для всего пользовательского интерфейса означало, что нам нужно было выяснить, как обеспечить рендеринг каждой дорожки с правильными координатами и не перетекать в другую дорожку. Например, если конкретная дорожка имеет высоту 100 пикселей, мы не можем позволить ей отображать что-то высотой 120 пикселей и переносить это на дорожку, находящуюся под ней. Чтобы решить эту проблему, мы можем использовать clip . Прежде чем визуализировать каждую дорожку, мы рисуем прямоугольник, представляющий видимое окно дорожки. Это гарантирует, что любые пути, нарисованные за пределами этих границ, будут обрезаны холстом.

canvasContext.beginPath();
canvasContext.rect(
    trackVisibleWindow.x, trackVisibleWindow.y, trackVisibleWindow.width, trackVisibleWindow.height);
canvasContext.clip();

Мы также не хотели, чтобы каждая дорожка знала свое положение по вертикали: каждая дорожка должна рендериться так, как если бы она отображалась в (0, 0), и у нас есть компонент более высокого уровня (который мы называем TrackManager ), чтобы управлять общим положение трека. Это можно сделать с помощью translate , который переводит холст на заданную позицию (x, y). Например:

canvasContext.translate(0, 10); // Translate by 10px in the y direction
canvasContext.rect(0, 0, 10, 10); // draw a rectangle at (0, 0) that’s 10px high and wide

Несмотря на то, что код rect устанавливает 0, 0 в качестве позиции, общий примененный сдвиг приведет к отображению прямоугольника в 0, 10 . Это позволяет нам работать на основе треков, как если бы мы выполняли рендеринг в (0, 0), и заставить наш менеджер треков переводить при рендеринге каждого трека, чтобы гарантировать, что каждый трек отображается правильно ниже предыдущего.

Закадровые полотна для треков и ярких моментов

Рендеринг холста обходится относительно дорого, и мы хотим, чтобы панель Insights оставалась плавной и отзывчивой во время работы с ней. Иногда вам не удастся избежать повторной визуализации всего холста: например, если вы измените уровень масштабирования, нам придется начинать заново и перерисовывать все. Повторный рендеринг холста особенно дорог, потому что вы не можете просто перерисовать небольшую его часть; нужно затереть весь холст и перерисовать. Это отличается от повторного рендеринга DOM, где инструменты могут рассчитать минимальную необходимую работу, а не удалять все и начинать заново.

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

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

Чтобы это исправить, мы разделили наш пользовательский интерфейс на два внеэкранных холста: «основной» холст, на котором происходит рендеринг дорожек, и холст «Основные моменты», на котором рисуются основные моменты. Затем мы выполняем рендеринг, копируя эти холсты на один холст, видимый пользователю на экране. Мы можем использовать метод drawImage в контексте холста, который может использовать другой холст в качестве источника.

Это означает, что удаление выделения не приводит к перерисовке основного холста: вместо этого мы можем очистить экранный холст, а затем скопировать основной холст на видимый холст. Копирование холста обходится дешево, а рисунок стоит дорого; поэтому, перемещая блики на отдельный холст, мы избегаем этих затрат при включении и выключении бликов.

Всесторонне протестированный анализ трассировки

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

Проанализируйте файл трассировки и извлеките необходимые данные. Рендеринг набора треков.

Отделение синтаксического анализа (часть 1) от работы с пользовательским интерфейсом (часть 2) позволило нам построить надежную систему синтаксического анализа; каждая трассировка проходит через серию обработчиков , которые отвечают за различные задачи: LayoutShiftHandler вычисляет всю информацию, необходимую для сдвигов макета, а NetworkRequestsHandler занимается исключительно извлечением сетевых запросов. Наличие этого явного этапа синтаксического анализа, где у нас есть разные обработчики, отвечающие за разные части трассировки, также оказалось полезным: синтаксический анализ трассировки может стать очень сложным, и это помогает сосредоточиться на одной проблеме за раз.

Мы также смогли всесторонне протестировать наш анализ трассировки, сняв записи в DevTools, сохранив их, а затем загрузив как часть нашего набора тестов. Это здорово, потому что мы можем тестировать реальные трассировки, а не создавать огромные объемы поддельных данных трассировки, которые могут устареть.

Тестирование скриншотов пользовательского интерфейса Canvas

Продолжая тему тестирования, мы обычно тестируем наши интерфейсные компоненты, отображая их в браузере и проверяя, что они ведут себя должным образом; мы можем отправлять события кликов для запуска обновлений и утверждать, что DOM, генерируемый компонентами, верен. Этот подход хорошо работает для нас, но не работает при рендеринге на холст; нет возможности осмотреть холст и определить, что там нарисовано! Поэтому наш обычный подход, заключающийся в рендеринге и последующем запросе, не подходит.

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

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

Заключение

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

Дополнительные сведения о панели «Статистика производительности» см . в разделе «Статистика производительности: получите полезную информацию о производительности вашего веб-сайта» .

Загрузите предварительный просмотр каналов

Рассмотрите возможность использования Chrome Canary , Dev или Beta в качестве браузера для разработки по умолчанию. Эти каналы предварительного просмотра предоставляют вам доступ к новейшим функциям DevTools, позволяют тестировать передовые API-интерфейсы веб-платформы и помогают находить проблемы на вашем сайте раньше, чем это сделают ваши пользователи!

Свяжитесь с командой Chrome DevTools

Используйте следующие параметры, чтобы обсудить новые функции, обновления или что-либо еще, связанное с DevTools.