На пути к лучшей метрике реагирования

Узнайте о наших мыслях по измерению оперативности и поделитесь с нами своим мнением.

Энни Салливан
Annie Sullivan
Хунбо Сонг
Hongbo Song
Николас Пенья Морено
Nicolás Peña Moreno

В команде Chrome Speed ​​Metrics мы работаем над углублением понимания того, как быстро веб-страницы реагируют на действия пользователя. Мы хотели бы поделиться некоторыми идеями по улучшению показателей оперативности и услышать ваши отзывы.

В этом посте будут рассмотрены две основные темы:

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

Что такое задержка первого ввода?

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

  • click
  • keydown
  • mousedown
  • pointerdown (только если за ним следует pointerup )

Следующая диаграмма иллюстрирует FID:

Задержка первого ввода измеряется с момента поступления ввода до момента, когда ввод может быть обработан.

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

Почему мы выбрали ФИД?

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

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

На это есть несколько причин. Возможно, самая важная причина заключается в том, что эти метрики не измеряют взаимодействие с пользователем напрямую. Все эти показатели измеряют, сколько JavaScript выполняется на странице. Хотя длительная работа JavaScript обычно вызывает проблемы на сайтах, эти задачи не обязательно влияют на взаимодействие с пользователем, если пользователь не взаимодействует со страницей во время их выполнения. Страница может иметь высокие оценки по TBT и TTI, но казаться медленной, или же она может иметь низкую оценку, но при этом быть быстрой для пользователей. По нашему опыту, эти косвенные измерения приводят к показателям, которые отлично работают для некоторых сайтов, но не для большинства сайтов. Короче говоря, тот факт, что длинные задачи и TTI не ориентированы на пользователя, делает этих кандидатов более слабыми.

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

Примечание по измерению TTI в полевых условиях

Измерение TTI реальных пользователей в полевых условиях проблематично, поскольку оно происходит очень поздно при загрузке страницы. Прежде чем можно будет вычислить TTI, требуется 5-секундное окно тишины в сети. В лаборатории вы можете выгружать страницу всякий раз, когда у вас есть все необходимые данные, но это не относится к реальному мониторингу пользователей в полевых условиях. Пользователь может покинуть страницу или взаимодействовать с ней в любое время. В частности, пользователи могут покинуть страницы, загрузка которых занимает много времени, и в таких случаях точный TTI не будет записан. Когда мы измерили TTI для реальных пользователей в Chrome, мы обнаружили, что только около половины загрузок страниц достигли TTI.

Какие улучшения мы рассматриваем?

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

Мы хотим, чтобы новый показатель:

  1. Учитывайте отзывчивость всех пользовательских действий (а не только первого).
  2. Захватывайте полную продолжительность каждого события (а не только задержку).
  3. Сгруппируйте вместе события, которые происходят как часть одного и того же логического взаимодействия с пользователем, и определите задержку этого взаимодействия как максимальную продолжительность всех его событий.
  4. Создайте совокупную оценку для всех взаимодействий, происходящих на странице, на протяжении всего ее жизненного цикла.

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

Захватите полную продолжительность мероприятия

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

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

Пять шагов жизненного цикла мероприятия

Ниже приведены шаги, которые Chrome предпринимает для обработки ввода:

  1. Происходит ввод данных от пользователя. Время, в которое это происходит, является timeStamp события.
  2. Браузер выполняет проверку попадания, чтобы решить, какому фрейму HTML (основному фрейму или iframe) принадлежит событие. Затем браузер отправляет событие соответствующему процессу рендеринга, отвечающему за этот HTML-фрейм.
  3. Средство визуализации получает событие и ставит его в очередь, чтобы обработать его, когда оно станет доступным.
  4. Средство визуализации обрабатывает событие, запуская его обработчики. Эти обработчики могут ставить в очередь дополнительную асинхронную работу, такую ​​как setTimeout и выборки, которые являются частью обработки ввода. Но на этом синхронная работа завершена.
  5. На экране отображается кадр, отражающий результат работы обработчиков событий. Обратите внимание, что любые асинхронные задачи, поставленные в очередь обработчиками событий, могут оставаться незавершенными.

Время между шагами (1) и (3), указанными выше, представляет собой задержку события, которую измеряет FID.

Время между шагами (1) и (5) выше — это продолжительность события. Это то, что будет измерять наша новая метрика.

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

Примечание об асинхронных задачах

