Cet article est rédigé par le contributeur Chromium Ahmed Elwasefi. Il explique comment il est devenu contributeur grâce au Google Summer of Code et les problèmes de performances d'accessibilité qu'il a identifiés et corrigés.
À l'approche de ma dernière année d'ingénierie informatique à l'Université allemande du Caire, j'ai décidé d'explorer les possibilités de contribuer au logiciel Open Source. J'ai commencé à explorer la liste des problèmes adaptés aux débutants de Chromium et je me suis particulièrement intéressé à l'accessibilité. Ma recherche de conseils m'a conduit à Aaron Leventhal, dont l'expertise et la volonté d'aider m'ont inspiré à collaborer avec lui pour un projet. Cette collaboration est devenue mon expérience Google Summer of Code, où j'ai été accepté pour travailler avec l'équipe d'accessibilité Chromium.
Après avoir terminé Google Summer of Code, j'ai continué à résoudre un problème de défilement non résolu, dans le but d'améliorer les performances. Grâce à deux subventions du programme OpenCollective de Google, j'ai pu continuer à travailler sur ce projet tout en assumant des tâches supplémentaires axées sur la simplification du code pour de meilleures performances.
Cet article de blog retrace mon parcours avec Chromium au cours des 18 derniers mois et détaille les améliorations techniques que nous avons apportées, en particulier dans le domaine des performances.
Impact du code d'accessibilité sur les performances dans Chrome
Le code d'accessibilité de Chrome aide les technologies d'assistance, comme les lecteurs d'écran, à accéder au Web. Toutefois, lorsqu'il est activé, il peut affecter les temps de chargement, les performances et l'autonomie de la batterie. Par conséquent, si ce n'est pas nécessaire, ce code reste inactif pour éviter de ralentir les performances. Environ 5 à 10% des utilisateurs ont activé le code d'accessibilité, souvent en raison d'outils tels que les gestionnaires de mots de passe et les logiciels antivirus qui utilisent les API d'accessibilité de la plate-forme. Ces outils s'appuient sur ces API pour interagir avec le contenu de la page et le modifier, par exemple pour localiser les champs de mot de passe des gestionnaires de mots de passe et des outils de saisie de formulaires.
La dégradation totale des métriques principales n'est pas encore connue, mais un test récent appelé "Désactivation automatique de l'accessibilité" (désactivation de l'accessibilité lorsqu'elle n'est pas utilisée) montre qu'elle est assez élevée. Ce problème survient en raison des quantités massives de calculs et de communications dans deux domaines principaux du codebase d'accessibilité de Chrome: le moteur de rendu et le navigateur. Le moteur de rendu collecte des informations sur les contenus Web et les modifications apportées au contenu, et calcule les propriétés d'accessibilité pour une arborescence de nœuds. Tous les nœuds sales sont ensuite sérialisés et envoyés via un canal au thread d'UI principal du processus du navigateur. Ce thread reçoit et désérialise ces informations dans un arbre de nœuds identique, puis les convertit finalement dans un format adapté aux technologies d'assistance tierces telles que les lecteurs d'écran.
Améliorations de l'accessibilité de Chromium
Les projets suivants ont été réalisés pendant l'édition 2019 du Summer of Code, puis financés par le programme Google OpenCollective.
Amélioration liée au cache
Dans Chrome, une structure de données spéciale appelée arbre d'accessibilité reflète l'arbre DOM. Il permet aux technologies d'assistance d'accéder au contenu Web. Parfois, lorsqu'un appareil a besoin d'informations de cet arbre, il n'est pas prêt. Le navigateur doit donc planifier ces requêtes pour plus tard.
Auparavant, cette planification était gérée à l'aide d'une méthode appelée "closures", qui consistait à placer des rappels dans une file d'attente. Cette approche a ajouté du travail supplémentaire en raison de la façon dont les fermetures sont traitées.
Pour améliorer ce point, nous sommes passés à un système utilisant des énumérations. Une valeur d'énumération spécifique est attribuée à chaque tâche. Une fois l'arborescence d'accessibilité prête, la méthode appropriée pour cette tâche est appelée. Ce changement a rendu le code plus facile à comprendre et a amélioré les performances de plus de 20%.
Identifier et résoudre les problèmes de performances de défilement
Ensuite, j'ai étudié l'amélioration des performances lorsque nous désactivons la sérialisation de la zone de délimitation. Les cadres de délimitation correspondent aux positions et aux tailles des éléments d'une page Web, y compris des détails tels que la largeur, la hauteur et leur position par rapport à leur élément parent.
Pour tester cela, nous avons temporairement supprimé le code qui gère les rectangles de délimitation et exécuté des tests de performances pour voir l'impact. Un test, focus-links.html, a montré une amélioration considérable d'environ 1 618%. Cette découverte est devenue la base de travaux ultérieurs.
Examiner le test lent
J'ai commencé à examiner pourquoi ce test spécifique était lent avec les rectangles de délimitation. Le test ne faisait que mettre en surbrillance plusieurs liens l'un après l'autre. Par conséquent, le problème principal doit concerner soit la mise au point sur des éléments, soit le défilement qui s'est produit avec l'action de mise au point. Pour tester cela, j'ai ajouté {preventScroll: true}
à l'appel focus()
dans le test de performances, ce qui a arrêté le défilement.
Lorsque le défilement est désactivé, le temps de test est réduit à 1,2 milliseconde lorsque les calculs de la zone de délimitation sont actifs. Cela a montré que le défilement était le véritable problème.
J'ai créé un nouveau test appelé scroll-in-page.html pour reproduire le test focus-links, mais au lieu d'utiliser le focus, il fait défiler les éléments avec scrollIntoView()
. J'ai testé le défilement fluide et instantané, avec et sans calculs de la zone de délimitation.
Les résultats ont montré qu'avec le défilement instantané et les cadres de délimitation, le processus prenait environ 66 ms. Le défilement fluide était encore plus lent, à environ 124 ms. Lorsque nous avons désactivé les rectangles de délimitation, cela n'a pris aucun temps, car aucun événement n'a été déclenché.
Nous connaissions le problème, mais pourquoi se produisait-il ?
Nous avons maintenant appris que le défilement est à l'origine de beaucoup de lenteurs dans la sérialisation d'accessibilité, mais nous devions encore comprendre pourquoi. Pour analyser cela, deux outils appelés perf et pprof ont été utilisés pour décomposer le travail effectué dans le processus du navigateur. Ces outils sont souvent utilisés en C++ pour le profilage. Les graphiques suivants montrent un extrait de la partie intéressante.
Après examen, nous avons constaté que le problème ne concernait pas le code de désérialisation lui-même, mais la fréquence des appels. Pour comprendre cela, nous devons examiner le fonctionnement des mises à jour d'accessibilité dans Chromium. Les mises à jour ne sont pas envoyées individuellement. Au lieu de cela, un emplacement central appelé AXObjectCache
stocke toutes les propriétés. Lorsqu'un nœud change, diverses méthodes informent le cache pour qu'il le marque comme sale pour une sérialisation ultérieure. Ensuite, toutes les propriétés des notes sales, y compris les propriétés inchangées, sont sérialisées et envoyées au navigateur. Bien que cette conception simplifie le code et réduise la complexité en ayant un seul chemin d'actualisation, elle devient lente en cas d'événements "marquer comme sale" rapides, tels que ceux provenant du défilement. La seule chose qui change est la valeur scrollX
et scrollY
. Pourtant, nous sérialisons le reste des propriétés avec elles à chaque fois. Le taux de mises à jour a atteint plus de vingt fois par seconde.
La sérialisation de la zone de délimitation résout ce problème en utilisant un chemin de sérialisation plus rapide qui n'envoie que les détails de la zone de délimitation, ce qui permet des mises à jour rapides sans affecter les autres propriétés. Cette méthode gère efficacement les modifications de la zone de délimitation.
Correction du défilement
La solution était claire: inclure les décalages de défilement actuels avec la sérialisation de la zone de délimitation. Cela garantit que les mises à jour de défilement sont traitées via le chemin rapide, ce qui améliore les performances sans retards inutiles. En empaquetant les décalages de défilement avec des données de rectangle de délimitation, nous optimisons le processus pour des mises à jour plus fluides et plus efficaces, ce qui crée une expérience moins saccadée pour les utilisateurs dont l'accessibilité est activée. L'amélioration après l'implémentation du correctif est jusqu'à 825% dans les tests de défilement.
Simplifications du code
Pendant cette période, je me suis concentré sur la qualité du code dans le cadre d'un projet appelé "Soupe à l'oignon", qui simplifie le code en réduisant ou en supprimant le code inutilement réparti sur les couches.
Le premier projet visait à simplifier la sérialisation des données d'accessibilité du moteur de rendu au navigateur. Auparavant, les données devaient passer par une couche supplémentaire avant d'atteindre leur destination, ce qui ajoutait une complexité inutile. Nous avons simplifié ce processus en permettant l'envoi direct des données, ce qui élimine l'intermédiaire.
De plus, nous avons identifié et supprimé certains événements obsolètes qui entraînaient un travail inutile dans le système, comme celui qui se déclenchait lorsqu'une mise en page était terminée. Nous les avons remplacés par une solution plus efficace.
D'autres petites améliorations ont également été apportées. Malheureusement, aucune amélioration des performances n'a été enregistrée pour ces éléments, mais nous sommes fiers de vous annoncer que le code est beaucoup plus clair et auto-documenté qu'auparavant. Cela permet de préparer l'amélioration des performances à l'avenir. Vous pouvez consulter les modifications réelles dans mon profil Gerrit.
Conclusion
Travailler avec l'équipe d'accessibilité de Chromium a été une expérience enrichissante. En abordant divers défis, de l'optimisation des performances de défilement à la simplification du codebase, j'ai acquis une compréhension plus approfondie du développement dans un projet de grande envergure, et j'ai appris des outils importants pour le profilage. De plus, j'ai appris à quel point l'accessibilité est essentielle pour créer un Web inclusif pour tous. Les améliorations que nous avons apportées non seulement améliorent l'expérience utilisateur pour les personnes qui s'appuient sur des technologies d'assistance, mais contribuent également aux performances et à l'efficacité globales du navigateur.
Les résultats en termes de performances ont été impressionnants. Par exemple, le passage à l'utilisation d'énumérations pour planifier des tâches a amélioré les performances de plus de 20%. De plus, notre correction du défilement a permis de réduire les tests de défilement jusqu'à 825%. Les modifications de simplification du code ont non seulement rendu le code plus clair et plus facile à gérer, mais elles ont également ouvert la voie à de futures améliorations.
Je tiens à remercier Stefan Zager, Chris Harrelson et Mason Freed pour leur soutien et leurs conseils tout au long de l'année, et en particulier Aaron Leventhal, sans qui cette opportunité n'aurait pas été possible. Je tiens également à remercier Tab Atkins-Bittner et l'équipe GSoC pour leur aide.
Pour ceux qui souhaitent contribuer à un projet significatif et développer leurs compétences, je recommande vivement de s'impliquer dans Chromium. C'est un excellent moyen d'apprendre, et des programmes comme Google Summer of Code constituent un excellent point de départ pour votre parcours.