Überblick über die RenderingNG-Architektur

Chris Harrelson
Chris Harrelson

In einem vorherigen Beitrag habe ich einen Überblick über die Ziele und wichtigsten Eigenschaften der RenderingNG-Architektur gegeben. In diesem Beitrag wird erläutert, wie die einzelnen Bestandteile aufgebaut sind und wie sie von der Rendering-Pipeline durchlaufen werden.

Beginnend auf der obersten Ebene und die Aufschlüsselung von dort aus werden die folgenden Aufgaben ausgeführt:

  1. Inhalte auf dem Bildschirm in Pixel rendern
  2. Animieren Sie visuelle Effekte auf den Inhalt von einem Status in einen anderen.
  3. Scrollen als Reaktion auf Eingabe
  4. Leiten Sie Eingaben effizient an die richtigen Stellen weiter, damit Entwicklerskripts und andere Subsysteme antworten können.

Der zu rendernde Inhalt besteht aus einer Struktur von Frames für jeden Browsertab und der Benutzeroberfläche des Browsers. Ein Stream von Roheingabeereignissen von Touchscreens, Mäusen, Tastaturen und anderen Hardwaregeräten.

Jeder Frame enthält Folgendes:

  • DOM-Status
  • CSS
  • Canvases
  • Externe Ressourcen wie Bilder, Videos, Schriftarten und SVG

Ein Frame ist ein HTML-Dokument plus dessen URL. Eine Webseite, die auf einem Browsertab geladen wird, hat einen Frame auf oberster Ebene, untergeordnete Frames für jeden im Dokument auf oberster Ebene enthaltenen iFrame und ihre untergeordneten iFrames.

Ein visueller Effekt ist ein grafischer Vorgang, der auf eine Bitmap angewendet wird, z. B. Scrollen, Transformieren, Abschneiden, Filtern, Deckkraft oder Überblenden.

Architekturkomponenten

In RenderingNG werden diese Aufgaben logisch auf mehrere Phasen und Codekomponenten aufgeteilt. Die Komponenten landen in verschiedenen CPU-Prozessen, Threads und Unterkomponenten innerhalb dieser Threads. Jede einzelne Rolle spielt eine wichtige Rolle beim Erreichen von Zuverlässigkeit, skalierbare Leistung und Erweiterbarkeit für alle Webinhalte.

Rendering-Pipeline-Struktur

Diagramm der Rendering-Pipeline, wie im folgenden Text erläutert

Das Rendering erfolgt in einer Pipeline. Dabei werden mehrere Phasen und Artefakte erstellt. Jede Phase stellt Code dar, der eine genau definierte Aufgabe im Rendering ausführt. Die Artefakte sind Datenstrukturen, die Ein- oder Ausgaben der Phasen sind. Im Diagramm werden Ein- und Ausgaben durch Pfeile gekennzeichnet.

In diesem Blogpost geht es nicht um Artefakte, die wir im nächsten Beitrag behandeln: Key Data Structures and their roles in RenderingNG (Schlüsseldatenstrukturen und ihre Rollen in RenderingNG).

Pipelinephasen

Im vorherigen Diagramm werden die Phasen durch Farben gekennzeichnet, die angeben, in welchem Thread oder Prozess sie ausgeführt werden:

  • Grün:Hauptthread des Renderingprozesses
  • Gelb:Compositor für den Renderingprozess
  • Orange: Visualisierungsprozess

In einigen Fällen können sie je nach Situation an mehreren Stellen ausgeführt werden. Deshalb haben einige davon zwei Farben.