В идеале нам бы хотелось также зафиксировать асинхронную работу, вызванную этим событием. Но проблема в том, что правильно определить асинхронную работу, вызванную событием, чрезвычайно сложно. Например, разработчик может выбрать запуск анимации в обработчиках событий и использовать setTimeout для запуска такой анимации. Если бы мы захватили все задачи, размещенные в обработчиках, анимация задержала бы время завершения до тех пор, пока выполняется анимация. Мы считаем, что стоит изучить варианты использования эвристики для захвата асинхронной работы, которую следует выполнить как можно скорее. Однако мы хотим быть очень осторожными при этом, потому что мы не хотим наказывать работу, выполнение которой должно занять много времени. Таким образом, наши первоначальные усилия будут рассматривать шаг 5 как конечную точку: он будет учитывать только синхронную работу и количество времени, необходимое для рисования после завершения такой работы. То есть мы не собираемся применять эвристику, чтобы угадать работу, которая будет запущена асинхронно на шаге 4 в нашей первоначальной попытке.

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

Группируйте события во взаимодействия

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

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

Типы взаимодействия

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

Взаимодействие Начать конец События рабочего стола Мобильные мероприятия
Клавиатура Клавиша нажата keydown keydown
keypress keypress
Ключ выпущен keyup keyup
Коснитесь или перетащите Нажмите «Старт» или перетащите «Старт». pointerdown pointerdown
mousedown touchstart
Нажмите вверх или перетащите конец pointerup pointerup
mouseup touchend
click mousedown
mouseup
click
Прокрутка Н/Д
События DOM для каждого типа взаимодействия.

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

Примечание о начале и конце

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

Клавиатура

Взаимодействие с клавиатурой состоит из двух частей: когда пользователь нажимает клавишу и когда он ее отпускает. С этим взаимодействием с пользователем связаны три события: keydown , keyup и keypress . На следующей диаграмме показаны задержки и продолжительность keydown и нажатия keyup при взаимодействии с клавиатурой:

Взаимодействие с клавиатурой при непересекающейся продолжительности событий

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

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

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

Примечание о повторяющихся нажатиях клавиш

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

Кран

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

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

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

Можем ли мы сузить дальше до просто pointerdown и pointerup ?

Первой мыслью было бы использовать события pointerdown и pointerup и предположить, что они охватывают все интересующие нас длительности. К сожалению, это не так, как показывает этот крайний случай . Попробуйте открыть этот сайт на мобильном телефоне или с помощью мобильной эмуляции и нажать там, где написано «Нажмите на меня». Этот сайт вызывает задержку нажатия браузера . Видно, что pointerdown , pointerup и touchend отправляются быстро, тогда как mousedown , mouseup и click ждут задержки перед отправкой. Это означает, что если бы мы смотрели только на pointerdown и pointerup , мы бы пропустили продолжительность синтетических событий, которая велика из-за задержки касания браузера и должна быть включена. Поэтому нам нужно измерить pointerdown , pointerup и click , чтобы охватить все взаимодействие.

Тащить

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

Мы также не рассматриваем возможности перетаскивания, реализованные с помощью API перетаскивания, поскольку они работают только на настольных компьютерах.

Прокрутка

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

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

Так зачем же измерять свитки? Результаты производительности прокрутки, которые мы собрали в Chrome, показывают, что прокрутка обычно происходит очень быстро. Тем не менее, мы по-прежнему хотим включить начальную задержку прокрутки в нашу новую метрику по разным причинам. Во-первых, прокрутка быстрая только потому, что она так сильно оптимизирована, потому что это так важно. Но у веб-сайта все еще есть способы обойти некоторые преимущества производительности, которые предлагает браузер. Самый распространенный способ в Chrome — принудительная прокрутка в основном потоке. Таким образом, наша метрика должна быть в состоянии сказать, когда это происходит и приводит к ухудшению производительности прокрутки для пользователей. Во-вторых, прокрутка слишком важна, чтобы ее игнорировать. Мы обеспокоены тем, что если мы исключим прокрутку, у нас будет большая слепая зона, и производительность прокрутки может со временем снизиться, даже если веб-разработчики этого не заметят.

