ABC de la performance Web

Ce billet date de plusieurs années, ses informations peuvent être devenues obsolètes.

Ce billet fait partie d'une série en 10 volets : #1, #2, #3, #4, #5, #6, #7, #8, #9 et #10.

Notes de lecture de Primer on Web Performance.

Hypertext, pages Web, et applications Web

L'évolution du web a engendré 3 types d'expériences différentes :

  • document hypertexte
  • page Web (ajout de données hypermédia à l'hypertexte)
  • application Web (DHTML et AJAX)

La mesure clé de la performance est passée du temps de chargement d'un seul document hypertexte (session HTTP/0.9) au temps de chargement d'une page Web : le temps écoulé jusqu'à ce que l'indicateur d'activité s'arrête de tourner dans le navigateur.

La migration vers un système d'applications Web a transformé la simple page Web en un système de dépendances complexes de JavaScript/CSS/HTML et rend l'indicateur de temps de chargement insuffisant : les mesures de la performance dépendent de plus en plus de critères spécifiques à l'application (combien de temps avant la première interaction de l'utilisateur etc.). Il faut définir au cas par cas un jeu de métriques clés de performance.

DOM, CSSOM, et JavaScript

HTML et CSS sont bloquants pour le rendu car ils sont à l'origine du DOM et du CSSOM permettant de dessiner une page.

JavaScript peut être bloquant en plein milieu de la construction du DOM, par exemple via un document.write, en demandant un style CSS calculé ou en ajoutant des attributs style aux éléments du DOM.

Par conséquent, les constructions du DOM et du CSSOM sont fréquemment entrelacées : la construction du DOM ne peut se faire tant que le JavaScript n'est pas exécuté, et l'exécution du JavaScript ne peut pas se faire tant que le CSSOM n'est pas disponible.

Le temps de rendu dépend de ces interdépendances de plus en plus complexes de JavaScript/CSS/HTML et la bonne pratique “les styles en haut, les scripts en bas” en découle.

Il est possible d'aller très loin dans l'amélioration des performances de chargement de CSS.

Anatomie d'une application Web moderne

Contrairement aux applications desktop, les applications Web n'ont pas besoin d'être installées : tapez l'URL, appuyez sur entrée, et c'est parti.

Si les applications desktop ne nécessitent qu'une seule installation, les applications Web exécutent leur “processus d'installation” à chaque visite : téléchargements des ressources, construction du DOM et du CSSOM, exécution de JavaScript.

Des centaines de ressources à charger, des mégaoctets de données, des douzaines d'hôtes différents à contacter, tout cela doit se faire en centaines de millisecondes pour obtenir la meilleure expérience Web possible.

Vitesse, performance et perception humaine

Le papier de référence concernant les temps de réponses est l'article de Robert Miller intitulé “Response Time in Man-Computer Conversational Transactions” publié en 1968.

Il y a 3 seuils important récapitulés plus tard par Jakob Nielsen.

Ilya Grigorik élabore une table un peu plus poussée dans son livre :

Délai Perception de l'utilisateur
0–100 ms Instantané
100–300 ms Petit retard perceptible
300–1000 ms La machine travaille
1000+ ms Changement de contexte mental probable
10.000+ ms La tâche est abandonnée

De ce tableau découle la règle (non officielle et relative) d'afficher les pages (ou a minima un premier retour visuel) en moins de 250 millisecondes.

Voir aussi Best Practices for Response Times and Latency.

Analyse de la cascade des ressources

Le graphique en cascade du téléchargement des ressources (disponible dans les outils de développement des navigateurs) est l'outil de référence pour un diagnostic des performances.

Il permet de vérifier que la bande passante n'est pas (toujours) le facteur limitant. Le goulot d'étranglement est (souvent) la latence réseau. Et surtout en HTTP/1.x où chaque requête HTTP est composée d'étapes distinctes : résolution DNS, TCP handshake, négociation TLS, envoi de la requête HTTP et téléchargement du contenu.

Quand on parle de performance front-end, on parle souvent de l'analyse et de l'optimisation de cette cascade.

C'est certainement mal nommé, car ça laisse penser que tous les goulots d'étranglement en matière de performance sont côté client. Les temps de réponse du serveur et la latence du réseau (performance back-end) sont tout aussi critiques.

Les piliers de la performance : calcul, rendu et réseau

Il y a 3 étapes dans l'exécution d'un programme Web :

  • la récupération des ressources
  • la mise en page et le rendu de la page
  • l'exécution du code JavaScript

Le rendu et l'exécution du JavaScript sont entrelacés et suivent un modèle d'exécution à thread unique ; il n'est pas possible d'effectuer des modifications simultanées du DOM.

Leurs optimisations et la livraison rapide et efficace des ressources réseau sont d'une importance capitale.

Davantage de bande passante ne sert à (presque) rien

S'il s'agit du streaming d'une video HD, le facteur limitant est la bande passante.

Mais lorsqu'il s'agit de naviguer sur le Web, il s'agit d'aller chercher des centaines de ressources relativement petites sur des dizaines d'hôtes différents, le facteur limitant est la latence aller-retour.

La latence comme goulot d'étranglement

Le gros des flux de données HTTP est constitué de petits transferts de données en rafale alors que TCP est optimisé pour les connexions de longue durée et les transferts de données en masse. Dans la plupart des cas, les temps d'aller-retour réseau sont le facteur limitant de TCP. Par conséquent, la latence est également le goulot d'étranglement des performances du protocole HTTP et de la plupart des applications Web.

Techniques de mesure

On peut collecter des données sur la performance via deux moyens :

  • par des tests automatiques (l'auteur parle de synthetic testing)
  • par l'observation des utilisateurs en cas d'usage réel (l'auteur parle de real-user measurement (RUM))

Les tests automatiques peuvent être par exemple des tests de performances d'un build local, des tests de charge d'une infrastructure de staging, un ensemble de serveurs de surveillance géo-répartis qui exécutent périodiquement un ensemble d'actions et enregistrent les résultats, etc. Chaque élément de l'infrastructure (débit du serveur d'application, performance de la base de données, temps de réponse du DNS, etc.) peut être testé individuellement pour détecter des régressions.

Les mesures recueillies ne sont toutefois pas représentatives du monde réel : difficile de reproduire un chemin de navigation réel, les caches (du navigateur ou des proxies) peuvent impacter les performances, vaste parc installé de navigateurs (avec des versions anciennes et nouvelles) etc.

Il est possible de compléter l'analyse par l'observation et la collecte des données de performance de notre application telle qu'expérimentée par les utilisateurs réels.

Outils permettant ces mesures réelles :

La capture de ces données permet d'observer les performances réelles de nos applications.

Optimisation des navigateurs

Les optimisations que les fabricants de navigateurs peuvent apporter se divisent en 2 catégories :

Pour assister le navigateur, il faut faire attention à la structure des pages :

  • les ressources essentielles au rendu doivent pouvoir être découvertes le plus tôt possible dans le document
  • les fichiers CSS doivent être livrés le plus tôt possible pour ne pas bloquer le rendu et l'exécution de JavaScript
  • le chargement du JavaScript non critique doit être différé pour ne pas bloquer la construction du DOM et du CSSOM

Avant TLS Après HTTP/1.1

Tag Kemar Joint