Capture_du_2016-10-28_23-43-53.png
 

Quantum comporte quatre projets distincts…

Le projet Quantum CSS remplacera le moteur CSS de Gecko par celui de Servo. Le moteur de Servo permet un parallélisme massif, pas celui de Gecko.

Le projet Quantum DOM va rendre Gecko plus adaptatif, particulièrement dans le cas où de très nombreux onglets sont ouverts en arrière-plan. Lorsque le Quantum DOM sera achevé, le code JS de différents onglets (et peut-être de différents iframes) tournera de façon coordonnée et planifiée entre différents threads de sorte que le code de plusieurs onglets en arrière-plan ne s’interrompe jamais.

Le Compositor de Quantum remplacera celui de Gecko par le sien propre. Comme l’instabilité des drivers graphiques est une cause principale des plantages de Firefox, nous espérons que transférer le code qui interagit avec le GPU rendra Firefox beaucoup plus stable.

Enfin, Quantum Rendering remplacera le sous-système de rendu graphique de Gecko par celui de Servo, appelé WebRender. Servo utilise le GPU de façon plus efficace que Gecko, il le pilote comme le ferait un jeu plutôt que comme un navigateur a l’habitude de le faire.

Ces projets en sont à des stades d’avancement divers. Le projet Quantum Compositor est déjà bien avancé alors que Quantum Rendering n’en est qu’à ses débuts. Il existe encore pas mal d’incertitudes sur ces projets. Toutefois je veux dire quelques mots à propos de Quantum DOM, le projet sur lequel je travaille.

Quantum DOM

Quantum DOM est essentiellement conçu pour que le contenu web fonctionne mieux et pour que les « accrocs » soient plus rares (il s’agit des pénibles petits sursauts et hoquets qui dégradent l’expérience de navigation). Un grand nombre de ces accrocs viennent des onglets en arrière-plan et des publicités. Voyez leur évaluation sur le bug 1296486. Un moyen pratique de réduire ces nuisances consiste à faire tourner chaque onglet et autre cadre de rendu de l’onglet dans son propre processus. Dans la mesure où les systèmes d’exploitation organisent les processus de manière préemptive, les cadres en arrière-plan peuvent toujours êtres interrompus pour favoriser le travail d’avant-plan.

Malheureusement, si l’on augmente le nombre de processus de contenu on augmente aussi la consommation de mémoire. D’après les expériences préliminaires que nous avons menées, il semble peu probable que nous puissions augmenter le nombre de processus de contenu au-delà de 8 dans un futur proche ; tout processus supplémentaire augmenterait de façon inacceptable la consommation de mémoire. Il vaut certainement mieux avoir 8 processus au lieu d’un, mais de nombreux utilisateurs ont plus de 8 onglets ouverts simultanément. Les développeurs de Mozilla travaillent à réduire la consommation excessive de mémoire des processus de contenu, mais nous ne pourrons jamais réduire cet excès à zéro. Nous explorons donc d’autres pistes, comme l’ordonnancement coopératif pour les onglets et le gel des onglets.

L’ordonnancement coopératif

Quantum DOM est une approche alternative qui vise à réduire les accrocs de performance sans augmenter la quantité de mémoire utilisée. Plutôt que de placer les différents cadres de rendu dans différents processus, nous les placerons dans des threads séparés. Plutôt que d’utiliser les threads du système d’exploitation, nous utiliserons des threads ordonnancés de façon coopérative dans la sphère de l’utilisateur (NDT : user space : tout le code qui n’est pas lié au cœur du système d’exploitation). L’avantage des threads est qu’ils permettent de partager un même espace d’adressage ce qui facilite le partage de données. L’inconvénient c’est que ces données partagées doivent être protégées par des verrous. Les threads ordonnancés de façon coopérative nous permettent de passer d’un thread à l’autre de manière « sûre » à des endroits où l’état partagé est censément consistant, rendant de fait les verrous inutiles (ou à minima, moins nécessaires).

Firefox dispose d’ores et déjà d’un ensemble de points de transition sûrs. Le moteur JavaScript est capable de se mettre en pause lors d’un appel de fonction ou d’un tour de boucle afin d’exécuter un autre code. Nous utilisons d’ailleurs déjà cette capacité pour mettre en œuvre la fenêtre de dialogue « script lent » qui permet à un utilisateur d’arrêter une boucle infinie. Cependant, le même mécanisme peut être utilisé pour passer d’un thread à l’autre et commencer à exécuter du code issu d’un nouveau cadre de rendu.