Существует несколько событий, которые отправляются, когда пользователь прокручивает страницу, например touchstart , touchmove и scroll . За исключением события прокрутки, это во многом зависит от устройства, используемого для прокрутки: события касания отправляются при прокрутке пальцем на мобильных устройствах, а события колеса происходят при прокрутке колесиком мыши. События прокрутки запускаются после завершения начальной прокрутки. И вообще, никакое событие DOM не блокирует прокрутку, если только на сайте не используются непассивные прослушиватели событий . Поэтому мы считаем, что прокрутка вообще не связана с событиями DOM. Мы хотим измерить время с момента, когда пользователь переместился достаточно, чтобы выполнить жест прокрутки, до первого кадра, показывающего, что произошла прокрутка.

Как определить задержку взаимодействия?

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

Для этих типов взаимодействий мы хотели бы, чтобы задержка включала продолжительность всех событий, связанных с ними. Поскольку длительность событий для каждой «нисходящей» и «восходящей» части взаимодействия может перекрываться, простейшим определением задержки взаимодействия, позволяющим добиться этого, является максимальная продолжительность любого события, связанного с ним. Возвращаясь к диаграмме клавиатуры, приведенной ранее, это будет длительность keydown , поскольку она длиннее, чем keyup :

Взаимодействие с клавиатурой, выделена максимальная продолжительность

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

Взаимодействие с клавиатурой, при котором нажатие и отпускание происходят в одном кадре

У такого подхода с максимальным использованием есть свои плюсы и минусы, и нам интересно услышать ваши отзывы :

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

Для прокрутки (с которой связано только одно событие) мы хотели бы определить ее задержку как время, необходимое браузеру для создания первого кадра в результате прокрутки. То есть задержка — это разница между событием timeStamp первого события DOM (например, touchmove , если используется палец), которое достаточно велико, чтобы вызвать прокрутку, и первой отрисовкой, отражающей происходящую прокрутку.

Объедините все взаимодействия на странице

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

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

Для выполнения этой агрегации нам необходимо решить два вопроса:

  1. Какие числа мы пытаемся агрегировать?
  2. Как нам агрегировать эти цифры?

Мы рассматриваем и оцениваем несколько вариантов. Мы приветствуем ваши мысли по поводу этого агрегата.

Один из вариантов — определить бюджет задержки взаимодействия, который может зависеть от типа (прокрутка, клавиатура, касание или перетаскивание). Например, если бюджет для касаний составляет 100 мс, а задержка касания — 150 мс, то превышение бюджета для этого взаимодействия составит 50 мс. Затем мы могли бы вычислить максимальную задержку, превышающую бюджет для любого взаимодействия пользователя на странице.

Другой вариант — вычислить среднюю или медианную задержку взаимодействий на протяжении всего существования страницы. Таким образом, если бы у нас были задержки 80 мс, 90 мс и 100 мс, то средняя задержка для страницы составила бы 90 мс. Мы также могли бы рассматривать среднее или медианное значение «превышения бюджета», чтобы учитывать разные ожидания в зависимости от типа взаимодействия.

Как это выглядит в API веб-производительности?

Чего не хватает в расписании событий?

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

Еще одним недостатком API синхронизации событий является отсутствие способа измерения взаимодействия с прокруткой, поэтому мы работаем над включением этих измерений (с помощью синхронизации событий или отдельного API).

Что вы можете попробовать прямо сейчас?

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

let maxTapOrDragDuration = 0;
let maxKeyboardDuration = 0;
const observer = new PerformanceObserver(list => {
  list.getEntries().forEach(entry => {
    switch(entry.name) {
      case "keydown":
      case "keyup":
        maxKeyboardDuration = Math.max(maxKeyboardDuration,
            entry.duration);
        break;
      case "pointerdown":
      case "pointerup":
      case "click":
        maxTapOrDragDuration = Math.max(maxTapOrDragDuration,
            entry.duration);
        break;
    }
  });
});
observer.observe({type: "event", durationThreshold: 16, buffered: true});
// We can report maxTapDragDuration and maxKeyboardDuration when sending
// metrics to analytics.

Обратная связь

Дайте нам знать, что вы думаете об этих идеях, написав по электронной почте: web-vitals-feedback@googlegroups.com!

,

Узнайте о наших мыслях по измерению оперативности и поделитесь с нами своим мнением.

Энни Салливан
Annie Sullivan
Хунбо Сонг
Hongbo Song
Николас Пенья Морено
Nicolás Peña Moreno

В команде Chrome Speed ​​Metrics мы работаем над углублением понимания того, как быстро веб-страницы реагируют на действия пользователя. Мы хотели бы поделиться некоторыми идеями по улучшению показателей оперативности и услышать ваши отзывы.

