Wie und warum wir Performance Insights erstellt haben

In Chrome 102 sehen Sie in den Entwicklertools den neuen experimentellen Bereich Leistungsstatistiken. In diesem Beitrag besprechen wir nicht nur, warum wir an einem neuen Gremium gearbeitet haben, sondern auch über die technischen Herausforderungen, mit denen wir konfrontiert waren, und die Entscheidungen, die wir auf diesem Weg getroffen haben.

ALT_TEXT_HERE

Warum ein weiteres Panel?

Falls Sie es noch nicht gesehen haben, haben wir ein Video dazu veröffentlicht, warum der Bereich „Leistungsstatistiken“ erstellt werden sollte und wie Sie damit umsetzbare Informationen zur Leistung Ihrer Website erhalten.

Der vorhandene Bereich „Leistung“ ist eine hervorragende Ressource, wenn Sie alle Daten für Ihre Website an einem Ort sehen möchten. Er könnte aber auch etwas überwältigend erscheinen. Auch wenn Sie kein Experte in Sachen Performance sind, können Sie nicht genau wissen, worauf Sie achten müssen und welche Teile der Aufnahme relevant sind.

Im Bereich „Statistiken“ können Sie weiterhin eine Zeitachse Ihres Trace aufrufen und die Daten prüfen. Außerdem erhalten Sie eine praktische Liste der wichtigsten Statistiken, die von den Entwicklertools als „Statistiken“ betrachtet werden. In den Statistiken werden Probleme wie Anfragen zum Blockieren des Renderings, Layoutverschiebungen und lange Aufgaben identifiziert, um nur einige zu nennen. All dies kann sich negativ auf die Seitenladeleistung Ihrer Website und insbesondere auf die Werte für Core Web Vitals (CWV) auswirken. Neben der Meldung von Problemen erhalten Sie auch umsetzbare Vorschläge zur Verbesserung Ihrer CWV-Werte sowie Links zu weiteren Ressourcen und Dokumentationen.

Feedback-Link im Bereich

Dieser Bereich ist experimentell und wir freuen uns auf Ihr Feedback. Bitte teilen Sie uns mit, wenn Fehler auftreten oder Sie Funktionsanfragen haben, die Ihnen bei der Verbesserung der Leistung Ihrer Website helfen könnten.

So haben wir Leistungsstatistiken entwickelt

Wie bei den anderen Entwicklertools haben wir Leistungsstatistiken in TypeScript erstellt und Webkomponenten mit lit-html-Unterstützung verwendet, um die Benutzeroberfläche zu erstellen. Die Leistungsstatistiken unterscheiden sich darin, dass die primäre Benutzeroberfläche ein HTML-canvas-Element ist und die Zeitachse auf diesem Canvas dargestellt ist. Ein Großteil der Komplexität entsteht durch die Verwaltung dieses Canvas: nicht nur die richtigen Details an der richtigen Stelle zeichnen, sondern auch Mausereignisse verwalten (z. B. wo haben Nutzende auf den Canvas geklickt?) Haben sie auf ein von uns gezeichnetes Ereignis geklickt?) und dafür gesorgt, dass wir den Canvas effektiv neu rendern.

Mehrere Titel auf einem Canvas

Für eine bestimmte Website gibt es mehrere „Tracks“, die wir rendern möchten, wobei jeder eine andere Datenkategorie darstellt. Im Bereich „Statistiken“ werden beispielsweise standardmäßig drei Tracks angezeigt:

Wir gehen davon aus, dass bald weitere Titel hinzukommen.

Ursprünglich sollten wir für jeden dieser Tracks einen eigenen <canvas> rendern, sodass die Hauptansicht aus mehreren vertikal übereinander gestapelten Canvas-Elementen bestehen würde. Dies würde das Rendering auf Titelebene vereinfachen, da jeder Track isoliert gerendert werden könnte und es keine Gefahr gäbe, dass ein Track außerhalb seiner Grenzen gerendert wird. Leider hat dieser Ansatz jedoch zwei größere Probleme:

Das (erneute) Rendern von canvas-Elementen ist kostspielig. Mehrere Canvases sind teurer als ein Canvas, auch wenn dieser Canvas größer ist. Das Rendern von Overlays, die sich über mehrere Tracks erstrecken (z. B. vertikale Linien zur Markierung von Ereignissen wie FCP-Zeit), wird komplex: Wir müssen auf mehreren Canvases rendern und sicherstellen, dass sie alle zusammen gerendert und richtig ausgerichtet sind.

Durch die Verwendung eines canvas für die gesamte Benutzeroberfläche mussten wir sicherstellen, dass jeder Track mit den richtigen Koordinaten gerendert wird und nicht in einen anderen Track überläuft. Wenn ein bestimmter Track beispielsweise 100 Pixel hoch ist, können wir nicht zulassen, dass er 120 Pixel hohe Elemente rendert und in den darunter liegenden Track eindringt. Um dieses Problem zu lösen, können wir clip verwenden. Bevor wir jede Spur rendern, zeichnen wir ein Rechteck, das das sichtbare Trackfenster darstellt. Dadurch wird sichergestellt, dass Pfade, die außerhalb dieser Grenzen gezeichnet werden, vom Canvas abgeschnitten werden.