Nous avons déjà commencé certaines expérimentations autour de ces concepts. Le bug 1279086, déployé dans Firefox 51, nous permet de mettre en pause l’exécution de JavaScript afin de rafraîchir l’affichage lors d’un changement d’onglet. Nos mesures de télémétrie nous indiquent que la conséquence directe de ceci est une diminution de moitié du nombre de changements d’onglets lents (> 300 ms). Nous espérons utiliser le même genre de démarche dans un futur proche pour pouvoir rafraîchir l’affichage des pages pendant le scrolling, même si une page d’arrière-plan est en train de faire tourner du JavaScript.

Notre objectif ultime cependant, c’est d’exécuter tous les cadres de rendu dans leur propre thread ordonnancé de manière coopérative. Cela nous permettra de mettre en pause un onglet d’arrière-plan afin de prioriser un certain nombre de tâches (i.e. les évènements d’entrée ou les animations) dans un onglet d’avant-plan. Avant d’en arriver là, il nous faut « étiqueter » toutes les tâches de notre pile d’évènements pour pouvoir les faire correspondre au cadre auquel elles appartiennent. De cette façon nous pourrons exécuter chaque tâche dans le thread qui lui correspond.

Étiqueter les tâches et les prioriser est un énorme travail. Michael Layzell est en train de construire une abstraction de regroupement (“DocGroup”) de manière à ce que les cadres de même origine (ceux qui peuvent dialoguer via window.parent ou window.opener) s’exécutent dans le même thread (bug 1303196). Andreas Farre est en train de mettre en place un mécanisme permettant d’organiser les tâches à basse priorités comme le GC (bug 1198381). Olli Pettay et Thinker Li sont, eux, en train de créer un mécanisme similaire pour les tâches à haute priorité comme les évènements d’entrée (bug 1306591). Au fur et à mesure de l’amélioration de notre infrastructure d’étiquetage dans les prochaines semaines, cet étiquetage des tâches sera un point d’entrée idéal pour les contributeurs qui veulent rejoindre le projet. L’état d’avancement du projet sera régulièrement publié sur la liste de diffusion dev-platform.

Finalement, nous pourrons envisager d’exécuter nos cadres de rendu dans leur propre thread géré par le système d’exploitation de façon préemptive. L’avantage des threads du système d’exploitation par rapport aux threads « utilisateur » c’est leur capacité à utiliser plusieurs cœurs du processeur. Cependant nos threads d’utilisateur seront déjà répartis sur 4 à 8 processus et la plupart des utilisateurs n’ont pas vraiment plus de cœurs de processeurs disponibles. Au fur et à mesure de l’avancée du projet nous évaluerons à nouveau si exploiter les threads du système d’exploitation nous semble pertinent.

Enfin, ce serait négligence de ma part de ne pas indiquer qu’Opera a été le premier à travailler sur une architecture d’ordonnancement coopératif. Ce sont eux qui ont accompli tout ça en premier.

Geler les onglets

Lors de nos discussions sur les méthodes d’ordonnancement du travail d’arrière-plan, nous nous sommes demandés : pourquoi exécuter quoi que ce soit ? Firefox réduit déjà la fréquence de certaines actions d’arrière-plan telles que les tâches setTimeout qui sont exécutées au plus une fois par seconde. Il est très probable que nous continuerons dans cette direction et que nous ralentirons encore plus. Pourrait-on envisager d’être encore plus agressifs et de geler complètement certains des onglets d’arrière-plan ?

freeze.png
 

Il n’est pas toujours possible de geler des onglets d’arrière-plan car certains doivent continuer à tourner. Par exemple, vous voulez que Pandora continue de lire votre musique même lorsque vous changez d’onglet. Vous voulez également que Gmail vous notifie de l’arrivée d’un e-mail même lorsque l’onglet Gmail n’est pas sélectionné. Cependant, si le navigateur avait la capacité d’identifier ces onglets « importants », nous pourrions geler le reste. Nous sommes toujours en train de définir les heuristiques qui nous permettront d’identifier les onglets d’arrière-plan importants. Ehsan Akhgari explore certaines pistes de travail que nous espérons pouvoir tester dans Firefox Nightly prochainement.

Capture_du_2016-10-29_00-06-02.png
Cliquez sur la bannière pour adopter Firefox Nightly en français