В этом посте будут рассмотрены две основные темы:

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

Что такое задержка первого ввода?

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

  • click
  • keydown
  • mousedown
  • pointerdown (только если за ним следует pointerup )

Следующая диаграмма иллюстрирует FID:

Задержка первого ввода измеряется с момента поступления ввода до момента, когда ввод может быть обработан.

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

Почему мы выбрали ФИД?

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

Другие показатели, такие как общее время блокировки (TBT) и время взаимодействия (TTI), основаны на длительных задачах и, как и FID, также измеряют время блокировки основного потока во время загрузки. Поскольку эти показатели можно измерить как в полевых условиях, так и в лаборатории, многие разработчики спрашивают, почему мы не предпочитаем один из них FID.

На это есть несколько причин. Возможно, самая важная причина заключается в том, что эти метрики не измеряют взаимодействие с пользователем напрямую. Все эти показатели измеряют, сколько JavaScript выполняется на странице. Хотя длительная работа JavaScript обычно вызывает проблемы на сайтах, эти задачи не обязательно влияют на взаимодействие с пользователем, если пользователь не взаимодействует со страницей во время их выполнения. Страница может иметь высокие оценки по TBT и TTI, но казаться медленной, или же она может иметь низкую оценку, но при этом быть быстрой для пользователей. По нашему опыту, эти косвенные измерения приводят к показателям, которые отлично работают для некоторых сайтов, но не для большинства сайтов. Короче говоря, тот факт, что длинные задачи и TTI не ориентированы на пользователя, делает этих кандидатов более слабыми.

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

Примечание по измерению TTI в полевых условиях

Измерение TTI реальных пользователей в полевых условиях проблематично, поскольку оно происходит очень поздно при загрузке страницы. Прежде чем можно будет вычислить TTI, требуется 5-секундное окно тишины в сети. В лаборатории вы можете выгружать страницу всякий раз, когда у вас есть все необходимые данные, но это не относится к реальному мониторингу пользователей в полевых условиях. Пользователь может покинуть страницу или взаимодействовать с ней в любое время. В частности, пользователи могут покинуть страницы, загрузка которых занимает много времени, и в таких случаях точный TTI не будет записан. Когда мы измерили TTI для реальных пользователей в Chrome, мы обнаружили, что только около половины загрузок страниц достигли TTI.

Какие улучшения мы рассматриваем?

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

Мы хотим, чтобы новый показатель:

  1. Учитывайте отзывчивость всех пользовательских действий (а не только первого).
  2. Захватывайте полную продолжительность каждого события (а не только задержку).
  3. Сгруппируйте вместе события, которые происходят как часть одного и того же логического взаимодействия с пользователем, и определите задержку этого взаимодействия как максимальную продолжительность всех его событий.
  4. Создайте совокупную оценку для всех взаимодействий, происходящих на странице, на протяжении всего ее жизненного цикла.

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

Захватите полную продолжительность мероприятия

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

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

Пять шагов жизненного цикла мероприятия

Ниже приведены шаги, которые Chrome предпринимает для обработки ввода:

  1. Происходит ввод данных от пользователя. Время, в которое это происходит, является timeStamp события.
  2. Браузер выполняет проверку попадания, чтобы решить, какому фрейму HTML (основному фрейму или iframe) принадлежит событие. Затем браузер отправляет событие соответствующему процессу рендеринга, отвечающему за этот HTML-фрейм.
  3. Средство визуализации получает событие и ставит его в очередь, чтобы обработать его, когда оно станет доступным.
  4. Средство визуализации обрабатывает событие, запуская его обработчики. Эти обработчики могут ставить в очередь дополнительную асинхронную работу, такую ​​как setTimeout и выборки, которые являются частью обработки ввода. Но на этом синхронная работа завершена.
  5. На экране отображается кадр, отражающий результат работы обработчиков событий. Обратите внимание, что любые асинхронные задачи, поставленные в очередь обработчиками событий, могут оставаться незавершенными.

Время между шагами (1) и (3), указанными выше, представляет собой задержку события, которую измеряет FID.

Время между шагами (1) и (5) выше — это продолжительность события. Именно это и будет измерять наша новая метрика.

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

Примечание об асинхронных задачах

