Nous l’avons nommé « projet Quantum », et la première version de cette renaissance en Firefox Quantum est disponible depuis le 13 novembre*.
Mais cela ne signifie pas que notre travail soit achevé. Cela ne veut pas dire qu’aujourd’hui Firefox est aussi rapide et réactif qu’il le deviendra.
Regardons d’un peu plus près comment Firefox est redevenu rapide et comment il va devenir plus rapide encore.
Poser les fondations d’un parallélisme à gros grain
Pour aller plus vite, nous avons besoin de nous appuyer sur la façon dont les composants matériels ont évolué ces 10 dernières années.
Nous ne sommes pas les premiers à le faire. Chrome était plus rapide et réactif que Firefox quand il a été présenté pour la première fois. C’était, entre autres choses, parce que les ingénieurs de Chrome avaient vu qu’un changement au niveau du matériel était en train de se produire et qu’ils ont commencé à mieux l’exploiter.
Un nouveau style de processeurs était en train de se répandre. Ces derniers sont constitués de plusieurs cœurs, ce qui signifie qu’ils peuvent réaliser des tâches en simultané et indépendamment les uns des autres – en parallèle.
Cela peut en revanche être complexe. Le parallélisme peut induire des bogues assez subtils et difficiles à voir ou à corriger. Par exemple, si deux cœurs ont besoin d’ajouter 1 au même nombre en mémoire, il est probable que l’un réécrive par-dessus l’autre si vous ne faites pas particulièrement attention.
Un moyen plutôt direct d’éviter ce genre de problèmes est simplement de s’assurer que les deux choses sur lesquelles vous travaillez ne partagent pas de mémoire afin de répartir le programme en tâches plutôt larges qui n’ont pas besoin de coopération. Voilà ce qu’est le parallélisme à gros grain.
Dans le navigateur, il est plutôt simple de trouver ces gros grains. Chaque onglet a ses propres tâches auxquelles s’employer. Il y a aussi la partie autour de ces pages – l’interface du navigateur – et celle-ci peut être prise en charge séparément.
De cette manière, les pages peuvent travailler à leur propre rythme, simultanément, sans se bloquer entre elles. Si vous avez un script qui dure depuis longtemps dans un onglet en arrière-plan, cela ne bloquera pas celui que vous utilisez actuellement.
C’est l’opportunité qu’ont anticipée les ingénieurs de Chrome. Nous l’avions également vue, mais un chemin plus cahoteux se présentait à nous pour y arriver. En effet, étant donné que nous avions une base de code existante, nous avions besoin de trouver un moyen de séparer celle-ci afin de tirer parti de plusieurs cœurs.
Il nous a fallu un peu de temps, mais nous y sommes arrivés. Avec le projet Electrolysis, nous avons finalement réussi à mettre le multiprocessus à la portée de tous les utilisateurs. Et Quantum a rendu notre usage du parallélisme à gros grain encore meilleur avec quelques autres projets.
Electrolysis
Electrolysis a préparé le terrain pour le projet Quantum. Il a introduit une sorte d’architecture multiprocessus similaire à celle mise en œuvre par Chrome. Le changement était tellement important que nous l’avons intégré progressivement en le faisant tester à de petits groupes d’utilisateurs à partir de 2016 avant d’en faire bénéficier tous les utilisateurs de Firefox à la mi-2017.
Quantum Compositor
Quantum Compositor déplace le compositeur dans un processus dédié. Le point-clé de ce changement est que cela rend Firefox plus stable. Avoir un processus séparé signifie que si le pilote graphique plante, il n’entraînera pas tout le navigateur avec lui. Mais avoir ce processus séparé rend aussi Firefox plus réactif.
Quantum DOM
Même en répartissant les onglets entre les différents cœurs et en ayant un thread [fil d’exécution] dédié à chacun d’entre eux, il reste encore bien des choses à la charge du thread principal. Certaines d’entre elles sont plus importantes que d’autres : répondre un l’utilisation d’une touche l’est par exemple plus que faire passer le ramasse-miettes. Quantum DOM nous donne la possibilité de prioriser ces tâches. Cela rend Firefox plus réactif. La majeure partie de ce travail est déjà là, mais nous prévoyons encore d’amener cela un peu plus loin avec une fonctionnalité nommée « ordonnancement préemptifs ».
Faire une meilleure utilisation du matériel avec le parallélisme à grain fin
Pourtant, lorsque nous nous avons regardé vers l’avenir, nous avons compris que nous devions aller plus loin qu’un parallélisme à gros grain.
Le parallélisme grossier fait meilleur usage du matériel… mais il n’en fait le meilleur usage. Lorsque vous répartissez ces pages web entre différents cœurs, certains d’entre eux se retrouvent sans aucune tâche à effectuer. Ces cœurs vont donc rester inactifs. Pourtant, une nouvelle page qui serait visitée et attribuée à un autre cœur prendrait tout autant de temps à être affichée que si le processeur ne possédait qu’un cœur.
Il serait génial de pouvoir utiliser tous ces cœurs pour traiter la nouvelle page durant son chargement. Ainsi, vous pourriez faire votre travail plus rapidement.
Mais avec le parallélisme à gros grain, on ne peut pas répartir le travail d’un cœur vers les autres cœurs. Il n’y a pas de frontières entre les différents travaux.
Avec un parallélisme fin, on découpe cette tâche en unités plus petites qui peuvent être envoyées aux différents cœurs. Par exemple, sur un site comme Pinterest, vous pouvez séparer les différents éléments épinglés et employer différents cœurs pour son affichage.
Cela n’améliore pas simplement la latence comme avec le parallélisme à gros grain. Cela améliore aussi la vitesse pure. Les chargements de page se font plus vite, car le travail est séparé entre les cœurs. Et plus vous ajoutez de cœurs, plus votre page sera chargée et affichée rapidement.
Nous avons ainsi pu voir ce que nous considérons être le futur, mais le moyen d’y arriver reste à clarifier. Car pour rapidement atteindre ce parallélisme à grain fin, il est généralement nécessaire de partager de la mémoire entre les cœurs. Mais cela donne lieu à ces data races [situations de compétition entre les données] dont je parlais plus tôt.
Nous savions néanmoins que le navigateur devait franchir ce pas, alors nous avons commencé à investir dans la recherche. Nous avons créé un langage dénué de ces data races : Rust. Puis nous avons créé un moteur de rendu, Servo, qui utilisait pleinement les capacités de ce parallélisme à grain fin. Par ce biais, nous avons prouvé que cela pouvait fonctionner et qu’il était donc possible de rencontrer moins de problèmes tout en étant plus rapides.
Quantum CSS (alias Stylo)
Avec Stylo, le calcul des styles CSS est intégralement parallélisé sur tous les cœurs du processeur. Stylo utilise une technique appelée work stealing [vol de travail] pour répartir les tâches entre les différents cœurs, de telle sorte qu’ils restent toujours tous occupés. Vous pouvez ainsi bénéficier d’une augmentation linéaire des performances : le temps de calcul des styles CSS est divisé par le nombre de cœurs dont vous disposez, quel que soit ce nombre.
Quantum Render (mettant en scène WebRender)
Le GPU [processeur graphique] est une autre partie du matériel hautement parallélisée. Il contient des centaines de milliers de cœurs. Néanmoins, il est nécessaire de planifier énormément afin de s’assurer que ces cœurs restent en permanence aussi occupés que possible. C’est ce que fait WebRender.
WebRender arrivera en 2018 et exploitera les atouts des GPU modernes. Nous nous sommes aussi attaqué au problème sous un angle différent par la même occasion. Le projet « Advanced Layers » modifie le système de couches existant de Firefox afin d’être en capacité de faire du rendu par lots. Cela nous donne des gains immédiats en optimisant la manière avec laquelle Firefox exploite déjà le GPU.
???
Nous pensons que d’autres parties du pipeline de rendu peuvent bénéficier de ce parallélisme à grain fin. Dans les prochains mois, nous allons étudier de plus près à quels autres endroits pourraient également être exploitées ces techniques.
S’assurer que nous ne faisons qu’accélérer et que nous ne ralentirons plus jamais
Au-delà des modifications architecturales, dont nous savions qu’elles seraient à effectuer, de nombreux problèmes de performances se sont glissés dans le code sans que nous y prêtions attention.
Nous avons donc créé un autre élément au sein de Quantum pour corriger cela. Nous avons mis en place une équipe dédiée à la performance du navigateur qui avait pour but de trouver ces problèmes et de mobiliser les équipes afin de les résoudre.
Quantum Flow
L’équipe Quantum Flow fut au cœur de cette révolution. Au lieu de se concentrer sur les performances globales d’un sous-système particulier, cette dernière a eu pour objectif de résoudre des cas spécifiques et importants tels que le chargement du flux de votre réseau social. Ils ont travaillé avec plusieurs équipes afin de déterminer pourquoi le flux était moins réactif dans Firefox que dans les autres navigateurs.
Quantum Flow nous a permis d’obtenir un grand nombre de gains de performance significatifs. Ce faisant, nous avons aussi développé des outils et des processus afin de faciliter la recherche et le suivi de ce type de problèmes.
Que va donc devenir Quantum Flow ?
Nous transformons ce processus efficace qui nous a permis d’identifier et de nous concentrer sur un cas particulier à la fois en un élément de fond de notre méthode de travail. Pour ce faire, nous améliorons nos outils pour ne pas avoir à impliquer un groupe d’experts pour trouver les problèmes, mais plutôt pour que les ingénieurs au sein de l’organisation puissent apprendre à le faire eux-mêmes.
Cependant, il y a un problème avec cette approche. Lorsque nous optimisons un cas, il se peut que ce soit au détriment d’un autre. Pour éviter cela, nous assurons maintenant un suivi incluant des améliorations à notre chaîne d’intégration continue chargée d’exécuter les tests de performance, de la télémétrie afin d’avoir connaissance de l’expérience utilisateur et une gestion des régressions au sein de tickets ou bogues. Ainsi, nous nous attendons à ce que Firefox Quantum continue à s’améliorer.
Demain n’est que le commencement
Ce 14 novembre* a été un grand jour pour nous à Mozilla. Nous avons travaillé d’arrache-pied pour rendre Firefox rapide. Mais ce n’est aussi que le début.
Nous allons fournir de nouvelles améliorations de performances tout au long de la prochaine année. Nous sommes impatients de les partager avec vous.
Essayez Firefox Quantum ou la Developer Edition afin d’être sûr d’avoir les dernières mises à jour quand elles sortent.
À propos de Lin Clark
Lin est ingénieure dans l’équipe Mozilla Developer Relations. Elle bricole autour de JavaScript, WebAssembly, Rust et Servo et dessine également des esquisses de code.
(*) L’article a été publié le 13 novembre 2017, soit la veille de la sortie de Firefox Quantum.
Traduction et relecture : Théo, dattaz, Ilphrin, Alpha, Mozinet, Cécile, Porkepix, Goofy et anonymes
Précédent article sur le futur de Firefox : Google, Microsoft et Mozilla ensemble pour parler Cross Browser
Crédit illustrations : Mozilla et Lin Clark.