canvasContext.beginPath();
canvasContext.rect(
    trackVisibleWindow.x, trackVisibleWindow.y, trackVisibleWindow.width, trackVisibleWindow.height);
canvasContext.clip();

Außerdem wollten wir nicht, dass jeder Track seine vertikale Position kennen muss. Jeder Track sollte sich selbst so rendern, als würde er bei (0, 0) gerendert werden. Außerdem haben wir eine übergeordnete Komponente (TrackManager) zur Verwaltung der Trackposition insgesamt. Das kann mit translate erfolgen, bei dem das Canvas um eine bestimmte (x, y)-Position übersetzt wird. Beispiel:

canvasContext.translate(0, 10); // Translate by 10px in the y direction
canvasContext.rect(0, 0, 10, 10); // draw a rectangle at (0, 0) that’s 10px high and wide

Trotz der rect-Codeeinstellung 0, 0 als Position führt die angewendete Gesamtübersetzung dazu, dass das Rechteck bei 0, 10 gerendert wird. Auf diese Weise können wir auf Track-Basis arbeiten, als ob wir bei (0, 0) rendern, und unseren Track-Manager beim Rendern jedes Titels übersetzen lassen, um sicherzustellen, dass jeder Track korrekt unter dem vorherigen gerendert wird.

Canvas für Titel und Highlights

Das Canvas-Rendering ist relativ teuer und wir möchten, dass der Bereich „Statistiken“ bei der Arbeit reibungslos und responsiv bleibt. Manchmal lässt sich nicht vermeiden, dass der gesamte Canvas neu gerendert werden muss. Wenn Sie beispielsweise die Zoomstufe ändern, müssen wir noch einmal von vorn beginnen und alles neu rendern. Das Re-Rendering von Canvas ist besonders teuer, da man nicht einfach nur einen kleinen Teil davon neu rendern kann. Sie müssen den gesamten Canvas löschen und neu zeichnen. Das unterscheidet sich vom DOM-Re-Rendering, bei dem Tools den minimalen Arbeitsaufwand berechnen, nicht alles entfernen und noch einmal von vorn beginnen können.

Ein Bereich, in dem wir auf visuelle Probleme stießen, war die Hervorhebung. Wenn du den Mauszeiger auf Messwerte im Fenster bewegst, werden sie auf der Zeitachse hervorgehoben. Ebenso wird ein blauer Rahmen um das Ereignis gezeichnet, wenn du den Mauszeiger auf eine Statistik zu einem bestimmten Ereignis bewegst.

Diese Funktion wurde zuerst implementiert, indem eine Mausbewegung über ein Element erkannt wurde, das eine Hervorhebung auslöst. Dann wurde dieses Hervorhebungselement direkt auf dem Haupt-Canvas gezeichnet. Das Problem tritt auf, wenn wir die Markierung entfernen müssen. Die einzige Möglichkeit besteht darin, alles neu zu zeichnen. Es ist unmöglich, den Bereich mit dem Highlight neu zu zeichnen (nicht ohne große architektonische Änderungen), aber das erneute Zeichnen des gesamten Canvas, nur weil wir einen blauen Rahmen um ein Element entfernen möchten, wirkt wie ein Overkill. Außerdem verzögert sich eine visuelle Darstellung, wenn Sie die Maus schnell über verschiedene Elemente bewegen, um mehrere Elemente in kurzer Abfolge aufzurufen.

Um dies zu beheben, teilen wir die UI in zwei Canvases, die außerhalb des Bildschirms sichtbar sind: den Haupt-Canvas, in dem die Tracks gerendert werden, und den Canvas für Hervorhebungen, in dem Markierungen gezeichnet werden. Dann rendern wir diese Canvases, indem wir sie auf das Canvas kopieren, das für die Nutzer auf dem Bildschirm sichtbar ist. Wir können die Methode drawImage auf einen Canvas-Kontext anwenden, der ein anderes Canvas als Quelle verwenden kann.

Das bedeutet, dass das Entfernen einer Markierung nicht dazu führt, dass der Haupt-Canvas neu gezeichnet wird. Stattdessen können Sie den Bildschirm-Canvas löschen und dann den Haupt-Canvas kopieren. Das Kopieren einer Leinwand ist kostengünstig, die Zeichnung ist jedoch teuer. Durch das Verschieben von Markierungen auf eine separate Leinwand vermeiden wir diese Kosten beim Aktivieren und Deaktivieren von Markierungen.

Umfassendes getestetes Trace-Parsing

Einer der Vorteile der von Grund auf neu entwickelten Funktion besteht darin, dass Sie die zuvor getroffenen technischen Entscheidungen reflektieren und Verbesserungen vornehmen können. Eines der Dinge, die wir verbessern wollten, war die explizite Aufteilung unseres Codes in zwei, beinahe völlig unterschiedliche Teile:

Parsen Sie die Trace-Datei und rufen Sie die erforderlichen Daten ab. Hiermit wird eine Reihe von Tracks gerendert.