В идеале нам бы хотелось также зафиксировать асинхронную работу, вызванную этим событием. Но проблема в том, что правильно определить асинхронную работу, вызванную событием, чрезвычайно сложно. Например, разработчик может выбрать запуск анимации в обработчиках событий и использовать setTimeout для запуска такой анимации. Если бы мы захватили все задачи, размещенные в обработчиках, анимация задержала бы время завершения до тех пор, пока выполняется анимация. Мы считаем, что стоит изучить варианты использования эвристики для захвата асинхронной работы, которую следует выполнить как можно скорее. Однако мы хотим быть очень осторожными при этом, потому что мы не хотим наказывать работу, выполнение которой должно занять много времени. Таким образом, в наших первоначальных усилиях шаг 5 будет рассматриваться как конечная точка: он будет учитывать только синхронную работу и количество времени, необходимое для рисования после завершения такой работы. То есть мы не собираемся применять эвристику, чтобы угадать работу, которая будет запущена асинхронно на шаге 4 в нашей первоначальной попытке.

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

Групповые события в взаимодействие

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

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

Типы взаимодействия

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

Взаимодействие Начать конец Настольные события Мобильные события
Клавиатура Клавиша нажала keydown keydown
keypress keypress
Ключ выпущен keyup keyup
Нажмите или перетаскивайте Нажмите начало или запуск перетаскивания pointerdown pointerdown
mousedown touchstart
Нажмите на конец или перетаскивать pointerup pointerup
mouseup touchend
click mousedown
mouseup
click
Прокрутка Н/Д
ДОМ события для каждого типа взаимодействия.

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

Примечание на начало и конец

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

Клавиатура

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

Взаимодействие с клавиатурой с продолжительностью событий с невысоки

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

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

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

Примечание на повторяющихся клавишах

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

Кран

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

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

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

Можем ли мы сужаться дальше, чтобы просто pointerdown и pointerup ?

Одной из первоначальной мысли было бы использовать события pointerdown и pointerup и предположить, что они охватывают все долгосрочные, которые нас интересуют. К сожалению, это не так, как показывает этот случай края . Попробуйте открыть этот сайт на мобильном телефоне или с мобильной эмуляцией и постукивание там, где написано «Нажмите меня». Этот сайт запускает задержку браузера . Можно видеть, что pointerdown , pointerup и touchend быстро отправляются, тогда как mousedown , mouseup и click «Ожидание задержки» перед отправкой. Это означает, что если бы мы только посмотрели на pointerdown и pointerup , то мы пропустили бы продолжительность синтетических событий, что является большим из -за задержки нажатия браузера и должно быть включено. Поэтому мы должны измерить pointerdown , pointerup и click , чтобы покрыть полное взаимодействие.

Тащить

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

Мы также не рассматриваем Drags, реализованные через API Drag and Drop , потому что они работают только на рабочем столе.

Прокрутка

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

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

Так зачем измерять свитки? Проверка прокрутки, которую мы собрали в хроме, показывает, что прокрутка, как правило, очень быстрая. Тем не менее, мы все еще хотим включить первоначальные задержки прокрутки в нашу новую метрику по разным причинам. Во -первых, прокрутка быстрая только потому, что она была оптимизирована так сильно, потому что это так важно. Но есть еще способы, чтобы веб -сайт обходил некоторые выгоды от производительности, которые предлагает браузер. Наиболее распространенным в Chrome является то, что прокрутка прокрутки произойдет в главной нити. Таким образом, наш показатель должен быть в состоянии сказать, когда это происходит, и вызывает плохую производительность прокрутки для пользователей. Во -вторых, прокрутка слишком важна, чтобы игнорировать. Мы беспокоимся о том, что если мы исключим прокрутку, у нас будет большая слепая точка зрения, а производительность прокрутки может со временем снизиться без должным образом веб -разработчиков.

Есть несколько событий, которые отправляются, когда пользовательские прокрутки, такие как touchstart , touchmove и scroll . За исключением события прокрутки, это в значительной степени зависит от устройства, используемого для прокрутки: события прикосновения отправляются при прокрутке при пальце на мобильных устройствах, в то время как колеса колеса происходят при прокрутке с колесом мыши. События прокрутки запускаются после завершения первоначальной прокрутки. И в целом, никакие блокирование событий DOM прокручивают, если только на веб-сайте не используются не пассивные слушатели событий . Поэтому мы думаем о прокрутке как о том, что отключено от событий DOM. То, что мы хотим измерить, - это время, когда пользователь перемещается достаточно, чтобы создать жест прокрутки до первого кадра, который показывает, что прокрутка произошла.