Die Phasen sind:

  1. Animation: Ändern Sie berechnete Stile und ändern Sie die Property-Bäume im Laufe der Zeit basierend auf deklarativen Zeitplänen.
  2. Stil: Wenden Sie CSS auf das DOM an und erstellen Sie berechnete Stile.
  3. Layout:Bestimmen Sie die Größe und Position von DOM-Elementen auf dem Bildschirm und erstellen Sie den unveränderlichen Fragmentbaum.
  4. Vormalen:Berechnen Sie die Eigenschaftsstruktur und invalidate Sie vorhandene Anzeigelisten und GPU-Texturkacheln entsprechend.
  5. Scrollen: Aktualisieren Sie den Scrollversatz von Dokumenten und scrollbaren DOM-Elementen, indem Sie die Eigenschaftenstruktur ändern.
  6. Paint:Es wird eine Anzeigeliste berechnet, in der beschrieben wird, wie GPU-Texturkacheln aus dem DOM gerastert werden.
  7. Commit:Property-Bäume und Anzeigeliste werden in den Compositor-Thread kopiert.
  8. Layerize:Unterteilen Sie die Anzeigeliste in eine zusammengesetzte Ebenenliste für eine unabhängige Rasterung und Animation.
  9. Worklets rastern, decodieren und malen:Wandelt Anzeigelisten, codierte Bilder bzw. Paint Worklet-Code in GPU-Texturkacheln um.
  10. Aktivieren:Erstellen Sie einen Compositor-Frame, der zeigt, wie GPU-Kacheln zusammen mit den visuellen Effekten gezeichnet und auf dem Bildschirm positioniert werden.
  11. Aggregieren:Kombinieren Sie Compositor-Frames aus allen sichtbaren Compositor-Frames zu einem einzelnen, globalen Compositor-Frame.
  12. Draw:Führen Sie den aggregierten Compositor-Frame auf der GPU aus, um Pixel auf dem Bildschirm zu erstellen.

Nicht benötigte Phasen der Rendering-Pipeline können übersprungen werden. Bei Animationen von visuellen Effekten und Scrollen können Sie beispielsweise Layout, Vormalen und Malen überspringen. Aus diesem Grund sind Animation und Scrollen im Diagramm mit gelben und grünen Punkten gekennzeichnet. Wenn Layout, Vormalen und Paint für visuelle Effekte übersprungen werden können, können sie vollständig im Compositor-Thread ausgeführt werden und den Hauptthread überspringen.

Das Browser-UI-Rendering wird hier nicht direkt dargestellt, sondern als vereinfachte Version derselben Pipeline betrachtet. Tatsächlich verwendet ihre Implementierung einen Großteil des Codes. Videos (auch nicht direkt dargestellt) werden im Allgemeinen über einen unabhängigen Code gerendert, der Frames in GPU-Texturkacheln decodiert, die dann in Compositor-Frames und im Zeichenschritt angeschlossen werden.

Prozess- und Threadstruktur

CPU-Prozesse

Durch die Verwendung mehrerer CPU-Prozesse wird eine Leistungs- und Sicherheitsisolation zwischen den Websites und dem Browserstatus sowie eine Isolation der Stabilität und Sicherheit von der GPU-Hardware erreicht.

Diagramm der verschiedenen Teile der CPU-Prozesse

  • Beim Renderingprozess werden Eingaben für eine einzelne Kombination aus Website und Tab gerendert, animiert, scrollt und weitergeleitet. Es gibt viele Rendering-Prozesse.
  • Der Browserprozess rendert, animiert und leitet Eingaben für die Benutzeroberfläche des Browsers (einschließlich der URL-Leiste, Tabtitel und Symbole) und leitet die gesamte verbleibende Eingabe an den entsprechenden Renderingprozess weiter. Es gibt genau einen Browserprozess.
  • Der Viz-Prozess aggregiert die Zusammensetzung aus mehreren Rendering-Prozessen und dem Browserprozess. Die Grafik rastert und zeichnet mithilfe der GPU. Es gibt genau einen Visualisierungsprozess.

Verschiedene Websites haben immer unterschiedliche Renderingprozesse. In Wirklichkeit ist dies jedoch immer auf Computern, wenn möglich auf Mobilgeräten. Ich schreibe „immer“ unten, aber diese Vorbehalte gilt durchgehend.)

Mehrere Browsertabs oder -fenster derselben Website werden in der Regel in verschiedenen Renderingprozessen ausgeführt, es sei denn, die Tabs sind miteinander verknüpft (ein Tab öffnet den anderen). Unter hoher Speicherauslastung auf dem Computer kann Chromium mehrere Tabs derselben Website in denselben Renderingprozess einfügen, auch wenn sie nicht miteinander in Zusammenhang stehen.

