Le fonctionnement d’un navigateur | Soirée performance web

Bon, ça vaut c’que ça vaut, mais voici mes notes de la soirée webperf de mardi dernier.
Comme pour la dernière fois (Atelier sur la performance web du 21 avril 2011 – Compte-rendu), j’ai noté ce que j’ai pu et ce que j’ai compris.

Un navigateur, comment ça marche ?

> comprendre le navigateur pour aider à faire des choix.
Anthony Ricaud

Introduction

Cette présentation n’a, initialement, pas été faite dans le contexte de la performance web. Elle permet de comprendre ce qu’un navigateur fait lors d’une requête (et cela inclue les temps d’attente et de traitement.)

D’un point de vue optimisation de la performance, les éléments présentés ci-dessous sont souvent minimes.

Voir les liens qui ont permis à Anthony de préparer sa présentation : Blogmarks > Marks de Rik lié au tag « navigateur-marche ».

Le navigateur a énormément de choses à traiter (parser les URL, rendu des polices, s’adapter aux OS, téléchargement, etc.)
Ici, on va voir ce qu’il se passe depuis la requête (clic sur un lien ou barre d’adresse) jusqu’au chargement de la page.

anthony

La requête et la réponse

La requête est envoyée. Nous sommes ici dans le cas où tout se passe bien. Le navigateur lit alors les premières lignes du html pour choisir le mode qu’il va appliquer pour interpréter la page.
Il y a trois modes possibles : xml, quirks et standard.

Avec « Content-Type: application/xhtml+xml » > Mode XML

Il est très peu utilisé parce que IE ne le supportait pas jusqu’à la version 9 et parce qu’en cas d’erreur : ça se voit
Pas de pb de performance par contre.
=> Tous les navigateurs sauf IE 7 et 8

Avec « Content-Type: text/html » > Mode Quirks

Modifie le box model (celui du W3C ou celui d’IE)
=> Tous les navigateurs

Avec un doctype > Mode Standard

Considère le doctype comme un indice, au moment où ça a été créé, de la qualité du code.
=> Tous les navigateurs

Les navigateurs se fichent des versions de spécifications (HTML5, HTML4, XHTML1.0, CSS3, etc.)

Conseil aux intégrateurs : d’un point de vue pragmatique, il vaut mieux se référer à ce qui est implémenté et fonctionne plutôt qu’aux specifications qui ne sont pas toujours à jour.

Le DOM

= la compréhension qu’a le navigateur du HTML qu’il stocke en mémoire
C’est le DOM qui est manipulé par JS.
Il est composé de nœuds éléments et de nœuds texte.

NB :
Même si espaces et retours à la ligne créent des nœuds texte vides, il n’est pas préconisé de minifier le HTML : le gain serait négligeable alors que parallèlement, il y aurait des problèmes de rendu à gérer.

Le HTML sera identique dans tous les navigateurs à partir de IE9/10. C’est-à-dire, par exemple que l’erreur <p><strong></p></strong> sera interprétée de la même manière par tous les navigateurs.

Les sous-ressources

Pendant que le navigateur récupère le HTML, il va chercher les sous-ressources (images, les CSS, JS).

Les images

C’est non-bloquant, le téléchargement continue.
Le décodeur (le machin qui traite les images) n’a pas non plus d’impact sur le temps de traitement car il compose l’image de son côté et l’envoie quand elle est prête.

Le CSS

C’est non-bloquant, le téléchargement continue.

CSS Buckets

Le navigateur ne prend que les sélecteurs et les place dans des « seaux » (hashtable) :

  • id : #sidebar ; div#sidebar pour une raison de spécificité
  • class : .item
  • tagname : div
  • autres : :visited

cssbuckets

Dès qu’il y a un combinateur de sélecteurs( espace , « ~ », « > » et « + »), c’est celui qui est le + à droite qui l’emporte

Les sélecteurs dans Autres vont ralentir la performance.

CSS maching

Les navigateurs prennent tous les nœuds et vont chercher les règles CSS qui leurs correspondent.

div#sidebar et #sidebar sont dans le même seau mais div#sidebar oblige à une vérification de plus.
Dragonfly sort un profiler de CSS qui va permettre de voir les performances de chaque sélecteur (beta). En effet, sur la performance de sélecteur, il y a beaucoup de  cas particulier. (un outil du même type est en préparation chez Webkit)

  • div p : on ira pas chercher « div »
  • ul p : il faudra vérifier tous les parents avant de passer à la suite
  • ul > p : il n’y a qu’un parent à remonter
  • body > div p : il a dû monter et descendre beaucoup de fois pour établir la règle