Как определить задержку взаимодействия?

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

Для этих типов взаимодействий мы хотели бы, чтобы задержка включала продолжительность всех событий, связанных с ними. Поскольку продолжительность событий для каждой «вниз» и «вверх» часть взаимодействия может перекрываться, простейшее определение задержки взаимодействия, которое достигает этого, является максимальной продолжительностью любого связанного с ним события. Ссылаясь на диаграмму клавиатуры с более раннего, это будет продолжительность keydown , так как она длиннее, чем keyup :

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

Длительность keydown и keyup также могут перекрываться. Это может произойти, например, когда кадр, представленная для обоих событий, одинаков, как на следующей диаграмме:

Взаимодействие клавиатуры, где нажатие и высвобождение происходит в той же кадре

Есть плюсы и минусы в таком подходе использования максимума, и мы заинтересованы в том, чтобы услышать ваши отзывы :

  • Pro : это согласован с тем, как мы намерены измерить прокрутку в том, что он измеряет только одно значение продолжительности.
  • Pro : он направлен на снижение шума для таких случаев, как взаимодействие с клавиатурой, где keyup обычно ничего не делает и где пользователь может выполнить нажатие клавиши и быстро или медленно выпустить.
  • CON : Это не захватывает полное время ожидания пользователя. Например, он захватит начало или конец сопротивления, но не оба.

Для прокрутки (который просто имеет одно связанное событие), мы хотели бы определить его задержку как время, которое необходимо для браузера, чтобы создать первый кадр в результате прокрутки. То есть задержка - это дельта между timeStamp события первого события DOM (например, touchmove , если использование пальца), которая достаточно велика, чтобы вызвать свиток, и первая краска, которая отражает прокрутку.

Собирать все взаимодействия на страницу

Как только мы определили, какова задержка взаимодействия, нам нужно вычислить совокупное значение для загрузки страницы, которая может иметь много взаимодействий с пользователем. Наличие агрегированного значения позволяет нам:

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

Чтобы выполнить эту агрегацию, нам нужно решить два вопроса:

  1. Какие цифры мы пытаемся агрегировать?
  2. Как мы собираем эти цифры?

Мы исследуем и оцениваем несколько вариантов. Мы приветствуем ваши мысли об этом агрегации.

Одним из вариантов является определение бюджета на задержку взаимодействия, которое может зависеть от типа (прокрутка, клавиатура, нажатие или перетаскивание). Так, например, если бюджет на TAPS составляет 100 мс, а задержка TAP составляет 150 мс, то сумма по бюджету для этого взаимодействия будет 50 мс. Затем мы могли бы вычислить максимальную сумму задержки, которая превышает бюджет для любого взаимодействия с пользователем на странице.

Другой вариант - вычислить среднюю или медианную задержку взаимодействия на протяжении всей жизни страницы. Поэтому, если бы у нас было задержку 80 мс, 90 мс и 100 мс, то средняя задержка для страницы составила бы 90 мс. Мы также могли бы рассмотреть средний или медиана «за бюджет» для учета различных ожиданий в зависимости от типа взаимодействия.

Как это выглядит на API веб -производительности?

Чего не хватает от времени событий?

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

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

Что вы можете попробовать прямо сейчас?

Прямо сейчас все еще возможно вычислить максимальную задержку для TAPS/перетаскивания и для взаимодействия клавиатуры. Следующий фрагмент кода даст эти две метрики.

let maxTapOrDragDuration = 0;
let maxKeyboardDuration = 0;
const observer = new PerformanceObserver(list => {
  list.getEntries().forEach(entry => {
    switch(entry.name) {
      case "keydown":
      case "keyup":
        maxKeyboardDuration = Math.max(maxKeyboardDuration,
            entry.duration);
        break;
      case "pointerdown":
      case "pointerup":
      case "click":
        maxTapOrDragDuration = Math.max(maxTapOrDragDuration,
            entry.duration);
        break;
    }
  });
});
observer.observe({type: "event", durationThreshold: 16, buffered: true});
// We can report maxTapDragDuration and maxKeyboardDuration when sending
// metrics to analytics.

Обратная связь

Дайте нам знать, что вы думаете об этих идеях по электронной почте: web-vitals-feedback@googlegroups.com!