Innerhalb eines einzelnen Browsertabs befinden sich die Frames verschiedener Websites immer in unterschiedlichen Rendering-Prozessen, die Frames derselben Website sind jedoch immer in demselben Renderprozess enthalten. Aus Sicht des Renderings besteht der wichtige Vorteil mehrerer Renderingprozesse darin, dass websiteübergreifende iFrames und Tabs eine Leistungsisolation voneinander erzielen. Außerdem kann für Ursprünge eine noch mehr Isolation aktiviert werden.

Es gibt genau einen Visualisierungsprozess für Chromium. Schließlich gibt es normalerweise nur eine GPU und einen Bildschirm zum Zeichnen. Die Aufteilung von Viz in einen eigenen Prozess ist gut für die Stabilität bei Programmfehlern in GPU-Treibern oder in der Hardware. Es eignet sich auch für die Sicherheitsisolation, die für GPU-APIs wie Vulkan wichtig ist. Es ist auch für die Sicherheit im Allgemeinen wichtig.

Da der Browser viele Tabs und Fenster haben kann und alle Nutzer mit Browser-UI-Pixeln gezeichnet werden, fragen Sie sich vielleicht: Warum gibt es genau einen Browserprozess? Dies liegt daran, dass immer nur einer davon aktiv ist. Nicht sichtbare Browsertabs werden größtenteils deaktiviert und entfernen ihren gesamten GPU-Arbeitsspeicher. Allerdings werden zunehmend komplexe Funktionen zum Rendern der Browser-UI auch in Rendering-Prozessen (WebUI) implementiert. Dies dient nicht der Leistungsisolation, sondern dient dazu, die Nutzerfreundlichkeit des Web-Rendering-Moduls von Chromium zu nutzen.

Auf älteren Android-Geräten werden Rendering- und Browserprozesse freigegeben, wenn sie in einer WebView verwendet werden. Dies gilt im Allgemeinen nicht für Chromium unter Android, nur für WebView. In WebView wird der Browserprozess auch mit der einbettenden App geteilt und WebView hat nur einen Renderingprozess.

Manchmal gibt es auch einen Dienstprogrammprozess zum Decodieren von geschützten Videoinhalten. Dieser Vorgang wurde oben nicht beschrieben.

Unterhaltungen

Threads tragen dazu bei, trotz langsamer Aufgaben, Pipelineparallelisierung und mehrfacher Zwischenspeicherung Leistungsisolierung und Reaktionsfähigkeit zu erreichen.

Ein Diagramm des im Artikel beschriebenen Renderingprozesses

  • Der Hauptthread führt Skripts, die Rendering-Ereignisschleife, den Dokumentlebenszyklus, die Treffertests, die Weiterleitung von Skriptereignissen und das Parsen von HTML-, CSS- und anderen Datenformaten aus.
    • Hauptthread-Hilfsprogramme führen Aufgaben wie das Erstellen von Bildbitmaps und Blobs aus, die eine Codierung oder Decodierung erfordern.
    • Web Worker führen ein Skript und eine Rendering-Ereignisschleife für OffscreenCanvas aus.
  • Der Compositor-Thread verarbeitet Eingabeereignisse, führt Scrollen und Animationen von Webinhalten durch, berechnet eine optimale Ebenenstrukturierung von Webinhalten und koordiniert Bilddecodierungen, Paint-Worklets und Rasteraufgaben.
    • Compositor-Thread-Hilfsprogramme koordinieren Visualisierungs-Rasteraufgaben und führen Bilddecodierungsaufgaben, Paint-Worklets und Fallback-Raster aus.
  • Medien-, Demuxer- oder Audioausgabe-Threads decodieren, verarbeiten und synchronisieren Video- und Audiostreams. Denken Sie daran, dass das Video parallel zur Haupt-Rendering-Pipeline ausgeführt wird.

Das Trennen der Haupt- und Compositor-Threads ist für die Leistungsisolation von Animationen und Scrollen vom Hauptthread äußerst wichtig.

Es gibt nur einen Hauptthread pro Renderingprozess, auch wenn mehrere Tabs oder Frames von derselben Website zum selben Prozess führen können. Die Leistung ist jedoch isoliert von der Arbeit in verschiedenen Browser-APIs. Beispielsweise wird das Generieren von Bild-Bitmaps und -Blobs in der Canvas API in einem Hauptthread-Hilfsthread ausgeführt.

