Découvrez nos réflexions sur la mesure de la réactivité et faites-nous part de vos commentaires.
Au sein de l'équipe Chrome Speed Metrics, nous cherchons à mieux comprendre la vitesse à laquelle les pages Web répondent aux entrées des utilisateurs. Nous aimerions vous faire part de quelques idées pour améliorer les métriques de réactivité et prendre en compte vos commentaires.
Cet article traite de deux sujets principaux:
- Examinez notre métrique de réactivité actuelle, First Input Delay (FID), et expliquez pourquoi nous avons choisi le FID plutôt que certaines des alternatives.
- Présenter des améliorations que nous avons envisagées pour mieux capturer la latence de bout en bout des événements individuels Ces améliorations visent également à capturer une image plus holistique de la réactivité globale d'une page tout au long de sa durée de vie.
Qu'est-ce que le First Input Delay ?
La métrique FID (First Input Delay) mesure le temps nécessaire au navigateur pour commencer à traiter la première interaction utilisateur sur une page. Plus précisément, elle mesure la différence entre le moment où l'utilisateur interagit avec l'appareil et le moment où le navigateur est en mesure de commencer à traiter les gestionnaires d'événements. Le FID n'est mesuré que pour les appuis et les pressions sur les touches, ce qui signifie qu'il ne prend en compte que la toute première occurrence des événements suivants:
click
keydown
mousedown
pointerdown
(seulement s'il est suivi depointerup
)
Le schéma suivant illustre le FID:
Le FID n'inclut pas le temps passé à exécuter ces gestionnaires d'événements, ni les tâches effectuées par le navigateur pour mettre à jour l'écran par la suite. Elle mesure la durée pendant laquelle le thread principal a été occupé avant de pouvoir traiter une entrée. Ce temps de blocage est généralement dû à de longues tâches JavaScript, qui ne peuvent pas être arrêtées à tout moment. La tâche actuelle doit donc être terminée pour que le navigateur puisse commencer à traiter l'entrée.
Pourquoi avons-nous choisi FID ?
Nous pensons qu'il est important de mesurer l'expérience utilisateur réelle afin de nous assurer que les améliorations apportées à cette métrique se traduisent par des avantages réels pour l'utilisateur. Nous avons choisi de mesurer le FID, car il représente la partie de l'expérience utilisateur lorsque l'utilisateur décide d'interagir avec un site qui vient d'être chargé. Le FID capture une partie du temps que l'utilisateur doit attendre pour voir une réponse de son interaction avec un site. En d'autres termes, le FID est une limite inférieure du temps d'attente d'un utilisateur après une interaction.
D'autres métriques telles que le Total Blocking Time (TBT) et le Time To Interactive (TTI) sont basées sur des tâches longues et, comme le FID, mesurent également le temps de blocage du thread principal pendant le chargement. Étant donné que ces métriques peuvent être mesurées à la fois sur le terrain et en laboratoire, de nombreux développeurs nous ont demandé pourquoi nous préférons l'une de ces métriques plutôt que le FID.
et ce pour différentes raisons. La raison la plus importante est sans doute que ces métriques ne mesurent pas directement l'expérience utilisateur. Toutes ces métriques mesurent la durée d'exécution de JavaScript sur la page. Bien que les scripts JavaScript de longue durée causent généralement des problèmes aux sites, ces tâches n'ont pas nécessairement d'incidence sur l'expérience utilisateur si l'utilisateur n'interagit pas avec la page au moment où elles se produisent. Une page peut avoir un excellent score en termes de navigation détaillée et d'analyse détaillée, mais elle peut sembler lente, ou elle peut avoir un score faible alors qu'elle semble rapide pour les utilisateurs. D'après notre expérience, ces mesures indirectes génèrent des métriques très efficaces pour certains sites, mais pas pour la plupart d'entre eux. Pour résumer, le fait que les tâches longues et l'TTI ne soient pas axés sur l'utilisateur en font des candidats plus faibles.
Si les mesures en laboratoire sont sans aucun doute importantes et un outil inestimable pour les diagnostics, ce qui compte vraiment, c'est la façon dont les utilisateurs interagissent avec les sites. Si vous disposez d'une métrique axée sur l'utilisateur qui reflète des conditions réelles de l'utilisateur, vous avez la garantie de capturer quelque chose de pertinent concernant l'expérience. Nous avons décidé de commencer par une petite partie de cette expérience, même si nous savons que cette partie n'est pas représentative de l'expérience complète. C'est pourquoi nous cherchons à capturer une plus grande partie du temps qu'un utilisateur attend que ses entrées soient traitées.
Mesurer le TTI sur des utilisateurs réels sur le terrain est problématique, car il se produit très tard dans le chargement de la page. Une fenêtre silencieuse sur le réseau de 5 secondes est requise avant même que le TTI puisse être calculé. Dans l'atelier, vous pouvez choisir de décharger la page chaque fois que vous disposez de toutes les données dont vous avez besoin, mais ce n'est pas le cas avec la surveillance des utilisateurs réels sur le terrain. Un utilisateur peut choisir de quitter la page ou d'interagir avec elle à tout moment. En particulier, les utilisateurs peuvent choisir de quitter des pages dont le chargement prend beaucoup de temps. Dans ce cas, aucun TTI précis n'est enregistré. Lorsque nous avons mesuré l'TTI pour les utilisateurs réels dans Chrome, nous avons constaté que seulement la moitié des chargements de pages atteignaient l'TTI.
Quelles améliorations envisageons-nous d'améliorer ?
Nous aimerions développer une nouvelle métrique qui étend ce que le FID mesure aujourd'hui, tout en conservant son lien fort avec l'expérience utilisateur.
Nous voulons que la nouvelle métrique:
- Tenir compte de la réactivité de toutes les entrées utilisateur (pas seulement de la première)
- Enregistrez toute la durée de chaque événement (pas seulement le décalage).
- Regroupez les événements qui se produisent dans le cadre de la même interaction utilisateur logique et définissez la latence de cette interaction comme la durée maximale de tous ses événements.
- Créez un score global pour toutes les interactions qui se produisent sur une page, tout au long de son cycle de vie.
Pour réussir, nous devons être en mesure d'affirmer avec un haut niveau de certitude que si un site obtient de mauvais résultats pour cette nouvelle métrique, il ne répond pas rapidement aux interactions des utilisateurs.
Capturer toute la durée de l'événement
La première amélioration évidente consiste à essayer de capturer une latence plus large de bout en bout d'un événement. Comme mentionné ci-dessus, le FID ne capture que la partie retard de l'événement d'entrée. Il ne tient pas compte du temps nécessaire au navigateur pour traiter les gestionnaires d'événements.
Le cycle de vie d'un événement comporte différentes étapes, comme illustré dans le schéma suivant:
Voici les étapes que Chrome suit pour traiter une entrée:
- L'entrée de l'utilisateur est effectuée. L'heure à laquelle cela se produit correspond à l'
timeStamp
de l'événement. - Le navigateur effectue des tests de positionnement pour déterminer à quel frame HTML (frame principal ou iFrame) appartient un événement. Le navigateur envoie ensuite l'événement au processus approprié du moteur de rendu en charge de cette image HTML.
- Le moteur de rendu reçoit l'événement et le met en file d'attente afin de pouvoir le traiter lorsqu'il devient disponible.
- Le moteur de rendu traite l'événement en exécutant ses gestionnaires. Ces gestionnaires peuvent mettre en file d'attente des tâches asynchrones supplémentaires, telles que
setTimeout
et des récupérations, qui font partie du traitement des entrées. Mais à ce stade, la tâche synchrone est terminée. - Un frame s'affiche à l'écran afin de refléter le résultat de l'exécution des gestionnaires d'événements. Notez que toutes les tâches asynchrones mises en file d'attente par les gestionnaires d'événements peuvent toujours être inachevées.
Le temps entre les étapes (1) et (3) ci-dessus correspond au retard d'un événement, que le FID mesure.
Le temps écoulé entre les étapes (1) et (5) ci-dessus correspond à la durée d'un événement. C'est ce que notre nouvelle métrique mesurera.
La durée de l'événement inclut le délai, mais elle inclut également le travail qui se produit dans les gestionnaires d'événements et le travail que le navigateur doit effectuer pour peindre le frame suivant après l'exécution de ces gestionnaires. La durée d'un événement est actuellement disponible dans l'API Event Timing via l'attribut duration de l'entrée.
Idéalement, nous aimerions également capturer le travail asynchrone déclenché par l'événement. Mais le problème est qu'il est extrêmement difficile de définir la tâche asynchrone déclenchée par l'événement. Par exemple, un développeur peut choisir de lancer une animation sur des gestionnaires d'événements et d'utiliser un setTimeout
pour la lancer. Si nous avions capturé toutes les tâches publiées sur les gestionnaires, l'animation retarderait son exécution aussi longtemps qu'elle s'exécute. Nous pensons qu'il est utile d'étudier les différentes possibilités d'utilisation de la méthode heuristique pour capturer les tâches asynchrones et devant être effectuées dès que possible. Cependant, nous devons faire très attention lorsque nous le faisons, car nous ne voulons pas pénaliser un travail qui devrait prendre beaucoup de temps. Ainsi, notre effort initial considérera l'étape 5 comme le point final: elle ne prendra en compte que le travail synchrone et le temps nécessaire pour peindre une fois ce travail terminé. En d'autres termes, nous n'allons pas appliquer des méthodes heuristiques pour deviner le travail qui serait lancé de manière asynchrone à l'étape 4 lors de nos efforts initiaux.
Notez que, dans de nombreux cas, les tâches doivent être exécutées de manière synchrone. Cela peut être inévitable, car les événements sont parfois envoyés l'un après l'autre et les gestionnaires d'événements doivent être exécutés dans l'ordre. Cela dit, nous passerons toujours à côté des tâches importantes, comme les événements qui déclenchent l'extraction ou qui dépendent d'un travail important à effectuer lors du prochain rappel requestAnimationFrame
, par exemple.
Regrouper des événements en interactions
Étendre la mesure des métriques de delay à duration est une bonne première étape, mais cela laisse toujours un lacune critique dans la métrique: elle se concentre sur des événements individuels et non sur l'expérience utilisateur liée à l'interaction avec la page.
De nombreux événements différents peuvent se déclencher à la suite d'une seule interaction utilisateur, et le fait de mesurer séparément chacun d'eux ne permet pas d'obtenir une image claire de l'expérience utilisateur. Nous voulons nous assurer que notre métrique capture la durée totale pendant laquelle un utilisateur doit attendre une réponse lorsqu'il appuie, appuie sur des touches, fait défiler et fait glisser l'élément avec autant de précision que possible. Nous introduisons donc le concept d'interactions pour mesurer la latence de chacune d'elles.
Types d'interaction
Le tableau suivant répertorie les quatre interactions que nous souhaitons définir, ainsi que les événements DOM auxquels elles sont associées. Notez qu'il ne s'agit pas tout à fait de la même valeur que l'ensemble des événements déclenchés lorsqu'une telle interaction de l'utilisateur se produit. Par exemple, lorsqu'un utilisateur fait défiler l'écran, un événement de défilement est envoyé, mais il se produit après la mise à jour de l'écran pour refléter le défilement. Nous ne le considérons donc pas comme une partie de la latence de l'interaction.
Interaction | Début / Fin | Événements sur ordinateur | Événements sur mobile |
---|---|---|---|
Clavier | Touche enclenché | keydown |
keydown |
keypress |
keypress |
||
Clé libérée | keyup |
keyup |
|
Appuyer ou faire glisser | Appuyez sur "Démarrer" ou faites glisser votre doigt sur "Début". | pointerdown |
pointerdown |
mousedown |
touchstart |
||
Appuyez vers le haut ou faites glisser la fin. | pointerup |
pointerup |
|
mouseup |
touchend |
||
click |
mousedown |
||
mouseup |
|||
click |
|||
Faire défiler | N/A |
Les trois premières interactions répertoriées ci-dessus (clavier, appui et déplacement) sont actuellement couvertes par le FID. Pour notre nouvelle métrique de réactivité, nous souhaitons également inclure le défilement, car ce type de défilement est extrêmement courant sur le Web et constitue un aspect essentiel de la réactivité d'une page pour les utilisateurs.
Notez que chacune de ces interactions se déroule en deux parties: lorsque l'utilisateur appuie sur la souris, le doigt ou la touche, et lorsqu'il le soulève. Nous devons nous assurer que notre métrique ne comptabilise pas le temps que l'utilisateur passe à maintenir le doigt entre ces deux actions dans le cadre de la latence de la page.
Clavier
Une interaction avec le clavier se compose de deux parties: lorsque l'utilisateur appuie sur la touche et lorsqu'il la relâche.
Trois événements sont associés à cette interaction utilisateur: keydown
, keyup
et keypress
.
Le schéma suivant illustre les délais et les durées keydown
et keyup
pour une interaction avec le clavier:
Dans le schéma ci-dessus, les durées sont disjointes, car le frame des mises à jour de keydown
est présenté avant l'événement keyup
, mais cela ne doit pas nécessairement être le cas. En outre, notez qu'un frame peut être présenté au milieu d'une tâche du processus du moteur de rendu, car les dernières étapes requises pour produire le frame sont effectuées en dehors du processus du moteur de rendu.
keydown
et keypress
se produisent lorsque l'utilisateur appuie sur la touche, tandis que keyup
se produit lorsqu'il libère la touche. En général, le contenu principal est mis à jour lorsque l'utilisateur appuie sur la touche: du texte apparaît à l'écran ou l'effet de modificateur est appliqué. Cela dit, nous voulons capturer les cas les plus rares où keyup
présenterait également des mises à jour intéressantes de l'interface utilisateur. Nous voulons donc examiner le temps total nécessaire.
Afin de capturer la durée totale d'une interaction avec le clavier, nous pouvons calculer la durée maximale des événements keydown
et keyup
.
Il existe un cas particulier qui mérite d'être mentionné: il peut arriver que l'utilisateur appuie sur une touche et met un certain temps à la relâcher. Dans ce cas, la séquence d'événements déclenchés peut varier. Dans ce cas, nous considérons qu'il y a une interaction par keydown
, qui peut ou non avoir un keyup
correspondant.
Appuyer
Une autre interaction importante de l'utilisateur se produit lorsqu'il appuie ou clique sur un site Web. Comme pour keypress
, certains événements sont déclenchés lorsque l'utilisateur appuie sur le bouton de la souris et d'autres lorsqu'ils le relâchent, comme illustré dans le schéma ci-dessus. Notez que les événements associés à un appui sont légèrement différents sur ordinateur et sur mobile.
Pour un appui ou un clic, la version est généralement celle qui déclenche la majorité des réactions, mais, comme pour les interactions au clavier, nous voulons capturer l'intégralité de l'interaction. Dans ce cas, il est plus important de le faire, car des mises à jour de l'interface utilisateur lorsque l'utilisateur appuie dessus n'est pas si rare.
Nous aimerions inclure les durées des événements pour tous ces événements, mais comme beaucoup d'entre eux se chevauchent complètement, nous ne devons mesurer que pointerdown
, pointerup
et click
pour couvrir l'ensemble de l'interaction.
pointerdown
et pointerup
?Nous vous conseillons d'abord d'utiliser les événements pointerdown
et pointerup
et de supposer qu'ils couvrent toutes les durées qui nous intéressent. Ce n'est malheureusement pas le cas, comme le montre ce cas limite. Essayez d'ouvrir ce site sur un appareil mobile ou avec une émulation mobile, puis d'appuyer là où il est indiqué "Cliquez ici". Ce site déclenche le délai d'appui dans le navigateur. Vous pouvez constater que les éléments pointerdown
, pointerup
et touchend
sont envoyés rapidement, tandis que mousedown
, mouseup
et click
attendent le délai avant d'être expédiés. Cela signifie que si nous n'examinions que pointerdown
et pointerup
, nous manquerions la durée des événements synthétiques, qui est importante en raison du délai d'appui du navigateur et doit être incluse. Nous devons donc mesurer pointerdown
, pointerup
et click
pour couvrir toute l'interaction.
Traînée
Nous avons également décidé d'inclure le déplacement, car il est associé à des événements similaires et qu'il entraîne généralement des mises à jour importantes de l'interface utilisateur des sites. Toutefois, pour notre métrique, nous ne voulons prendre en compte que le début et la fin du déplacement (première et dernière partie). Cela permet de faciliter le raisonnement et de rendre les latences comparables aux autres interactions prises en compte. Ceci est conforme à notre décision d'exclure les événements continus comme mouseover
.
De plus, nous ne prenons pas en compte les glisser-déposer via l'API de glisser-déposer, car ils ne fonctionnent que sur ordinateur.
Utilisez le défilement
Le défilement est l'une des formes les plus courantes d'interaction avec un site. Pour notre nouvelle métrique, nous aimerions mesurer la latence de l'interaction initiale de défilement de l'utilisateur. Nous sommes particulièrement attentifs à la première réaction du navigateur face au fait que l'utilisateur demande un défilement. Nous ne couvrirons pas l'ensemble de l'expérience de défilement. Autrement dit, le défilement produit de nombreux frames, et nous nous concentrerons sur l'image initiale produite en réaction au défilement.
Pourquoi seulement le premier ? D'une part, les images suivantes peuvent être capturées par une proposition de fluidité distincte. Autrement dit, une fois que l'utilisateur a vu le premier résultat du défilement, le reste doit être mesuré en termes de fluidité de l'expérience de défilement. Par conséquent, nous pensons que la fluidité de l'effort pourrait mieux capturer cela. Ainsi, comme pour FID, nous choisissons de nous en tenir à des expériences utilisateur distinctes, c'est-à-dire des expériences utilisateur associées à des moments précis et pour lesquels nous pouvons facilement calculer leur latence. Le défilement dans son ensemble est une expérience continue. Nous n'avons donc pas l'intention de tout mesurer dans cette métrique.
Alors pourquoi mesurer les défilements ? Les performances de défilement que nous avons recueillies dans Chrome montrent que le défilement est généralement très rapide. Cela dit, nous souhaitons toujours inclure les latences de défilement initiales dans notre nouvelle métrique pour diverses raisons. Tout d'abord, le défilement n'est rapide que parce qu'il a été tellement optimisé, et qu'il est très important. Toutefois, un site Web peut tout de même contourner certains des gains de performances offerts par le navigateur. La règle la plus courante dans Chrome consiste à forcer le défilement sur le thread principal. Notre métrique doit donc pouvoir indiquer quand cela se produit et nuire aux performances de défilement pour les utilisateurs. Deuxièmement, le défilement est tout simplement trop important pour être ignoré. Nous craignons que si nous excluons le défilement, nous ayons un grand angle d'affichage et que les performances de défilement puissent diminuer au fil du temps sans que les développeurs Web ne s'en aperçoivent correctement.
Plusieurs événements, tels que touchstart
, touchmove
et scroll
, sont déclenchés lorsqu'un utilisateur fait défiler l'écran. À l'exception des événements de défilement, cela dépend en grande partie de l'appareil utilisé pour le défilement: les événements tactiles sont envoyés lorsque l'utilisateur fait défiler l'écran avec le doigt sur les appareils mobiles, tandis que les événements liés à la molette se produisent lorsqu'un utilisateur défile avec la molette de la souris. Les événements de défilement sont déclenchés une fois le défilement initial terminé. Et en général, aucun événement DOM ne bloque le défilement, sauf si le site Web utilise des écouteurs d'événements non passifs. Nous considérons le défilement comme étant
totalement découplé des événements DOM. Ce que nous voulons mesurer, c'est le temps écoulé entre le moment où l'utilisateur se déplace suffisamment pour produire un geste de défilement et le premier frame qui indique que le défilement s'est produit.
Comment définir la latence d'une interaction ?
Comme indiqué ci-dessus, les interactions comportant une composante "bas" et "haut" doivent être considérées séparément afin d'éviter d'attribuer le temps que l'utilisateur a passé à maintenir le doigt appuyé.
Pour ces types d'interactions, la latence doit impliquer la durée de tous les événements qui leur sont associés. Étant donné que les durées des événements pour chaque partie "down" et "up" de l'interaction peuvent se chevaucher, la définition la plus simple de la latence d'interaction qui permet d'atteindre cet objectif est la durée maximale de tout événement qui lui est associé. Pour en revenir au diagramme de clavier précédent, il s'agirait de la durée keydown
, car elle est plus longue que la keyup
:
Les durées keydown
et keyup
peuvent également se chevaucher. Cela peut se produire, par exemple, lorsque la trame présentée pour les deux événements est la même, comme dans le schéma suivant:
Cette approche présente des avantages et des inconvénients, et nous aimerions prendre en compte vos commentaires:
- Avantage: il correspond à la façon dont nous prévoyons de mesurer le défilement, dans la mesure où il ne mesure qu'une seule valeur de durée.
- Avantage: il vise à réduire le bruit pour les cas tels que les interactions au clavier, où
keyup
n'a généralement aucune action et où l'utilisateur peut appuyer sur une touche et la relâcher rapidement ou lentement. - Inconvénient: cette méthode ne reflète pas le temps d'attente total de l'utilisateur. Par exemple, elle capturera le début ou la fin d'un déplacement, mais pas les deux.
Pour le défilement (qui n'a qu'un seul événement associé), nous souhaitons définir sa latence comme le temps nécessaire au navigateur pour produire le premier frame à la suite du défilement. En d'autres termes, la latence correspond au delta entre l'événement timeStamp
du premier événement DOM (comme touchmove
, si vous utilisez un doigt) suffisamment grand pour déclencher un défilement et la première peinture qui reflète le défilement.
Agréger toutes les interactions par page
Une fois que nous avons défini la latence d'une interaction, nous devons calculer une valeur globale pour le chargement d'une page, qui peut générer de nombreuses interactions utilisateur. Avoir une valeur agrégée nous permet de:
- Créez des corrélations avec les métriques métier.
- Évaluez les corrélations avec d'autres métriques de performances. Idéalement, notre nouvelle métrique sera suffisamment indépendante pour ajouter de la valeur aux métriques existantes.
- Exposez facilement les valeurs dans les outils d'une manière facile à assimiler.
Pour effectuer cette agrégation, nous devons répondre à deux questions:
- Quels nombres essayons-nous d'agréger ?
- Comment agréger ces chiffres ?
Nous étudions et évaluons plusieurs options. N'hésitez pas à nous faire part de vos commentaires sur cette agrégation.
Une option consiste à définir un budget pour la latence d'une interaction, qui peut dépendre du type (défilement, clavier, appui ou déplacement). Par exemple, si le budget pour les transactions est de 100 ms et que la latence d'une transaction est de 150 ms, le dépassement du budget pour cette interaction est de 50 ms. Nous pouvons alors calculer la latence maximale qui dépasse le budget pour toute interaction utilisateur sur la page.
Une autre option consiste à calculer la latence moyenne ou médiane des interactions tout au long de la vie de la page. Ainsi, avec des latences de 80, 90 et 100 ms, la latence moyenne de la page serait de 90 ms. Nous pourrions également considérer le "sur le budget" moyen ou médian pour tenir compte des attentes différentes en fonction du type d'interaction.
Comment cela se présente-t-il dans les API Web Performance ?
Qu'est-ce qui manque dans la durée de l'événement ?
Malheureusement, l'API Event Timing ne permet pas de capturer toutes les idées présentées dans cet article. En particulier, il n'existe aucun moyen simple de connaître les événements associés à une interaction utilisateur donnée avec l'API. Pour ce faire, nous avons proposé l'ajout d'un interactionID
à l'API.
Un autre inconvénient de l'API Event Timing est qu'il n'existe aucun moyen de mesurer l'interaction de défilement. Nous travaillons donc à activer ces mesures (via Event Timing ou une API distincte).
Que pouvez-vous essayer maintenant ?
Pour le moment, il est toujours possible de calculer la latence maximale pour les gestes d'appui et de déplacement et les interactions avec le clavier. L'extrait de code suivant génère ces deux métriques.
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.
Commentaires
N'hésitez pas à nous envoyer un e-mail à l'adresse web-vitals-feedback@googlegroups.com et donnez-nous votre avis sur ces idées.