Da das Parsing (Teil 1) von der Arbeit mit der Benutzeroberfläche (Teil 2) getrennt war, konnten wir ein solides Parsing-System aufbauen. Jeder Trace durchläuft eine Reihe von Handlern, die für unterschiedliche Belange verantwortlich sind: Ein LayoutShiftHandler berechnet alle Informationen, die wir für Layout Shifts benötigen, und NetworkRequestsHandler dient ausschließlich dazu, Netzwerkanfragen abzurufen. Auch dieser explizite Parsing-Schritt, bei dem verschiedene Handler für verschiedene Teile des Trace verantwortlich sind, war von Vorteil: Das Parsen von Traces kann sehr kompliziert werden und hilft, sich auf jeweils ein Problem zu konzentrieren.

Außerdem konnten wir das Trace-Parsing umfassend testen, indem wir Aufzeichnungen in den Entwicklertools erstellt, sie gespeichert und dann als Teil unserer Testsuite geladen werden. Das ist großartig, weil wir mit echten Traces testen können und keine riesigen Mengen an fiktiven Trace-Daten ansammeln, die veralten könnten.

Screenshot-Test für Canvas-UI

Beim Thema Tests testen wir in der Regel unsere Front-End-Komponenten, indem wir sie im Browser rendern und sicherstellen, dass sie sich erwartungsgemäß verhalten. Wir können Klickereignisse auslösen, um Updates auszulösen, und bestätigen, dass das von den Komponenten generierte DOM korrekt ist. Dieser Ansatz funktioniert gut für uns, bricht jedoch beim Rendern auf einem Canvas ab. Es gibt keine Möglichkeit, ein Canvas zu überprüfen und zu bestimmen, was dort gezeichnet wird. Daher ist unser üblicher Ansatz für Rendering und anschließende Abfragen nicht geeignet.

Um eine gewisse Testabdeckung zu gewährleisten, haben wir Screenshot-Tests durchgeführt. Bei jedem Test wird ein Canvas erstellt, der zu testende Track gerendert und dann ein Screenshot des Canvas-Elements erstellt. Dieser Screenshot wird dann in unserer Codebasis gespeichert und bei zukünftigen Testläufen wird der gespeicherte Screenshot mit dem von ihnen generierten Screenshot verglichen. Wenn sich die Screenshots unterscheiden, schlägt der Test fehl. Wir stellen auch ein Flag zum Ausführen des Tests bereit und erzwingen ein Screenshot-Update, wenn wir das Rendering absichtlich geändert haben und eine Aktualisierung des Tests erforderlich ist.

Screenshot-Tests sind nicht perfekt und sind ein wenig stumpf. Sie können nur testen, ob die gesamte Komponente wie erwartet gerendert wird, anstatt spezifischere Assertions. Anfangs haben wir uns schuldig gemacht, dass wir sie zu häufig verwendet haben, um sicherzustellen, dass jede einzelne Komponente (HTML oder Canvas) korrekt gerendert wird. Dies hat unsere Testsuite drastisch verlangsamt und zu Problemen geführt, bei denen kleine, fast irrelevante Anpassungen der Benutzeroberfläche (z. B. subtile Farbänderungen oder ein etwas Abstand zwischen Elementen) dazu führten, dass mehrere Screenshots nicht mehr funktionierten und aktualisiert werden mussten. Wir haben die Nutzung von Screenshots reduziert und sie nur für Canvas-basierte Komponenten verwendet. Diese Balance hat sich bisher gut bewährt.

Fazit

Das Erstellen des neuen Bereichs mit Leistungsstatistiken war für das Team sehr angenehm und lehrreich. Wir haben schon viel über Trace-Dateien, die Arbeit mit Canvas und vieles mehr gelernt. Wir hoffen, dass dir das neue Panel gefällt, und sind gespannt auf dein Feedback.

Weitere Informationen zum Bereich „Leistungsstatistiken“ finden Sie unter Leistungsstatistiken: Umsetzbare Informationen zur Leistung Ihrer Website erhalten.

Vorschaukanäle herunterladen

Sie können Chrome Canary, Dev oder Beta als Standardbrowser für die Entwicklung verwenden. Über diese Vorschaukanäle erhältst du Zugriff auf die neuesten Entwicklertools-Funktionen, kannst neue Webplattform-APIs testen und Probleme auf deiner Website erkennen, bevor deine Nutzer es tun.

Chrome-Entwicklertools-Team kontaktieren

Verwende die folgenden Optionen, um die neuen Funktionen und Änderungen im Beitrag oder andere Themen im Zusammenhang mit den Entwicklertools zu besprechen.

  • Sende uns über crbug.com Vorschläge oder Feedback.
  • Wenn du ein Problem mit den Entwicklertools melden möchtest, klicke in den Entwicklertools auf Weitere Optionen   Mehr   > Hilfe > Probleme mit den Entwicklertools melden.
  • Senden Sie einen Tweet an @ChromeDevTools.
  • Hinterlasse Kommentare zu den Neuheiten in den Entwicklertools YouTube-Videos oder YouTube-Videos in den Entwicklertools-Tipps.