Daher gibt es nur einen Compositor-Thread pro Renderingprozess. Im Allgemeinen ist es kein Problem, dass es nur eines gibt, da alle wirklich teuren Vorgänge im Compositor-Thread entweder an Compositor-Worker-Threads oder an den Visualisierungsprozess delegiert werden und diese Arbeit parallel zum Eingaberouting, zum Scrollen oder zur Animation erledigt werden kann. Compositor-Worker-Threads koordinieren Aufgaben, die im Viz-Prozess ausgeführt werden. Die GPU-Beschleunigung überall kann jedoch aus Gründen ausfallen, die Chromium außerhalb der Kontrolle liegt, z. B. Treiberfehler. In diesen Situationen führt der Worker-Thread die Arbeit in einem Fallback-Modus auf der CPU aus.

Die Anzahl der Compositor-Worker-Threads hängt von den Funktionen des Geräts ab. Desktop-Computer verwenden beispielsweise in der Regel mehr Threads, da sie mehr CPU-Kerne haben und weniger Batterieleistung benötigen als Mobilgeräte. Dies ist ein Beispiel für das Hoch- und Herunterskalieren.

Beachten Sie auch, dass die Threading-Architektur für den Renderingprozess eine Anwendung von drei verschiedenen Optimierungsmustern ist:

  • Hilfsthreads:lang andauernde Unteraufgaben werden an zusätzliche Threads gesendet, damit der übergeordnete Thread auf andere Anfragen reagiert, die gleichzeitig auftreten. Die Hauptthread-Hilfsthreads und Compositor-Hilfsthreads sind gute Beispiele für diese Technik.
  • Mehrfachzwischenspeicherung:Es werden zuvor gerenderte Inhalte beim Rendern neuer Inhalte angezeigt, um die Renderinglatenz zu verbergen. Der Compositor-Thread verwendet dieses Verfahren.
  • Pipelineparallelisierung: Ausführung der Rendering-Pipeline an mehreren Orten gleichzeitig. So können Scrollen und Animationen schnell sein, selbst wenn das Rendering des Hauptthreads aktualisiert wird, da Scrollen und Animationen parallel ausgeführt werden können.

Browserprozess

Ein Browser-Prozessdiagramm, das die Beziehung zwischen dem Rendering- und dem zusammengesetzten Thread und dem Assistenten zum Rendern und Zusammensetzen des Threads zeigt.

  • Der Rendering- und Compositing-Thread reagiert auf Eingaben in der Browser-UI, leitet andere Eingaben an den richtigen Renderingprozess weiter und erstellt das Layout und die Darstellung der Browser-UI.
  • Die Hilfsprogramme zum Rendern und Zusammensetzen von Threads führen Bilddecodierungsaufgaben und Fallback-Raster- oder Fallback-Decodierungsvorgänge aus.

Das Rendering und die Zusammensetzung des Threads durch den Browserprozess ähneln dem Code und der Funktionalität eines Renderingprozesses, mit der Ausnahme, dass der Hauptthread und der Compositor-Thread in einem Thread kombiniert werden. In diesem Fall wird nur ein Thread benötigt, da keine Leistungsisolation von Aufgaben langer Hauptthreads erforderlich ist, da diese nicht vorgesehen sind.

Visualisierungsprozess

Ein Diagramm, das zeigt, dass der Viz-Prozess den GPU-Hauptthread und den Display-Compositor-Thread enthält.

  • Die GPU-Hauptthread-Raster zeigen Listen und Videoframes in GPU-Texturkacheln an und ziehen Compositor-Frames auf den Bildschirm.
  • Der Display-Compositor-Thread aggregiert und optimiert den Compositing aus jedem Renderingprozess sowie dem Browserprozess in einem einzigen Compositor-Frame zur Präsentation auf dem Bildschirm.

Rastern und Zeichnen erfolgen im Allgemeinen im selben Thread, da beide auf GPU-Ressourcen basieren und es schwierig ist, die Multithread-GPU zuverlässig zu nutzen. Ein einfacherer Multithread-Zugriff auf die GPU ist eine Motivation für die Entwicklung des neuen Vulkan-Standards. In Android WebView gibt es einen separaten Rendering-Thread auf Betriebssystemebene zum Zeichnen, da WebViews in eine native App eingebettet sind. Andere Plattformen werden einen solchen Thread wahrscheinlich in Zukunft haben.

Der Displaycompositor befindet sich in einem anderen Thread, da er immer responsiv sein muss und nicht aufgrund einer möglichen Verlangsamung des GPU-Hauptthreads blockiert wird. Eine Ursache für eine Verlangsamung des GPU-Hauptthreads sind Aufrufe von Nicht-Chromium-Code, z. B. anbieterspezifische GPU-Treiber, die auf schwer vorhersehbare Weise langsam sein können.

Komponentenstruktur

In jedem Rendering-Haupt- oder Compositor-Thread gibt es logische Softwarekomponenten, die auf strukturierte Weise miteinander interagieren.

Hauptthread-Komponenten des Renderingprozesses

Ein Diagramm des Blink-Renderers

  • Blink-Renderer:
    • Das lokale Frame-Baumfragment stellt den Baum der lokalen Frames und das DOM innerhalb der Frames dar.
    • Die Komponente DOM und Canvas APIs enthält Implementierungen dieser APIs.
    • Der Runner für den Dokumentlebenszyklus führt die Schritte der Rendering-Pipeline bis einschließlich zum Commit-Schritt aus.
    • Die Komponente zum Testen und Senden von Eingabeereignissen führt Treffertests aus, um herauszufinden, auf welches DOM-Element ein Ereignis ausgerichtet ist. Außerdem führt sie die Weiterleitungsalgorithmen und Standardverhalten der Eingabeereignisse aus.
  • Der Planer und Runner der Rendering-Ereignisschleife entscheidet, was und wann in der Ereignisschleife ausgeführt werden soll. Er plant das Rendering in einer Frequenz, die dem Display des Geräts entspricht.

Ein Diagramm des Framebaums.

Lokale Frame-Baumfragmente sind etwas kompliziert. Denken Sie daran, dass ein Frame-Baum rekursiv die Hauptseite und ihre untergeordneten iFrames darstellt. Ein Frame ist für einen Renderingprozess lokal, wenn er während dieses Prozesses gerendert wird. Andernfalls ist er remote.

Sie können Frames anhand ihres Renderingprozesses einfärben. In der vorherigen Abbildung sind die grünen Kreise alle Frames in einem Renderingprozess. Die orangefarbenen Kreise befinden sich in einem zweiten und der blaue Kreis in einem dritten.

Ein lokales Frame-Baumfragment ist eine verbundene Komponente derselben Farbe in einem Frame-Baum. Im Bild sind vier lokale Frame-Bäume zu sehen: zwei für Standort A, einer für Standort B und einer für Standort C. Jede lokale Frame-Baumstruktur erhält eine eigene Blink-Renderer-Komponente. Der Blink-Renderer einer lokalen Frame-Baumstruktur kann sich im selben Renderingprozess wie andere lokale Frame-Bäume befinden. Dies hängt davon ab, wie die Renderingprozesse ausgewählt werden (siehe oben).

Zusammengesetzter Thread des Renderingprozesses

Ein Diagramm, das die Compositor-Komponenten des Renderingprozesses zeigt.

Zu den Compositor-Komponenten des Renderingprozesses gehören:

  • Daten-Handler, der eine Liste mit zusammengesetzten Ebenen, Anzeigelisten und Eigenschaftsstrukturen verwaltet
  • Ein Lebenszyklus-Runner, auf dem die Schritte zum Animieren, Scrollen, Zusammensetzen, Rastern, Decodieren und Aktivieren der Renderingpipeline ausgeführt werden. Das Animieren und Scrollen ist sowohl im Hauptthread als auch im Compositor möglich.
  • Ein Eingabe- und Treffertest-Handler führt eine Eingabeverarbeitung und Treffertests mit der Auflösung der zusammengesetzten Ebenen durch, um festzustellen, ob Scrollgesten im Compositor-Thread ausgeführt werden können und auf welche Treffertests für den Renderingprozess ausgerichtet werden sollen.

Ein Beispiel aus der Praxis

Machen wir die Architektur jetzt anhand eines Beispiels konkreter. In diesem Beispiel gibt es drei Tabs:

Tab 1: foo.com

<html>
  <iframe id=one src="foo.com/other-url"></iframe>
  <iframe  id=two src="bar.com"></iframe>
</html>

Tab 2: bar.com

<html>
 …
</html>

Tab 3: baz.com html <html> … </html>

Prozess-, Thread- und Komponentenstruktur für diese Registerkarten sieht folgendermaßen aus:

Diagramm des Vorgangs für die Tabs.

Sehen wir uns jetzt ein Beispiel für jede der vier Hauptaufgaben des Renderings an. Zur Erinnerung:

  1. Rendere Inhalte auf dem Bildschirm in Pixel.
  2. Animieren visueller Effekte auf Inhalte von einem Status in einen anderen.
  3. Scrollen als Reaktion auf Eingabe
  4. Leiten Sie Eingaben effizient an die richtigen Stellen weiter, damit Entwicklerskripts und andere Subsysteme antworten können.

So rendern das geänderte DOM für Tab 1:

  1. Ein Entwicklerskript ändert das DOM im Renderingprozess für foo.com.
  2. Der Blink-Renderer teilt dem Compositor mit, dass ein Rendering erfolgen muss.
  3. Der Compositor teilt Viz mit, dass ein Rendering erforderlich ist.
  4. Die Visualisierung signalisiert dem Compositor den Start des Renderings.
  5. Der Compositor leitet das Startsignal an den Blink-Renderer weiter.
  6. Der Runner des Hauptthread-Ereignisschleife führt den Dokumentlebenszyklus aus.
  7. Der Hauptthread sendet das Ergebnis an den Compositor-Thread.
  8. Der Runner der Compositor-Ereignisschleife führt den Compositing-Lebenszyklus aus.
  9. Alle Rasteraufgaben werden für Raster an Viz gesendet. Häufig gibt es mehrere dieser Aufgaben.
  10. Die Visualisierung rastert Inhalte auf der GPU.
  11. Viz bestätigt den Abschluss der Rasteraufgabe. Hinweis: Chromium wartet häufig nicht, bis das Raster abgeschlossen ist. Stattdessen wird ein sogenanntes Synchronisierungstoken verwendet, das vor dem Ausführen von Schritt 15 von Rasteraufgaben aufgelöst werden muss.
  12. Ein Compositor-Frame wird an Viz gesendet.
  13. Viz fasst die Compositor-Frames für den Renderingprozess foo.com, den iFrame-Renderingprozess von bar.com und die Browser-Benutzeroberfläche zusammen.
  14. Viz plant eine Verlosung.
  15. Visualisierung zieht den aggregierten Compositor-Frame auf den Bildschirm.

So animieren Sie einen CSS-Transformationsübergang auf Tab 2:

  1. Der Compositor-Thread für den bar.com-Renderingprozess markiert eine Animation in seiner Compositor-Ereignisschleife, indem die vorhandenen Property-Bäume verändert werden. Dadurch wird der Compositor-Lebenszyklus noch einmal ausgeführt. (Raster- und Decodierungsaufgaben können auftreten, werden hier aber nicht dargestellt.)
  2. Ein Compositor-Frame wird an Viz gesendet.
  3. Visualisierung aggregiert die Compositor-Frames für den foo.com-Renderingprozess, den bar.com-Renderingprozess und die Browser-Benutzeroberfläche.
  4. Viz plant eine Verlosung.
  5. Visualisierung zieht den aggregierten Compositor-Frame auf den Bildschirm.

So scrollen Sie die Webseite auf Tab 3:

  1. Im Browserprozess wird eine Abfolge von input-Ereignissen (Maus, Touchscreen oder Tastatur) ausgelöst.
  2. Jedes Ereignis wird an den Compositor-Thread des Renderingprozesses von baz.com weitergeleitet.
  3. Der Compositor bestimmt, ob der Hauptthread über das Ereignis informiert werden muss.
  4. Das Ereignis wird gegebenenfalls an den Hauptthread gesendet.
  5. Der Hauptthread löst input-Ereignis-Listener (pointerdown, touchstar, pointermove, touchmove oder wheel) aus, um festzustellen, ob Listener für das Ereignis preventDefault aufrufen.
  6. Der Hauptthread gibt zurück, ob preventDefault beim Compositor aufgerufen wurde.
  7. Andernfalls wird das Eingabeereignis an den Browserprozess zurückgesendet.
  8. Der Browserprozess wandelt sie in eine Scroll-Geste um, indem sie mit anderen aktuellen Ereignissen kombiniert wird.
  9. Die Scroll-Geste wird noch einmal an den Compositor-Thread des Renderingprozesses von baz.com gesendet.
  10. Das Scrollen wird dort angewendet und der Compositor-Thread für den bar.com-Renderingprozess tickt eine Animation in seiner Compositor-Ereignisschleife. Dadurch wird dann der Scroll-Offset in den Eigenschaftsstrukturen mutiert und der Compositor-Lebenszyklus noch einmal ausgeführt. Außerdem wird der Hauptthread angewiesen, ein scroll-Ereignis auszulösen (hier nicht dargestellt).
  11. Ein Compositor-Frame wird an Viz gesendet.
  12. Viz fasst die Compositor-Frames für den Renderingprozess foo.com, den Renderingprozess bar.com und die Browser-Benutzeroberfläche zusammen.
  13. Viz plant eine Verlosung.
  14. Visualisierung zieht den aggregierten Compositor-Frame auf den Bildschirm.

So leiten Sie ein click-Ereignis bei einem Hyperlink in iFrame Nr. 2 auf Tab 1 weiter:

  1. Ein input-Ereignis (Maus, Touchscreen oder Tastatur) wird im Browserprozess erfasst. Dabei wird ein ungefährer Treffertest durchgeführt, um festzustellen, ob der iFrame-Renderingprozess von bar.com den Klick empfangen und dorthin senden soll.
  2. Der Compositor-Thread für bar.com leitet das click-Ereignis an den Hauptthread für bar.com weiter und plant eine Rendering-Ereignisschleifenaufgabe zur Verarbeitung.
  3. Der Eingabeereignisprozessor für die Hauptthread-Treffertests von bar.com wird ermittelt, auf welches DOM-Element im iFrame geklickt wurde, und löst ein click-Ereignis aus, das von Skripts beobachtet werden kann. Wenn kein preventDefault gehört, wird zum Hyperlink gewechselt.
  4. Beim Laden der Landingpage des Hyperlinks wird der neue Status gerendert, wobei die Schritte dem Beispiel „geändertes DOM rendern“ ähnlich sind. (Diese nachfolgenden Änderungen werden hier nicht dargestellt.)

Fazit

Puh, das waren sehr viele Details. Wie Sie sehen, ist das Rendern in Chromium ziemlich kompliziert. Es kann eine Menge Zeit dauern, sich alle Bestandteile zu merken und zu verinnerlichen. Machen Sie sich also keine Sorgen, wenn es überwältigend erscheint.

Die wichtigste Erkenntnis ist, dass es eine konzeptionell einfache Rendering-Pipeline gibt, die durch sorgfältige Modularisierung und Liebe zum Detail in mehrere in sich geschlossene Komponenten aufgeteilt wurde. Diese Komponenten wurden dann auf parallele Prozesse und Threads aufgeteilt, um die Möglichkeiten der skalierbaren Leistung und der Erweiterbarkeit zu maximieren.

Jede dieser Komponenten spielt eine wichtige Rolle bei der optimalen Leistung und allen Funktionen, die moderne Webanwendungen benötigen. Bald werden wir einen detaillierten Einblick in diese Tools und ihre wichtigen Rollen veröffentlichen.

Vorher erkläre ich jedoch noch, warum die in diesem Beitrag genannten wichtigen Datenstrukturen (die an den Seiten des Renderingpipelinediagramms blau markiert sind) für RenderingNG genauso wichtig sind wie Codekomponenten.

Vielen Dank für Ihr Interesse.

Illustrationen von Una Kravets.