Là encore, à moins d’avoir un très grand DOM ET un très grand nombre de sélecteurs, tout ça est négligeable en matière d’optimisation de la performance. S’il n’y avait que deux choses à avoir en tête :

  • Plus un sélecteur est court, plus il est rapide à analyser.
  • Essayer d’avoir le moins possible de sélecteur dans « Autres »

(webkit stocke + d’informations sur le DOM pour pouvoir descendre et remonter dans les noeuds plus vite ensuite)

Render Tree

Les images et le CSS ayant été traités, le « render tree » peut être fabriqué.

Reflow ou layout (selon les navigateurs)

A moins d’un timeout ou d’un JS qui demande une position, le reflow n’est lancé qu’une fois que toutes les CSS ont été chargées.

Chaque bloc est placé dans la page selon sa position et sa taille.

reflow

> Voir la vidéo sur Wikipédia Japon qui montre le reflow
On voit dans la vidéo qu’il commence par le centre, fait le côté et, à la fin …recommence : car il se rend compte en bas de colonne de gauche qu’il n’a pas assez de place en hauteur et qu’il doit donc ajouter un ascenseur à droite. Il recalcule alors les largeurs en fonction.

NB : Sur IE, la scrollbar est mise d’office.

A ce propos, Vincent Voyer
propose une astuce : « Forcer la barre de défilement et empêcher un reflow au chargement : body{overflow-y: scroll;} »

NB : Chrome et Safari ont des outils géniaux pour se faire une idée également de ce qui se passe pour l’affichage de la page. Voir aussi Firefox Affiliates.

Le reflow est donc une étape relativement longue (compte-tenu de notre échelle). On peut donc garder en tête de veiller à ne pas générer de reflow inutiles.

Les 2 cas fréquents qui déclenchent le reflow alors que cela pourrait être facilement évité :

  • images dans le code HTML sans width / height
  • l’insertion des Flash avec des librairies JS comme swfobject
Painting

= la vue de ce qui est affiché à l’écran

Avant, c’était le processeur qui dessinait tout. De ++ c’est le GPU (Processeur Graphique) (+ puissant pour ces tâches (dont les transformations pour certains navigateurs)

Le JS

Rappel : c’est bloquant (= le parseur s’arrête et télécharge, interprète et exécute le JS avant de continuer)
Depuis deux, trois ans, un parseur secondaire va chercher en parallèle les URL (pour gagner un peu de temps) mais pas plus

Il  y a des opérations JS hyper rapide. par contre, les éléments entres JS et DOM prennent forcément du temps.
Le DOM c’est lent.
Si on demande des dimensions, on déclenche le reflow : faire toutes les demandes de lecture au début et ensuite seulement toutes les écritures.

EX : si on change couleur ou opacité, par exemple, pas de reflow déclenché

Display none libère de la mémoire mais est plus long à remettre en place.
Visibilty hidden : ne libère pas de mémoire mais est ré-affiché plus vite.

Les soirées webperfParis se réorganisent …Lorgnez du côté de https://sites.google.com/a/survol.fr/webperf-user-group/ pour être tenu au courant.
Photo : Prélude

8 réponses sur “Le fonctionnement d’un navigateur | Soirée performance web”

  1. Je pense que tu as une petite coquille au niveau de ton sélecteur descendant.
    À priori « ul > p » devrait toujours échouer puisque les liste « ul » et « ol » sont censées contenir des « li » uniquement. 😉

    1. Je ne te comprends pas. Un <ul> et un <ol> peuvent se retrouver à contenir des <p> (si ceux-ci sont bien dans un <li>) et le sélecteur « > » n’implique pas qu’il s’agisse du premier enfant.
      Qu’est-ce que je ne comprends pas dans ta remarque ?

      1. En fait, le sélecteur d’enfant se distingue en ça du sélecteur descendant qu’il ne permet de cibler que les enfants directs de l’élément (ou les descendants de premier niveau, si tu préfères).

        En d’autre termes « ul > p » ne peut pas être vérifié car un item de liste viendra forcément s’intercaler entre les deux.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *