Hier vindt u hoe de componentonderdelen van RenderingNG zijn opgezet en hoe de renderingpijplijn er doorheen stroomt.
Beginnend op het hoogste niveau zijn de taken van het renderen:
- Render inhoud in pixels op het scherm.
- Animeer visuele effecten op de inhoud van de ene staat naar de andere.
- Scroll als reactie op invoer.
- Leid invoer efficiënt naar de juiste plaatsen, zodat ontwikkelaarsscripts en andere subsystemen kunnen reageren.
De inhoud die moet worden weergegeven, bestaat uit een boom met frames voor elk browsertabblad, plus de browserinterface. En een stroom ruwe invoergebeurtenissen van aanraakschermen, muizen, toetsenborden en andere hardwareapparaten.
Elk frame bevat:
- DOM-staat
- CSS
- Doeken
- Externe bronnen, zoals afbeeldingen, video, lettertypen en SVG
Een frame is een HTML-document, plus de URL ervan. Een webpagina die op een browsertabblad wordt geladen, heeft een frame op het hoogste niveau, onderliggende frames voor elk iframe dat is opgenomen in het document op het hoogste niveau, en hun recursieve iframe-afstammelingen.
Een visueel effect is een grafische bewerking die op een bitmap wordt toegepast, zoals scrollen, transformeren, knippen, filteren, dekking of overvloeien.
Architectuurcomponenten
In RenderingNG zijn deze taken logisch verdeeld over verschillende fasen en codecomponenten. De componenten komen terecht in verschillende CPU-processen, threads en subcomponenten binnen die threads. Ze spelen allemaal een belangrijke rol bij het bereiken van betrouwbaarheid , schaalbare prestaties en uitbreidbaarheid voor alle webinhoud.
Pijpleidingstructuur renderen

Het renderen verloopt in een pijplijn, waarbij onderweg een aantal fasen en artefacten worden gecreëerd. Elke fase vertegenwoordigt code die één goed gedefinieerde taak binnen het renderen uitvoert. De artefacten zijn datastructuren die input of output zijn van de fasen.
De fasen zijn:
- Animeren: verander berekende stijlen en muteer eigendomsbomen in de loop van de tijd op basis van declaratieve tijdlijnen.
- Stijl: pas CSS toe op de DOM en maak berekende stijlen .
- Lay-out: bepaal de grootte en positie van DOM-elementen op het scherm en creëer de onveranderlijke fragmentboom .
- Voorschilderen: bereken eigenschappenbomen en maak eventuele bestaande weergavelijsten en GPU- textuurtegels ongeldig.
- Scrollen: update de scroll-offset van documenten en scrollbare DOM-elementen door eigenschappenbomen te muteren.
- Verf: bereken een weergavelijst die beschrijft hoe GPU-textuurtegels vanuit de DOM moeten worden gerasterd.
- Commit: kopieer eigenschappenbomen en de weergavelijst naar de compositor-thread.
- Gelaagd maken: deel de weergavelijst op in een samengestelde lagenlijst voor onafhankelijke rastering en animatie.
- Raster-, decodeer- en verfwerkjes: zet respectievelijk weergavelijsten, gecodeerde afbeeldingen en verfwerkletcode om in GPU-textuurtegels .
- Activeren: maak een compositorframe dat weergeeft hoe GPU-tegels op het scherm moeten worden getekend en gepositioneerd, samen met eventuele visuele effecten.
- Aggregeren: combineer compositorframes van alle zichtbare compositorframes in één enkel, globaal compositorframe.
- Tekenen: voer het geaggregeerde compositorframe uit op de GPU om pixels op het scherm te creëren.
Fasen van de weergavepijplijn kunnen worden overgeslagen als ze niet nodig zijn. Animaties van visuele effecten en scrollen kunnen bijvoorbeeld de lay-out, pre-paint en paint overslaan. Daarom zijn animatie en scrollen in het diagram gemarkeerd met gele en groene stippen. Als layout, pre-paint en paint kunnen worden overgeslagen voor visuele effecten, kunnen ze volledig op de compositor-thread worden uitgevoerd en de hoofdthread worden overgeslagen.
De weergave van de browser-UI wordt hier niet direct weergegeven, maar kan worden gezien als een vereenvoudigde versie van dezelfde pijplijn (en in feite deelt de implementatie ervan een groot deel van de code). Video (ook niet direct afgebeeld) wordt over het algemeen weergegeven met onafhankelijke code die frames decodeert in GPU-textuurtegels die vervolgens worden aangesloten op compositorframes en de tekenstap.
Proces- en draadstructuur
CPU-processen
Het gebruik van meerdere CPU-processen zorgt voor prestatie- en beveiligingsisolatie tussen sites en van de browserstatus, en stabiliteit en beveiligingsisolatie van GPU-hardware.
- Het weergaveproces rendert, animeert, scrollt en routeert invoer voor een enkele combinatie van site en tabblad. Er zijn verschillende renderprocessen.
- Het browserproces rendert, animeert en routeert invoer voor de gebruikersinterface van de browser (inclusief de adresbalk, tabbladtitels en pictogrammen), en stuurt alle resterende invoer door naar het juiste weergaveproces. Er is één browserproces.
- Het Viz-proces verzamelt composities van meerdere weergaveprocessen plus het browserproces. Het rastert en tekent met behulp van de GPU. Er is één Viz-proces.
Verschillende sites eindigen altijd in verschillende weergaveprocessen.
Meerdere browsertabbladen of vensters van dezelfde site gebruiken doorgaans verschillende weergaveprocessen, tenzij de tabbladen gerelateerd zijn, zoals de ene die de andere opent . Onder sterke geheugendruk op de desktop kan Chromium meerdere tabbladen van dezelfde site in hetzelfde weergaveproces plaatsen, zelfs als ze niet gerelateerd zijn.
Binnen één browsertabblad bevinden frames van verschillende sites zich altijd in verschillende weergaveprocessen, maar frames van dezelfde site bevinden zich altijd in hetzelfde weergaveproces. Vanuit het perspectief van weergave is het belangrijke voordeel van meerdere weergaveprocessen dat cross-site iframes en tabbladen prestatie-isolatie van elkaar bereiken. Bovendien kunnen origines kiezen voor nog meer isolatie .
Er is precies één Viz-proces voor heel Chromium, omdat er meestal maar één GPU en scherm is om naar toe te tekenen.
Het scheiden van Viz in zijn eigen proces is goed voor de stabiliteit in het geval van bugs in GPU-stuurprogramma's of hardware. Het is ook goed voor beveiligingsisolatie, wat belangrijk is voor GPU-API's zoals Vulkan en beveiliging in het algemeen .
Omdat de browser veel tabbladen en vensters kan hebben, en ze allemaal browser-UI-pixels hebben om te tekenen, vraag je je misschien af: waarom is er precies één browserproces? De reden is dat slechts één van hen tegelijk gefocust is; in feite zijn niet-zichtbare browsertabbladen meestal gedeactiveerd en wordt al hun GPU-geheugen verwijderd. Complexe browser-UI-renderingfuncties worden echter ook steeds vaker geïmplementeerd in renderprocessen (bekend als WebUI ). Dit is niet om redenen van prestatie-isolatie, maar om te profiteren van het gebruiksgemak van de webweergave-engine van Chromium.
Op oudere Android-apparaten worden het weergave- en browserproces gedeeld bij gebruik in een WebView (dit geldt niet voor Chromium op Android in het algemeen, alleen voor WebView). Op WebView wordt het browserproces ook gedeeld met de insluitingsapp, en WebView heeft slechts één weergaveproces.
Er is soms ook een hulpprogramma voor het decoderen van beveiligde video-inhoud. Dit proces is niet weergegeven in de voorgaande diagrammen.
Draden
Threads helpen prestatie-isolatie en reactievermogen te bereiken, ondanks langzame taken, parallellisatie van pijplijnen en meervoudige buffering.
- De rode draad voert scripts uit, de rendering-gebeurtenislus, de documentlevenscyclus, hittests, verzending van scriptgebeurtenissen en het parseren van HTML, CSS en andere gegevensformaten.
- Hoofdthreadhelpers voeren taken uit zoals het maken van afbeeldingsbitmaps en blobs waarvoor codering of decodering vereist is.
- Web Workers voeren een script uit en een rendering-gebeurtenislus voor OffscreenCanvas.
- De Compositor-thread verwerkt invoergebeurtenissen, voert scrollen en animaties van webinhoud uit, berekent de optimale gelaagdheid van webinhoud en coördineert beelddecodering, verfwerkjes en rastertaken.
- Compositor-threadhelpers coördineren Viz-rastertaken en voeren afbeeldingsdecoderingstaken uit, verfworklets en fallback-raster.
- Media-, demuxer- of audio-uitvoerthreads decoderen, verwerken en synchroniseren video- en audiostreams. (Houd er rekening mee dat video parallel wordt uitgevoerd met de hoofdrenderingpijplijn.)
Het scheiden van de hoofdthreads en de compositorthreads is van cruciaal belang voor de prestatie-isolatie van animatie en scrollen van hoofdthreadwerk.
Er is slechts één rode draad per weergaveproces, ook al kunnen meerdere tabbladen of frames van dezelfde site in hetzelfde proces terechtkomen. Er is echter prestatie-isolatie van werk dat wordt uitgevoerd in verschillende browser-API's. Het genereren van afbeeldingsbitmaps en blobs in de Canvas API wordt bijvoorbeeld uitgevoerd in een hoofdthread-helperthread.
Op dezelfde manier is er slechts één compositor-thread per weergaveproces. Het is over het algemeen geen probleem dat er maar één is, omdat alle erg dure bewerkingen op de compositor-thread worden gedelegeerd naar de compositor-werkthreads of het Viz-proces, en dit werk kan parallel worden gedaan met invoerroutering, scrollen of animatie. Compositor-werkthreads coördineren de taken die in het Viz-proces worden uitgevoerd, maar GPU-versnelling kan overal mislukken om redenen buiten de controle van Chromium, zoals bugs in stuurprogramma's. In deze situaties zal de werkthread het werk doen in een fallback-modus op de CPU.
Het aantal compositor-werkthreads is afhankelijk van de mogelijkheden van het apparaat. Desktops zullen bijvoorbeeld over het algemeen meer threads gebruiken, omdat ze meer CPU-kernen hebben en minder batterijbelast zijn dan mobiele apparaten. Dit is een voorbeeld van opschalen en afschalen .
De threading-architectuur van het renderproces is een toepassing van drie verschillende optimalisatiepatronen:
- Hulpthreads : stuur langlopende subtaken naar extra threads om de bovenliggende thread te laten reageren op andere, gelijktijdige verzoeken. De hoofdthreadhelper- en compositorhelperthreads zijn goede voorbeelden van deze techniek.
- Meervoudige buffering : toon eerder gerenderde inhoud tijdens het renderen van nieuwe inhoud, om de latentie van het renderen te verbergen. De compositor-thread gebruikt deze techniek.
- Parallellisatie van pijpleidingen: voer de weergavepijplijn op meerdere plaatsen tegelijk uit. Dit is hoe scrollen en animatie snel kunnen zijn; zelfs als er een update voor de weergave van de hoofdthread plaatsvindt, kunnen scrollen en animatie parallel worden uitgevoerd.
Browserproces
- De render- en compositingthread reageert op invoer in de gebruikersinterface van de browser en leidt andere invoer naar het juiste weergaveproces; lay-out en schildert de browser-UI.
- De render- en compositing-thread-helpers voeren afbeeldingsdecoderingstaken uit en fallback-raster of decodering.
De render- en compositingthread van het browserproces zijn vergelijkbaar met de code en functionaliteit van een renderproces, behalve dat de hoofdthread en de compositorthread in één zijn gecombineerd. Er is in dit geval slechts één thread nodig omdat er geen behoefte is aan prestatie-isolatie van lange hoofdthreadtaken, aangezien deze er niet zijn door het ontwerp.
Zie proces
- De GPU-hoofdthreadrasters geven lijsten en videoframes weer in GPU-textuurtegels, en tekenen compositorframes naar het scherm.
- De display-compositor-thread verzamelt en optimaliseert de compositie van elk weergaveproces, plus het browserproces, in een enkel compositor-frame voor presentatie op het scherm.
Raster en draw gebeuren over het algemeen op dezelfde thread, omdat ze allebei afhankelijk zijn van GPU-bronnen, en het moeilijk is om op betrouwbare wijze multi-threaded gebruik te maken van de GPU (gemakkelijkere multi-threaded toegang tot de GPU is één motivatie voor het ontwikkelen van de nieuwe Vulkan- standaard). Op Android WebView is er een aparte renderthread op besturingssysteemniveau voor tekenen, vanwege de manier waarop WebViews zijn ingebed in een native app. Andere platforms zullen in de toekomst waarschijnlijk zo'n draad hebben.
De weergavecompositor bevindt zich op een andere thread omdat deze te allen tijde moet reageren en geen enkele mogelijke bron van vertraging op de GPU-hoofdthread mag blokkeren. Eén oorzaak van de vertraging van de GPU-hoofdthread zijn oproepen naar niet-Chromium-code, zoals leverancierspecifieke GPU-stuurprogramma's, die op moeilijk te voorspellen manieren traag kunnen zijn.
Componentenstructuur
Binnen elke hoofd- of compositor-thread van het weergaveproces zijn er logische softwarecomponenten die op gestructureerde manieren met elkaar communiceren.
Render de hoofdthreadcomponenten van het proces
In de Blink-renderer:
- Het lokale frameboomfragment vertegenwoordigt de boom van lokale frames en de DOM binnen frames.
- De component DOM en Canvas API's bevat implementaties van al deze API's.
- De documentlevenscyclusloper voert de renderingpijplijnstappen uit tot en met de commit-stap.
- De component voor het testen en verzenden van invoergebeurtenissen voert hittests uit om erachter te komen welk DOM-element het doelwit is van een gebeurtenis, en voert de algoritmen voor het verzenden van invoergebeurtenissen en het standaardgedrag uit.
De planner en runner van de renderende gebeurtenislus beslissen wat er op de gebeurtenislus moet worden uitgevoerd en wanneer. Het plant de weergave in een ritme dat overeenkomt met de weergave van het apparaat.
Lokale frameboomfragmenten zijn een beetje ingewikkeld. Bedenk dat een frameboom de hoofdpagina en de onderliggende iframes is, recursief. Een frame is lokaal voor een weergaveproces als het in dat proces wordt weergegeven, en anders bevindt het zich op afstand.
U kunt zich voorstellen dat u frames kleurt op basis van hun weergaveproces. In de voorgaande afbeelding zijn de groene cirkels allemaal frames in één weergaveproces; de oranje zijn in een seconde, en de blauwe in een derde.
Een lokaal frameboomfragment is een verbonden component van dezelfde kleur in een frameboom. Er zijn vier lokale framebomen in de afbeelding: twee voor site A, één voor site B en één voor site C. Elke lokale frameboom krijgt zijn eigen Blink-renderercomponent. De Blink-renderer van een lokale frameboom bevindt zich mogelijk niet in hetzelfde renderproces als andere lokale framebomen. Het wordt bepaald door de manier waarop weergaveprocessen worden geselecteerd, zoals eerder beschreven.
Geef de threadstructuur van de procescompositor weer
De componenten van de renderprocescompositor omvatten:
- Een gegevenshandler die een samengestelde lagenlijst, weergavelijsten en eigenschappenbomen bijhoudt.
- Een levenscyclusloper die de animatie-, scroll-, composiet-, raster- en decoderings- en activeringsstappen van de weergavepijplijn uitvoert. (Houd er rekening mee dat animeren en scrollen zowel in de hoofdthread als in de compositor kunnen voorkomen.)
- Een invoer- en hittesthandler voert invoerverwerking en hittests uit met de resolutie van samengestelde lagen, om te bepalen of scrollbewegingen kunnen worden uitgevoerd op de compositorthread, en op welke renderproceshittests zich moeten richten.
Voorbeeldarchitectuur in de praktijk
In dit voorbeeld zijn er drie tabbladen:
Tabblad 1: foo.com
<html>
<iframe id=one src="foo.com/other-url"></iframe>
<iframe id=two src="bar.com"></iframe>
</html>
Tabblad 2: bar.com
<html>
…
</html>
Tab 3: baz.com html <html> … </html>
De proces-, thread- en componentenstructuur voor deze tabbladen zien er als volgt uit:
Laten we elk van de vier hoofdtaken van weergave met één voorbeeld bekijken. Een herinnering:
- Render inhoud in pixels op het scherm.
- Animeer visuele effecten op de inhoud van de ene staat naar de andere.
- Scroll als reactie op invoer.
- Leid invoer efficiënt naar de juiste plaatsen, zodat ontwikkelaarsscripts en andere subsystemen kunnen reageren.
Om de gewijzigde DOM voor tabblad één weer te geven :
- Een ontwikkelaarsscript verandert de DOM in het weergaveproces voor foo.com.
- De Blink-renderer vertelt de compositor dat er een render nodig is.
- De compositor vertelt Viz dat er een render nodig is.
- Viz signaleert het begin van de render terug naar de compositor.
- De compositor stuurt het startsignaal door naar de Blink-renderer.
- De hoofdthreadgebeurtenislooprunner voert de levenscyclus van het document uit.
- De hoofdthread verzendt het resultaat naar de compositorthread.
- De compositor-gebeurtenislooprunner voert de compositing-levenscyclus uit.
- Alle rastertaken worden voor raster naar Viz verzonden (er zijn vaak meer dan één van deze taken).
- Viz rastert inhoud op de GPU.
- Viz bevestigt voltooiing van de rastertaak. Opmerking: Chromium wacht vaak niet tot het raster is voltooid, maar gebruikt in plaats daarvan iets dat een synchronisatietoken wordt genoemd en dat moet worden opgelost door rastertaken voordat stap 15 wordt uitgevoerd.
- Er wordt een compositorframe naar Viz gestuurd.
- Viz verzamelt de compositorframes voor het foo.com-weergaveproces, het bar.com iframe-weergaveproces en de browsergebruikersinterface.
- Viz plant een gelijkspel.
- Viz tekent het geaggregeerde compositorframe naar het scherm.
Een CSS-transformatieovergang op tabblad twee animeren :
- De compositor-thread voor het bar.com-weergaveproces tikt een animatie aan in de compositor-gebeurtenislus door de bestaande eigenschappenbomen te muteren. Hierdoor wordt de levenscyclus van de compositor opnieuw uitgevoerd. (Raster- en decodeertaken kunnen voorkomen, maar worden hier niet weergegeven.)
- Er wordt een compositorframe naar Viz gestuurd.
- Viz verzamelt de compositorframes voor het foo.com-weergaveproces, het bar.com-weergaveproces en de browsergebruikersinterface.
- Viz plant een gelijkspel.
- Viz tekent het geaggregeerde compositorframe naar het scherm.
Om door de webpagina te scrollen op tabblad drie:
- Een reeks
input
(muis, aanraking of toetsenbord) komt naar het browserproces. - Elke gebeurtenis wordt doorgestuurd naar de renderprocescompositorthread van baz.com.
- De compositor bepaalt of de hoofdthread op de hoogte moet zijn van de gebeurtenis.
- De gebeurtenis wordt indien nodig naar de hoofdthread verzonden.
- De hoofdthread vuurt luisteraars
input
af (pointerdown
,touchstar
,pointermove
,touchmove
ofwheel
) om te zien of luisteraarspreventDefault
voor de gebeurtenis zullen aanroepen. - De hoofdthread retourneert of
preventDefault
naar de compositor is aangeroepen. - Als dit niet het geval is, wordt de invoergebeurtenis teruggestuurd naar het browserproces.
- Het browserproces converteert het naar een scrollgebaar door het te combineren met andere recente gebeurtenissen.
- Het scrollgebaar wordt nogmaals naar de renderprocescompositorthread van baz.com gestuurd,
- De scroll wordt daar toegepast en de compositor-thread voor het bar.com-weergaveproces tikt een animatie aan in de compositor-gebeurtenislus. Hierdoor wordt de scroll-offset in de eigenschappenbomen gemuteerd en wordt de levenscyclus van de compositor opnieuw uitgevoerd. Het vertelt de hoofdthread ook om een
scroll
af te vuren (hier niet afgebeeld). - Er wordt een compositorframe naar Viz gestuurd.
- Viz verzamelt de compositorframes voor het foo.com-weergaveproces, het bar.com-weergaveproces en de browsergebruikersinterface.
- Viz plant een gelijkspel.
- Viz tekent het geaggregeerde compositorframe naar het scherm.
Een click
routeren naar een hyperlink in iframe #twee op tabblad één:
- Er komt een
input
(muis, aanraking of toetsenbord) naar het browserproces. Het voert een geschatte hittest uit om te bepalen of het iframe-weergaveproces van bar.com de klik moet ontvangen en deze daarheen stuurt. - De compositor-thread voor bar.com stuurt de
click
naar de hoofdthread voor bar.com en plant een rendering-gebeurtenislustaak om deze te verwerken. - De invoergebeurtenisprocessor voor de hoofdthreadhittests van bar.com om te bepalen op welk DOM-element in het iframe is geklikt, en vuurt een
click
af zodat scripts deze kunnen observeren. Als u geenpreventDefault
hoort, navigeert het naar de hyperlink. - Bij het laden van de bestemmingspagina van de hyperlink wordt de nieuwe status weergegeven, met stappen die vergelijkbaar zijn met het vorige voorbeeld "geef gewijzigde DOM weer". (Deze daaropvolgende wijzigingen worden hier niet weergegeven.)
Afhaalmaaltijden
Het kan veel tijd kosten om te onthouden en te internaliseren hoe weergave werkt.
De belangrijkste conclusie is dat de renderingpijplijn, door middel van zorgvuldige modularisering en aandacht voor detail, is opgesplitst in een aantal op zichzelf staande componenten. Deze componenten zijn vervolgens verdeeld over parallelle processen en threads om de schaalbare prestaties en uitbreidbaarheidsmogelijkheden te maximaliseren.
Elke component speelt een cruciale rol bij het mogelijk maken van de prestaties en functies van moderne webapps.
Blijf lezen over de belangrijkste datastructuren , die net zo belangrijk zijn voor RenderingNG als codecomponenten.
Illustraties door Una Kravets.
,Hier vindt u hoe de componentonderdelen van RenderingNG zijn opgezet en hoe de renderingpijplijn er doorheen stroomt.
Beginnend op het hoogste niveau zijn de taken van het renderen:
- Render inhoud in pixels op het scherm.
- Animeer visuele effecten op de inhoud van de ene staat naar de andere.
- Scroll als reactie op invoer.
- Leid invoer efficiënt naar de juiste plaatsen, zodat ontwikkelaarsscripts en andere subsystemen kunnen reageren.
De inhoud die moet worden weergegeven, bestaat uit een boom met frames voor elk browsertabblad, plus de browserinterface. En een stroom ruwe invoergebeurtenissen van aanraakschermen, muizen, toetsenborden en andere hardwareapparaten.
Elk frame bevat:
- DOM-staat
- CSS
- Doeken
- Externe bronnen, zoals afbeeldingen, video, lettertypen en SVG
Een frame is een HTML-document, plus de URL ervan. Een webpagina die op een browsertabblad wordt geladen, heeft een frame op het hoogste niveau, onderliggende frames voor elk iframe dat is opgenomen in het document op het hoogste niveau, en hun recursieve iframe-afstammelingen.
Een visueel effect is een grafische bewerking die op een bitmap wordt toegepast, zoals scrollen, transformeren, knippen, filteren, dekking of overvloeien.
Architectuurcomponenten
In RenderingNG zijn deze taken logisch verdeeld over verschillende fasen en codecomponenten. De componenten komen terecht in verschillende CPU-processen, threads en subcomponenten binnen die threads. Ze spelen allemaal een belangrijke rol bij het bereiken van betrouwbaarheid , schaalbare prestaties en uitbreidbaarheid voor alle webinhoud.
Pijpleidingstructuur renderen

Het renderen verloopt in een pijplijn, waarbij onderweg een aantal fasen en artefacten worden gecreëerd. Elke fase vertegenwoordigt code die één goed gedefinieerde taak binnen het renderen uitvoert. De artefacten zijn datastructuren die input of output zijn van de fasen.
De fasen zijn:
- Animeren: verander berekende stijlen en muteer eigendomsbomen in de loop van de tijd op basis van declaratieve tijdlijnen.
- Stijl: pas CSS toe op de DOM en maak berekende stijlen .
- Lay-out: bepaal de grootte en positie van DOM-elementen op het scherm en creëer de onveranderlijke fragmentboom .
- Voorschilderen: bereken eigenschappenbomen en maak eventuele bestaande weergavelijsten en GPU- textuurtegels ongeldig.
- Scrollen: update de scroll-offset van documenten en scrollbare DOM-elementen door eigenschappenbomen te muteren.
- Verf: bereken een weergavelijst die beschrijft hoe GPU-textuurtegels vanuit de DOM moeten worden gerasterd.
- Commit: kopieer eigenschappenbomen en de weergavelijst naar de compositor-thread.
- Gelaagd maken: deel de weergavelijst op in een samengestelde lagenlijst voor onafhankelijke rastering en animatie.
- Raster-, decodeer- en verfwerkjes: zet respectievelijk weergavelijsten, gecodeerde afbeeldingen en verfwerkletcode om in GPU-textuurtegels .
- Activeren: maak een compositorframe dat weergeeft hoe GPU-tegels op het scherm moeten worden getekend en gepositioneerd, samen met eventuele visuele effecten.
- Aggregeren: combineer compositorframes van alle zichtbare compositorframes in één enkel, globaal compositorframe.
- Tekenen: voer het geaggregeerde compositorframe uit op de GPU om pixels op het scherm te creëren.
Fasen van de weergavepijplijn kunnen worden overgeslagen als ze niet nodig zijn. Animaties van visuele effecten en scrollen kunnen bijvoorbeeld de lay-out, pre-paint en paint overslaan. Daarom zijn animatie en scrollen in het diagram gemarkeerd met gele en groene stippen. Als layout, pre-paint en paint kunnen worden overgeslagen voor visuele effecten, kunnen ze volledig op de compositor-thread worden uitgevoerd en de hoofdthread worden overgeslagen.
De weergave van de browser-UI wordt hier niet direct weergegeven, maar kan worden gezien als een vereenvoudigde versie van dezelfde pijplijn (en in feite deelt de implementatie ervan een groot deel van de code). Video (ook niet direct afgebeeld) wordt over het algemeen weergegeven met onafhankelijke code die frames decodeert in GPU-textuurtegels die vervolgens worden aangesloten op compositorframes en de tekenstap.
Proces- en draadstructuur
CPU-processen
Het gebruik van meerdere CPU-processen zorgt voor prestatie- en beveiligingsisolatie tussen sites en van de browserstatus, en stabiliteit en beveiligingsisolatie van GPU-hardware.
- Het weergaveproces rendert, animeert, scrollt en routeert invoer voor een enkele combinatie van site en tabblad. Er zijn verschillende renderprocessen.
- Het browserproces rendert, animeert en routeert invoer voor de gebruikersinterface van de browser (inclusief de adresbalk, tabbladtitels en pictogrammen), en stuurt alle resterende invoer door naar het juiste weergaveproces. Er is één browserproces.
- Het Viz-proces verzamelt composities van meerdere weergaveprocessen plus het browserproces. Het rastert en tekent met behulp van de GPU. Er is één Viz-proces.
Verschillende sites eindigen altijd in verschillende weergaveprocessen.
Meerdere browsertabbladen of vensters van dezelfde site gebruiken doorgaans verschillende weergaveprocessen, tenzij de tabbladen gerelateerd zijn, zoals de ene die de andere opent . Onder sterke geheugendruk op de desktop kan Chromium meerdere tabbladen van dezelfde site in hetzelfde weergaveproces plaatsen, zelfs als ze niet gerelateerd zijn.
Binnen één browsertabblad bevinden frames van verschillende sites zich altijd in verschillende weergaveprocessen, maar frames van dezelfde site bevinden zich altijd in hetzelfde weergaveproces. Vanuit het perspectief van weergave is het belangrijke voordeel van meerdere weergaveprocessen dat cross-site iframes en tabbladen prestatie-isolatie van elkaar bereiken. Bovendien kunnen origines kiezen voor nog meer isolatie .
Er is precies één Viz-proces voor heel Chromium, omdat er meestal maar één GPU en scherm is om naar toe te tekenen.
Het scheiden van Viz in zijn eigen proces is goed voor de stabiliteit in het geval van bugs in GPU-stuurprogramma's of hardware. Het is ook goed voor beveiligingsisolatie, wat belangrijk is voor GPU-API's zoals Vulkan en beveiliging in het algemeen .
Omdat de browser veel tabbladen en vensters kan hebben, en ze allemaal browser-UI-pixels hebben om te tekenen, vraag je je misschien af: waarom is er precies één browserproces? De reden is dat slechts één van hen tegelijk gefocust is; in feite zijn niet-zichtbare browsertabbladen meestal gedeactiveerd en wordt al hun GPU-geheugen verwijderd. Complexe browser-UI-renderingfuncties worden echter ook steeds vaker geïmplementeerd in renderprocessen (bekend als WebUI ). Dit is niet om redenen van prestatie-isolatie, maar om te profiteren van het gebruiksgemak van de webweergave-engine van Chromium.
Op oudere Android-apparaten worden het weergave- en browserproces gedeeld bij gebruik in een WebView (dit geldt niet voor Chromium op Android in het algemeen, alleen voor WebView). Op WebView wordt het browserproces ook gedeeld met de insluitingsapp, en WebView heeft slechts één weergaveproces.
Er is soms ook een hulpprogramma voor het decoderen van beveiligde video-inhoud. Dit proces is niet weergegeven in de voorgaande diagrammen.
Draden
Threads helpen prestatie-isolatie en reactievermogen te bereiken, ondanks langzame taken, parallellisatie van pijplijnen en meervoudige buffering.
- De rode draad voert scripts uit, de rendering-gebeurtenislus, de documentlevenscyclus, hittests, verzending van scriptgebeurtenissen en het parseren van HTML, CSS en andere gegevensformaten.
- Hoofdthreadhelpers voeren taken uit zoals het maken van afbeeldingsbitmaps en blobs waarvoor codering of decodering vereist is.
- Web Workers voeren een script uit en een rendering-gebeurtenislus voor OffscreenCanvas.
- De Compositor-thread verwerkt invoergebeurtenissen, voert scrollen en animaties van webinhoud uit, berekent de optimale gelaagdheid van webinhoud en coördineert beelddecodering, verfwerkjes en rastertaken.
- Compositor-threadhelpers coördineren Viz-rastertaken en voeren afbeeldingsdecoderingstaken uit, verfworklets en fallback-raster.
- Media-, demuxer- of audio-uitvoerthreads decoderen, verwerken en synchroniseren video- en audiostreams. (Houd er rekening mee dat video parallel wordt uitgevoerd met de hoofdrenderingpijplijn.)
Het scheiden van de hoofdthreads en de compositorthreads is van cruciaal belang voor de prestatie-isolatie van animatie en scrollen van hoofdthreadwerk.
Er is slechts één rode draad per weergaveproces, ook al kunnen meerdere tabbladen of frames van dezelfde site in hetzelfde proces terechtkomen. Er is echter prestatie-isolatie van werk dat wordt uitgevoerd in verschillende browser-API's. Het genereren van afbeeldingsbitmaps en blobs in de Canvas API wordt bijvoorbeeld uitgevoerd in een hoofdthread-helperthread.
Op dezelfde manier is er slechts één compositor-thread per weergaveproces. Het is over het algemeen geen probleem dat er maar één is, omdat alle erg dure bewerkingen op de compositor-thread worden gedelegeerd naar de compositor-werkthreads of het Viz-proces, en dit werk kan parallel worden gedaan met invoerroutering, scrollen of animatie. Compositor-werkthreads coördineren de taken die in het Viz-proces worden uitgevoerd, maar GPU-versnelling kan overal mislukken om redenen buiten de controle van Chromium, zoals bugs in stuurprogramma's. In deze situaties zal de werkthread het werk doen in een fallback-modus op de CPU.
Het aantal compositor-werkthreads is afhankelijk van de mogelijkheden van het apparaat. Desktops zullen bijvoorbeeld over het algemeen meer threads gebruiken, omdat ze meer CPU-kernen hebben en minder batterijbelast zijn dan mobiele apparaten. Dit is een voorbeeld van opschalen en afschalen .
De threading-architectuur van het renderproces is een toepassing van drie verschillende optimalisatiepatronen:
- Hulpthreads : stuur langlopende subtaken naar extra threads om de bovenliggende thread te laten reageren op andere, gelijktijdige verzoeken. De hoofdthreadhelper- en compositorhelperthreads zijn goede voorbeelden van deze techniek.
- Meervoudige buffering : toon eerder gerenderde inhoud tijdens het renderen van nieuwe inhoud, om de latentie van het renderen te verbergen. De compositor-thread gebruikt deze techniek.
- Parallellisatie van pijpleidingen: voer de weergavepijplijn op meerdere plaatsen tegelijk uit. Dit is hoe scrollen en animatie snel kunnen zijn; zelfs als er een update voor de weergave van de hoofdthread plaatsvindt, kunnen scrollen en animatie parallel worden uitgevoerd.
Browserproces
- De render- en compositingthread reageert op invoer in de gebruikersinterface van de browser en leidt andere invoer naar het juiste weergaveproces; lay-out en schildert de browser-UI.
- De render- en compositing-thread-helpers voeren afbeeldingsdecoderingstaken uit en fallback-raster of decodering.
De render- en compositingthread van het browserproces zijn vergelijkbaar met de code en functionaliteit van een renderproces, behalve dat de hoofdthread en de compositorthread in één zijn gecombineerd. Er is in dit geval slechts één thread nodig omdat er geen behoefte is aan prestatie-isolatie van lange hoofdthreadtaken, aangezien deze er niet zijn door het ontwerp.
Zie proces
- De GPU -hoofdthread rasters weergeven lijsten en videoframes in GPU -textuurtegels en trekt compositorframes naar het scherm.
- De Display Compositor -thread aggregeert en optimaliseert compositing van elk renderproces, plus het browserproces, in een enkel compositor -frame voor presentatie naar het scherm.
Raster en gelijkspel gebeuren over het algemeen op dezelfde thread, omdat beide afhankelijk zijn van GPU-bronnen, en het is moeilijk om betrouwbaar multi-threaded gebruik van de GPU te maken (gemakkelijkere multi-threaded toegang tot de GPU is een motivatie voor het ontwikkelen van de nieuwe Vulkan- standaard). Op Android WebView is er een afzonderlijke os-niveau render-thread voor tekenen vanwege hoe webviews zijn ingebed in een native app. Andere platforms zullen in de toekomst waarschijnlijk zo'n thread hebben.
De display -compositor bevindt zich in een andere thread omdat deze te allen tijde moet reageren en niet moet worden geblokkeerd op een mogelijke bron van vertraging op de GPU -hoofddraad. Een oorzaak van vertraging op de GPU-hoofdthread is oproepen tot niet-chromiumcode, zoals leverancierspecifieke GPU-stuurprogramma's, die op moeilijk te voorspellen traag kunnen zijn.
Componentstructuur
Binnen elke hoofd- of compositor -thread zijn er logische softwarecomponenten die op gestructureerde manieren met elkaar interageren.
Render Process Componenten van de hoofddraad
In de Blink Renderer:
- Het lokale frameboomfragment vertegenwoordigt de boom van lokale frames en de DOM binnen frames.
- De DOM- en Canvas APIS -component bevat implementaties van al deze API's.
- De Lifecycle Runner van het document voert de weergave van de weergave -pijplijn uit tot en met de commit -stap.
- De invoergebeurtenis -hittest- en verzendingscomponent voert hittests uit om erachter te komen welk DOM -element wordt gericht op een gebeurtenis en voert het invoergebeurtenis -verzendingsalgoritmen en standaardgedrag uit.
De Rendering Event Loop Scheduler en Runner beslist wat te draaien op de evenementenlus en wanneer. Het is gepland om weergegeven te gebeuren bij een cadans die overeenkomt met het apparaatdisplay.
Lokale frameboomfragmenten zijn een beetje ingewikkeld. Bedenk dat een frameboom de hoofdpagina en zijn kind is, recursief. Een frame is lokaal voor een renderproces als het in dat proces wordt weergegeven, en anders is het afgelegen.
Je kunt je voorstellen dat kleurplaten volgens hun renderproces. In het voorgaande beeld zijn de groene cirkels allemaal frames in één renderproces; De oranje zijn in een seconde en de blauwe is in een derde.
Een lokaal frameboomfragment is een verbonden onderdeel van dezelfde kleur in een frameboom. Er zijn vier lokale framebomen in de afbeelding: twee voor site A, één voor site B en één voor site C. Elke lokale frameboom krijgt zijn eigen knipperrenterercomponent. De Blink Renderer van een lokale kaderboom kan al dan niet in hetzelfde renderproces zijn als andere lokale frame -bomen. Het wordt bepaald door de manier waarop renderprocessen worden geselecteerd, zoals eerder beschreven.
Render Process Compositor threadstructuur
De componenten van de renderprocescompositor omvatten:
- Een data -handler die een gecomponeerde lagenlijst, weergavelijsten en eigenschapsbomen bijhoudt.
- Een levenscyclusloper die de animaat, scrol, samengesteld, raster en decodering en activeert stappen van de rendering -pijplijn uitvoert. (Vergeet niet dat Animate en Scroll kunnen optreden in zowel de hoofdthread als de compositor.)
- Een invoer- en hit -testhandler voert invoerverwerking uit en raakt testen bij de resolutie van samengestelde lagen, om te bepalen of scrolling -gebaren kunnen worden uitgevoerd op de compositor -thread, en op welk puntproces hit -tests moeten targeten.
Voorbeeld architectuur in de praktijk
In dit voorbeeld zijn er drie tabbladen:
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>
De proces-, thread- en componentstructuur voor deze tabbladen zien er als volgt uit:
Laten we door een voorbeeld lopen, elk van de vier hoofdtaken van rendering. Een herinnering:
- Render inhoud in pixels op het scherm.
- Animate visuele effecten op de inhoud van de ene toestand naar de andere.
- Scroll in reactie op invoer.
- Routevoer efficiënt naar de juiste plaatsen zodat ontwikkelaarscripts en andere subsystemen kunnen reageren.
Om de gewijzigde DOM voor Tab One weer te geven :
- Een ontwikkelaarscript verandert de DOM in het renderproces voor FOO.com.
- De Blink Renderer vertelt de compositor dat het een render moet optreden.
- De compositor vertelt namelijk dat het een weergave moet optreden.
- Viz signaleert het begin van de weergave terug naar de compositor.
- De compositor stuurt het startsignaal door naar de knipperrenterer.
- De hoofddraadsevenementlus Runner voert de Lifecycle van het document uit.
- De hoofdthread verzendt het resultaat naar de componistische thread.
- De Compositor Event Loop Runner voert de compositerende levenscyclus uit.
- Alle rastertaken worden verzonden naar Viz voor raster (er zijn vaak meer dan een van deze taken).
- Viz rasters content op de GPU.
- Viz erkent de voltooiing van de rastertaak. OPMERKING: Chroom wacht vaak niet tot het raster wordt voltooid en gebruikt in plaats daarvan iets dat een sync -token wordt genoemd dat moet worden opgelost door rastertaken voordat stap 15 wordt uitgevoerd.
- Een compositorframe wordt verzonden naar VIZ.
- Viz verzamelt de compositorframes voor het Foo.com Render -proces, het BAR.COM IFRAME RENDERPROCES en de browser UI.
- Viz plant een gelijkspel.
- Viz trekt het geaggregeerde compositorframe naar het scherm.
Om een CSS -transformatieovergang te animeren op Tab Twee:
- De Compositor -thread voor het BAR.COM -renderproces vinkt een animatie aan in zijn Compositor Event Loop door de bestaande eigenschapsbomen te muteren. Dit voert vervolgens de levenscyclus van de compositor opnieuw uit. (Raster en decoderen kan optreden, maar worden hier niet afgebeeld.)
- Een compositorframe wordt verzonden naar VIZ.
- Viz verzamelt de compositorframes voor het Foo.com Render Process, het Bar.com Render Process en de Browser UI.
- Viz plant een gelijkspel.
- Viz trekt het geaggregeerde compositorframe naar het scherm.
Om de webpagina op Tab drie te scrollen :
- Een reeks
input
(muis, aanraking of toetsenbord) komt naar het browserproces. - Elk evenement wordt gerouteerd naar Baz.com's Render Process Compositor Thread.
- De compositor bepaalt of de hoofdthread moet weten over het evenement.
- Het evenement wordt indien nodig naar de hoofdthread verzonden.
- De belangrijkste thread vuurt
input
-gebeurtenis luisteraars (pointerdown
,touchstar
,pointermove
,touchmove
ofwheel
) af om te zien of luisteraars voorkomen dat hij op het evenement wordtpreventDefault
. - De hoofdthread keert terug of
preventDefault
naar de compositor is geroepen. - Zo niet, wordt de invoergebeurtenis teruggestuurd naar het browserproces.
- Het browserproces converteert het naar een scroll -gebaar door het te combineren met andere recente gebeurtenissen.
- Het scroll -gebaar wordt opnieuw verzonden naar de scendercompositor -thread van Baz.com,
- De scroll wordt daar toegepast en de Compositor -thread voor het BAR.COM RENDER -proces tikt een animatie in zijn compositor -evenementenlus. Dit muteert vervolgens de scroll-offset in de eigenschapsbomen en voert de levenscyclus van de compositor opnieuw uit. Het vertelt ook de hoofdthread om een
scroll
-gebeurtenis af te vuren (hier niet afgebeeld). - Een compositorframe wordt verzonden naar VIZ.
- Viz verzamelt de compositorframes voor het Foo.com Render Process, het Bar.com Render Process en de Browser UI.
- Viz plant een gelijkspel.
- Viz trekt het geaggregeerde compositorframe naar het scherm.
Om een click
op een hyperlink in iframe #two op Tab One te routeren :
- Een
input
(muis, aanraking of toetsenbord) komt naar het browserproces. Het voert een geschatte hit -test uit om te bepalen dat het BAR.COM IFRAME -renderproces de klik moet ontvangen en het daar verzendt. - De Compositor -thread voor BAR.com routeert het
click
naar de hoofdthread voor Bar.com en plant een rendering -evenementenlustaak om deze te verwerken. - De invoergebeurtenisprocessor voor de hoofdtests van Bar.com om te bepalen op welk DOM -element in de IFRAME is geklikt en vuurt een
click
af voor scripts om te observeren. NopreventDefault
horen, het navigeert naar de hyperlink. - Na de lading van de bestemmingspagina van de hyperlink wordt de nieuwe status weergegeven, met stappen die vergelijkbaar zijn met de eerder voorbeeld van de "Render gewijzigd DOM". (Deze daaropvolgende wijzigingen worden hier niet weergegeven.)
Afhaalmaaltijden
Het kan veel tijd kosten om te onthouden en te internaliseren hoe rendering werkt.
De belangrijkste afhaalmaaltijd is dat de rendering pijplijn, door zorgvuldige modularisatie en aandacht voor detail, is opgesplitst in een aantal op zichzelf staande componenten. Deze componenten zijn vervolgens verdeeld over parallelle processen en threads om schaalbare prestaties en uitbreidbaarheidsmogelijkheden te maximaliseren.
Elk onderdeel speelt een cruciale rol bij het mogelijk maken van de prestaties en functies van moderne web -apps.
Blijf lezen over de belangrijkste gegevensstructuren , die net zo belangrijk zijn om als codecomponenten weer te geven.
Illustraties door Una Kravets.
,Hier zul je vinden hoe de componentstukken van RenderingNg zijn opgezet en hoe de rendering pijplijn erdoorheen stroomt.
Beginnend op het hoogste niveau, zijn de taken van rendering:
- Render inhoud in pixels op het scherm.
- Animate visuele effecten op de inhoud van de ene toestand naar de andere.
- Scroll in reactie op invoer.
- Routevoer efficiënt naar de juiste plaatsen zodat ontwikkelaarscripts en andere subsystemen kunnen reageren.
De inhoud om te renderen is een boom met frames voor elk tabblad brows, plus de browserinterface. En een stroom ruwe invoerevenementen van aanraakschermen, muizen, toetsenborden en andere hardware -apparaten.
Elk frame omvat:
- DOM -staat
- CSS
- Doeken
- Externe bronnen, zoals afbeeldingen, video, lettertypen en SVG
Een frame is een HTML -document, plus de URL. Een webpagina geladen in een browsertabblad heeft een frame op het hoogste niveau, onderliggende frames voor elk iframe dat is opgenomen in het document op het hoogste niveau en hun recursieve iframe-afstammelingen.
Een visueel effect is een grafische bewerking die wordt toegepast op een bitmap, zoals scroll, transformatie, clip, filter, dekking of blend.
Architectuurcomponenten
In renderingng zijn deze taken logisch gesplitst in verschillende fasen en codecomponenten. De componenten belanden in verschillende CPU-processen, threads en subcomponenten in die threads. Elk speelt een belangrijke rol bij het bereiken van betrouwbaarheid , schaalbare prestaties en uitbreidbaarheid voor alle webinhoud.
Pijplijnstructuur weergeven

Rendering in een pijplijn met een aantal fasen en artefacten die onderweg zijn gemaakt. Elke fase vertegenwoordigt code die één goed gedefinieerde taak doet binnen de rendering. De artefacten zijn gegevensstructuren die invoer of uitgangen van de fasen zijn.
De fasen zijn:
- ANIATIE: Verander berekende stijlen en muteer onroerend goed in de loop van de tijd op basis van declaratieve tijdlijnen.
- Stijl: Pas CSS toe op de DOM en maak berekende stijlen .
- Lay -out: bepaal de grootte en positie van DOM -elementen op het scherm en maak de onveranderlijke fragmentboom .
- Pre-Paint: Bereken van eigenschapsbomen en ongeldig alle bestaande displaylijsten en GPU- textuurtegels indien van toepassing.
- Scroll: update de scroll offset van documenten en schuifbare DOM -elementen, door onroerendgoedbomen te muteren.
- Verf: bereken een weergavelijst die beschrijft hoe GPU -textuurtegels van de DOM worden gerasterd.
- Commit: kopieer van eigenschapsbomen en de weergavelijst naar de compositor -thread.
- Layerize: Breek de weergavelijst op in een samengestelde laaglijst voor onafhankelijke rasterisatie en animatie.
- Raster-, decodeer- en verfwerkbanden: weergaveslijsten, gecodeerde afbeeldingen en respectievelijk verfworkletcode omdraaien in GPU -textuurtegels .
- Activeren: maak een compositor -frame dat vertegenwoordigt hoe GPU -tegels naar het scherm worden getrokken en positioneren, samen met eventuele visuele effecten.
- Aggregate: Combineer compositorframes uit alle zichtbare compositorframes in een enkel globaal compositor -frame.
- Draw: voer het geaggregeerde compositorframe uit op de GPU om pixels op het scherm te maken.
De fasen van de rendering -pijpleiding kunnen worden overgeslagen als ze niet nodig zijn. Animaties van visuele effecten en scroll kunnen bijvoorbeeld lay-out, pre-paint en verf overslaan. Dit is de reden waarom animatie en scroll zijn gemarkeerd met gele en groene stippen in het diagram. Als lay-out, pre-paint en verf kunnen worden overgeslagen voor visuele effecten, kunnen ze volledig worden uitgevoerd op de componistische draad en de hoofddraad overslaan.
Browser UI -weergave wordt hier niet direct weergegeven, maar kan worden beschouwd als een vereenvoudigde versie van dezelfde pijplijn (en in feite deelt de implementatie veel van de code). Video (ook niet direct afgebeeld) geeft in het algemeen weer met onafhankelijke code die frames decodeert in GPU -textuurtegels die vervolgens worden aangesloten op compositorframes en de trekkingsstap.
Proces- en threadstructuur
CPU -processen
Het gebruik van meerdere CPU -processen bereikt prestaties en beveiligingsisolatie tussen sites en van de browserstatus, en stabiliteit en beveiligingsisolatie van GPU -hardware.
- Het renderproces geeft, animeert, scrolls en routes input voor een enkele site- en tabcombinatie. Er zijn verschillende renderprocessen.
- Het browserproces geeft, animeert en routes input voor de browser -gebruikersinterface (inclusief de adresbalk, TAB -titels en pictogrammen), en routeert alle resterende invoer naar het juiste renderproces. Er is één browserproces.
- Het VIZ -proces aggregeert compositing van meerdere renderprocessen plus het browserproces. Het rasters en trekt met behulp van de GPU. Er is één viz -proces.
Verschillende sites belanden altijd in verschillende renderprocessen.
Meerdere browsertabs of vensters van dezelfde site gaan meestal in verschillende renderprocessen, tenzij de tabbladen gerelateerd zijn, zoals de ene die de andere openen . Onder sterke geheugendruk op desktopchroom kan chroom meerdere tabbladen van dezelfde site in hetzelfde renderproces plaatsen, zelfs als ze niet gerelateerd zijn.
Binnen een enkel tabblad met brows zijn frames van verschillende sites altijd in verschillende renderprocessen van elkaar, maar frames van dezelfde site zijn altijd in hetzelfde renderproces. Vanuit het perspectief van rendering is het belangrijke voordeel van meerdere renderprocessen dat cross-site IFRAMES en tabbladen prestatie-isolatie van elkaar bereiken. Bovendien kan Origins kiezen voor nog meer isolatie .
Er is precies één viz -proces voor heel chroom, omdat er meestal slechts één GPU en scherm is om mee te tekenen.
Het scheiden van viz in zijn eigen proces is goed voor stabiliteit in het licht van bugs in GPU -stuurprogramma's of hardware. Het is ook goed voor beveiligingsisolatie, wat belangrijk is voor GPU API's zoals Vulkan en Security in het algemeen .
Omdat de browser veel tabbladen en ramen kan hebben, en ze allemaal browser -UI -pixels hebben om te tekenen, vraag je je misschien af: waarom er precies één browserproces is? De reden is dat slechts één van hen tegelijk is gericht; In feite zijn niet-zichtbare browsertabs meestal gedeactiveerd en laten ze al hun GPU-geheugen vallen. Complexe browser UI -weergave -functies worden echter in toenemende mate geïmplementeerd in renderprocessen (bekend als WebUI ). Dit is niet om redenen van de prestatie, maar om te profiteren van het gebruiksgemak van de Web Rendering -engine van Chromium.
Op oudere Android -apparaten worden het render- en browserproces gedeeld bij gebruik in een WebView (dit is niet van toepassing op chroom op Android in het algemeen, alleen WebView). Op WebView wordt het browserproces ook gedeeld met de inbedding -app en WebView heeft slechts één renderproces.
Er is soms ook een nutsproces voor het decoderen van beschermde video -inhoud. Dit proces wordt niet weergegeven in de vorige diagrammen.
Draden
Threads helpen bij het bereiken van prestatie -isolatie en reactievermogen, ondanks trage taken, pijplijnparallellisatie en meervoudige buffering.
- De hoofdthread voert scripts uit, de rendering -gebeurtenislus, de documentlevenscyclus, hit -testen, scriptgebeurtenisverzenden en parseren van HTML, CSS en andere gegevensformaten.
- Hoofdthread -helpers voeren taken uit zoals het maken van afbeeldingsbitmaps en blobs die coderen of decoderen vereisen.
- Webmedewerkers voeren script uit en een rendering -evenementenlus voor offscreencanvas.
- De compositor -thread verwerkt inputevenementen, voert scrolling en animaties van webinhoud uit, berekent een optimale laag van webinhoud en coördineert beelddecodes, verfwerkingen en rastertaken.
- Compositor thread helpers coördineren namelijk rastertaken, en voer beelddecode -taken uit, verfwerkingen en fallback -raster uit.
- Media, demuxer of audio -uitvoer threads decoderen, verwerken en synchroniseren video- en audiostreams. (Vergeet niet dat video parallel wordt uitgevoerd met de belangrijkste rendering pijplijn.)
Het scheiden van de hoofd- en compositor -threads is van cruciaal belang voor prestatie -isolatie van animatie en scrollen van hoofdthreadwerk.
Er is slechts één hoofdthread per renderproces, hoewel meerdere tabbladen of frames van dezelfde site in hetzelfde proces kunnen eindigen. Er is echter prestatie -isolatie van het werk dat wordt uitgevoerd in verschillende browser -API's. Het genereren van afbeelding bitmaps en blobs in de canvas API wordt bijvoorbeeld uitgevoerd in een hoofdtreadhelperdraad.
Evenzo is er slechts één componistische thread per renderproces. Het is over het algemeen geen probleem dat er er maar één is, omdat alle echt dure bewerkingen op de compositor -thread worden gedelegeerd aan ofwel componitorwerkers of het VIZ -proces, en dit werk kan parallel worden gedaan met invoerroutering, scrollen of animatie. Compositor Worker -threads coördineren taken die worden uitgevoerd in het VIZ -proces, maar GPU -versnelling overal kan falen om redenen buiten de controle van Chromium, zoals stuurprogramma's. In deze situaties zal de werknemersdraad het werk doen in een fallback -modus op de CPU.
Het aantal threads van de compositorwerkers hangt af van de mogelijkheden van het apparaat. Desktops zullen bijvoorbeeld over het algemeen meer threads gebruiken, omdat ze meer CPU-kernen hebben en minder batterij hebben beperkt dan mobiele apparaten. Dit is een voorbeeld van opschalen en verkleinen .
De schroefdraad van de renderproces is een toepassing van drie verschillende optimalisatiepatronen:
- Helper Dreads : Stuur langlopende subtaken naar extra threads om de bovenliggende thread te laten reageren op andere, gelijktijdige verzoeken. De hoofdtreadhelper en componistische helperdraden zijn goede voorbeelden van deze techniek.
- Meerdere buffering : toon eerder weergegeven inhoud tijdens het weergeven van nieuwe inhoud, om de latentie van rendering te verbergen. De Compositor Thread gebruikt deze techniek.
- Pipeline parallellisatie: voer de rendering pijplijn op meerdere plaatsen tegelijkertijd uit. Dit is hoe scrollen en animatie snel kunnen zijn; Zelfs als er een hoofdthread -rendering -update plaatsvindt, kunnen scroll en animatie parallel worden uitgevoerd.
Browserproces
- De render- en compositiethread reageert op invoer in de browser -gebruikersinterface, routeert andere invoer naar het juiste renderproces; Legt en schildert browser -gebruikersinterface.
- De thread -helpers renderen en compositeren voeren taken voor het decoderen van beelddecodes en fallback -raster of decoderen.
Het browserproces render en compositiethread zijn vergelijkbaar met de code en functionaliteit van een renderproces, behalve dat de hoofddraad en de compositor -thread in één worden gecombineerd. Er is in dit geval maar één thread nodig omdat er geen behoefte is aan prestatie -isolatie van lange hoofddreadtaken, omdat er geen door ontwerp is.
Namelijk proces
- De GPU -hoofdthread rasters weergeven lijsten en videoframes in GPU -textuurtegels en trekt compositorframes naar het scherm.
- De Display Compositor -thread aggregeert en optimaliseert compositing van elk renderproces, plus het browserproces, in een enkel compositor -frame voor presentatie naar het scherm.
Raster en gelijkspel gebeuren over het algemeen op dezelfde thread, omdat beide afhankelijk zijn van GPU-bronnen, en het is moeilijk om betrouwbaar multi-threaded gebruik van de GPU te maken (gemakkelijkere multi-threaded toegang tot de GPU is een motivatie voor het ontwikkelen van de nieuwe Vulkan- standaard). Op Android WebView is er een afzonderlijke os-niveau render-thread voor tekenen vanwege hoe webviews zijn ingebed in een native app. Andere platforms zullen in de toekomst waarschijnlijk zo'n thread hebben.
De display -compositor bevindt zich in een andere thread omdat deze te allen tijde moet reageren en niet moet worden geblokkeerd op een mogelijke bron van vertraging op de GPU -hoofddraad. Een oorzaak van vertraging op de GPU-hoofdthread is oproepen tot niet-chromiumcode, zoals leverancierspecifieke GPU-stuurprogramma's, die op moeilijk te voorspellen traag kunnen zijn.
Componentstructuur
Binnen elke hoofd- of compositor -thread zijn er logische softwarecomponenten die op gestructureerde manieren met elkaar interageren.
Render Process Componenten van de hoofddraad
In de Blink Renderer:
- Het lokale frameboomfragment vertegenwoordigt de boom van lokale frames en de DOM binnen frames.
- De DOM- en Canvas APIS -component bevat implementaties van al deze API's.
- De Lifecycle Runner van het document voert de weergave van de weergave -pijplijn uit tot en met de commit -stap.
- De invoergebeurtenis -hittest- en verzendingscomponent voert hittests uit om erachter te komen welk DOM -element wordt gericht op een gebeurtenis en voert het invoergebeurtenis -verzendingsalgoritmen en standaardgedrag uit.
De Rendering Event Loop Scheduler en Runner beslist wat te draaien op de evenementenlus en wanneer. Het is gepland om weergegeven te gebeuren bij een cadans die overeenkomt met het apparaatdisplay.
Lokale frameboomfragmenten zijn een beetje ingewikkeld. Bedenk dat een frameboom de hoofdpagina en zijn kind is, recursief. Een frame is lokaal voor een renderproces als het in dat proces wordt weergegeven, en anders is het afgelegen.
Je kunt je voorstellen dat kleurplaten volgens hun renderproces. In het voorgaande beeld zijn de groene cirkels allemaal frames in één renderproces; De oranje zijn in een seconde en de blauwe is in een derde.
Een lokaal frameboomfragment is een verbonden onderdeel van dezelfde kleur in een frameboom. Er zijn vier lokale framebomen in de afbeelding: twee voor site A, één voor site B en één voor site C. Elke lokale frameboom krijgt zijn eigen knipperrenterercomponent. De Blink Renderer van een lokale kaderboom kan al dan niet in hetzelfde renderproces zijn als andere lokale frame -bomen. Het wordt bepaald door de manier waarop renderprocessen worden geselecteerd, zoals eerder beschreven.
Render Process Compositor threadstructuur
De componenten van de renderprocescompositor omvatten:
- Een data -handler die een gecomponeerde lagenlijst, weergavelijsten en eigenschapsbomen bijhoudt.
- Een levenscyclusloper die de animaat, scrol, samengesteld, raster en decodering en activeert stappen van de rendering -pijplijn uitvoert. (Vergeet niet dat Animate en Scroll kunnen optreden in zowel de hoofdthread als de compositor.)
- Een invoer- en hit -testhandler voert invoerverwerking uit en raakt testen bij de resolutie van samengestelde lagen, om te bepalen of scrolling -gebaren kunnen worden uitgevoerd op de compositor -thread, en op welk puntproces hit -tests moeten targeten.
Voorbeeld architectuur in de praktijk
In dit voorbeeld zijn er drie tabbladen:
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>
De proces-, thread- en componentstructuur voor deze tabbladen zien er als volgt uit:
Laten we door een voorbeeld lopen, elk van de vier hoofdtaken van rendering. Een herinnering:
- Render inhoud in pixels op het scherm.
- Animate visuele effecten op de inhoud van de ene toestand naar de andere.
- Scroll in reactie op invoer.
- Routevoer efficiënt naar de juiste plaatsen zodat ontwikkelaarscripts en andere subsystemen kunnen reageren.
Om de gewijzigde DOM voor Tab One weer te geven :
- Een ontwikkelaarscript verandert de DOM in het renderproces voor FOO.com.
- De Blink Renderer vertelt de compositor dat het een render moet optreden.
- De compositor vertelt namelijk dat het een weergave moet optreden.
- Viz signaleert het begin van de weergave terug naar de compositor.
- De compositor stuurt het startsignaal door naar de knipperrenterer.
- De hoofddraadsevenementlus Runner voert de Lifecycle van het document uit.
- De hoofdthread verzendt het resultaat naar de componistische thread.
- De Compositor Event Loop Runner voert de compositerende levenscyclus uit.
- Alle rastertaken worden verzonden naar Viz voor raster (er zijn vaak meer dan een van deze taken).
- Viz rasters content op de GPU.
- Viz erkent de voltooiing van de rastertaak. OPMERKING: Chroom wacht vaak niet tot het raster wordt voltooid en gebruikt in plaats daarvan iets dat een sync -token wordt genoemd dat moet worden opgelost door rastertaken voordat stap 15 wordt uitgevoerd.
- Een compositorframe wordt verzonden naar VIZ.
- Viz verzamelt de compositorframes voor het Foo.com Render -proces, het BAR.COM IFRAME RENDERPROCES en de browser UI.
- Viz plant een gelijkspel.
- Viz trekt het geaggregeerde compositorframe naar het scherm.
Om een CSS -transformatieovergang te animeren op Tab Twee:
- De Compositor -thread voor het BAR.COM -renderproces vinkt een animatie aan in zijn Compositor Event Loop door de bestaande eigenschapsbomen te muteren. Dit voert vervolgens de levenscyclus van de compositor opnieuw uit. (Raster en decoderen kan optreden, maar worden hier niet afgebeeld.)
- Een compositorframe wordt verzonden naar VIZ.
- Viz verzamelt de compositorframes voor het Foo.com Render Process, het Bar.com Render Process en de Browser UI.
- Viz plant een gelijkspel.
- Viz trekt het geaggregeerde compositorframe naar het scherm.
Om de webpagina op Tab drie te scrollen :
- Een reeks
input
(muis, aanraking of toetsenbord) komt naar het browserproces. - Elk evenement wordt gerouteerd naar Baz.com's Render Process Compositor Thread.
- De compositor bepaalt of de hoofdthread moet weten over het evenement.
- Het evenement wordt indien nodig naar de hoofdthread verzonden.
- De belangrijkste thread vuurt
input
-gebeurtenis luisteraars (pointerdown
,touchstar
,pointermove
,touchmove
ofwheel
) af om te zien of luisteraars voorkomen dat hij op het evenement wordtpreventDefault
. - De hoofdthread keert terug of
preventDefault
naar de compositor is geroepen. - Zo niet, wordt de invoergebeurtenis teruggestuurd naar het browserproces.
- Het browserproces converteert het naar een scroll -gebaar door het te combineren met andere recente gebeurtenissen.
- Het scroll -gebaar wordt opnieuw verzonden naar de scendercompositor -thread van Baz.com,
- De scroll wordt daar toegepast en de Compositor -thread voor het BAR.COM RENDER -proces tikt een animatie in zijn compositor -evenementenlus. Dit muteert vervolgens de scroll-offset in de eigenschapsbomen en voert de levenscyclus van de compositor opnieuw uit. Het vertelt ook de hoofdthread om een
scroll
-gebeurtenis af te vuren (hier niet afgebeeld). - Een compositorframe wordt verzonden naar VIZ.
- Viz verzamelt de compositorframes voor het Foo.com Render Process, het Bar.com Render Process en de Browser UI.
- Viz plant een gelijkspel.
- Viz trekt het geaggregeerde compositorframe naar het scherm.
Om een click
op een hyperlink in iframe #two op Tab One te routeren :
- Een
input
(muis, aanraking of toetsenbord) komt naar het browserproces. Het voert een geschatte hit -test uit om te bepalen dat het BAR.COM IFRAME -renderproces de klik moet ontvangen en het daar verzendt. - De Compositor -thread voor BAR.com routeert het
click
naar de hoofdthread voor Bar.com en plant een rendering -evenementenlustaak om deze te verwerken. - De invoergebeurtenisprocessor voor de hoofdtests van Bar.com om te bepalen op welk DOM -element in de IFRAME is geklikt en vuurt een
click
af voor scripts om te observeren. NopreventDefault
horen, het navigeert naar de hyperlink. - Na de lading van de bestemmingspagina van de hyperlink wordt de nieuwe status weergegeven, met stappen die vergelijkbaar zijn met de eerder voorbeeld van de "Render gewijzigd DOM". (Deze daaropvolgende wijzigingen worden hier niet weergegeven.)
Afhaalmaaltijden
Het kan veel tijd kosten om te onthouden en te internaliseren hoe rendering werkt.
De belangrijkste afhaalmaaltijd is dat de rendering pijplijn, door zorgvuldige modularisatie en aandacht voor detail, is opgesplitst in een aantal op zichzelf staande componenten. Deze componenten zijn vervolgens verdeeld over parallelle processen en threads om schaalbare prestaties en uitbreidbaarheidsmogelijkheden te maximaliseren.
Elk onderdeel speelt een cruciale rol bij het mogelijk maken van de prestaties en functies van moderne web -apps.
Blijf lezen over de belangrijkste gegevensstructuren , die net zo belangrijk zijn om als codecomponenten weer te geven.
Illustraties door Una Kravets.
,Hier zul je vinden hoe de componentstukken van RenderingNg zijn opgezet en hoe de rendering pijplijn erdoorheen stroomt.
Beginnend op het hoogste niveau, zijn de taken van rendering:
- Render inhoud in pixels op het scherm.
- Animate visuele effecten op de inhoud van de ene toestand naar de andere.
- Scroll in reactie op invoer.
- Routevoer efficiënt naar de juiste plaatsen zodat ontwikkelaarscripts en andere subsystemen kunnen reageren.
De inhoud om te renderen is een boom met frames voor elk tabblad brows, plus de browserinterface. En een stroom ruwe invoerevenementen van aanraakschermen, muizen, toetsenborden en andere hardware -apparaten.
Elk frame omvat:
- DOM -staat
- CSS
- Doeken
- Externe bronnen, zoals afbeeldingen, video, lettertypen en SVG
Een frame is een HTML -document, plus de URL. Een webpagina geladen in een browsertabblad heeft een frame op het hoogste niveau, onderliggende frames voor elk iframe dat is opgenomen in het document op het hoogste niveau en hun recursieve iframe-afstammelingen.
Een visueel effect is een grafische bewerking die wordt toegepast op een bitmap, zoals scroll, transformatie, clip, filter, dekking of blend.
Architectuurcomponenten
In renderingng zijn deze taken logisch gesplitst in verschillende fasen en codecomponenten. De componenten belanden in verschillende CPU-processen, threads en subcomponenten in die threads. Elk speelt een belangrijke rol bij het bereiken van betrouwbaarheid , schaalbare prestaties en uitbreidbaarheid voor alle webinhoud.
Pijplijnstructuur weergeven

Rendering in een pijplijn met een aantal fasen en artefacten die onderweg zijn gemaakt. Elke fase vertegenwoordigt code die één goed gedefinieerde taak doet binnen de rendering. De artefacten zijn gegevensstructuren die invoer of uitgangen van de fasen zijn.
De fasen zijn:
- ANIATIE: Verander berekende stijlen en muteer onroerend goed in de loop van de tijd op basis van declaratieve tijdlijnen.
- Stijl: Pas CSS toe op de DOM en maak berekende stijlen .
- Lay -out: bepaal de grootte en positie van DOM -elementen op het scherm en maak de onveranderlijke fragmentboom .
- Pre-paint: compute property trees and invalidate any existing display lists and GPU texture tiles as appropriate.
- Scroll: update the scroll offset of documents and scrollable DOM elements, by mutating property trees.
- Paint: compute a display list that describes how to raster GPU texture tiles from the DOM.
- Commit: copy property trees and the display list to the compositor thread.
- Layerize: break up the display list into a composited layer list for independent rasterization and animation.
- Raster, decode and paint worklets: turn display lists, encoded images, and paint worklet code, respectively, into GPU texture tiles .
- Activate: create a compositor frame representing how to draw and position GPU tiles to the screen, together with any visual effects.
- Aggregate: combine compositor frames from all the visible compositor frames into a single, global compositor frame.
- Draw: execute the aggregated compositor frame on the GPU to create pixels on-screen.
Stages of the rendering pipeline can be skipped if they aren't needed. For example, animations of visual effects, and scroll, can skip layout, pre-paint and paint. This is why animation and scroll are marked with yellow and green dots in the diagram. If layout, pre-paint, and paint can be skipped for visual effects, they can be run entirely on the compositor thread and skip the main thread.
Browser UI rendering is not depicted directly here, but can be thought of as a simplified version of this same pipeline (and in fact its implementation shares much of the code). Video (also not directly depicted) generally renders with independent code that decodes frames into GPU texture tiles that are then plugged into compositor frames and the draw step.
Process and thread structure
CPU processes
The use of multiple CPU processes achieves performance and security isolation between sites and from browser state, and stability and security isolation from GPU hardware.
- The render process renders, animates, scrolls, and routes input for a single site and tab combination. There are several render processes.
- The browser process renders, animates, and routes input for the browser UI (including the address bar, tab titles, and icons), and routes all remaining input to the appropriate render process. There is one browser process.
- The Viz process aggregates compositing from multiple render processes plus the browser process. It rasters and draws using the GPU. There is one Viz process.
Different sites always end up in different render processes.
Multiple browser tabs or windows of the same site usually go in different render processes, unless the tabs are related, such as one opening the other. Under strong memory pressure on desktop Chromium may put multiple tabs from the same site into the same render process even if not related.
Within a single browser tab, frames from different sites are always in different render processes from each other, but frames from the same site are always in the same render process. From the perspective of rendering, the important advantage of multiple render processes is that cross-site iframes and tabs achieve performance isolation from each other. In addition, origins can opt into even more isolation .
There is exactly one Viz process for all of Chromium, as there is usually only one GPU and screen to draw to.
Separating Viz into its own process is good for stability in the face of bugs in GPU drivers or hardware. It's also good for security isolation, which is important for GPU APIs like Vulkan and security in general .
Since the browser can have many tabs and windows, and all of them have browser UI pixels to draw, you might wonder: why there is exactly one browser process? The reason is that only one of them is focused at a time; in fact, non-visible browser tabs are mostly deactivated and drop all of their GPU memory. However, complex browser UI rendering features are increasingly being implemented in render processes as well (known as WebUI ). This is not for performance isolation reasons, but in order to take advantage of the ease of use of Chromium's web rendering engine.
On older Android devices , the render and browser process are shared when used in a WebView (this does not apply to Chromium on Android generally, just WebView). On WebView, the browser process is also shared with the embedding app, and WebView has only one render process.
There is also sometimes a utility process for decoding protected video content. This process is not depicted in the previous diagrams.
Threads
Threads help achieve performance isolation and responsiveness in spite of slow tasks, pipeline parallelization and multiple buffering.
- The main thread runs scripts, the rendering event loop, the document lifecycle, hit testing, script event dispatching, and parsing of HTML, CSS and other data formats.
- Main thread helpers perform tasks such as creating image bitmaps and blobs that require encoding or decoding.
- Web Workers run script, and a rendering event loop for OffscreenCanvas.
- The Compositor thread processes input events, performs scrolling and animations of web content, computes optimal layerization of web content, and coordinates image decodes, paint worklets and raster tasks.
- Compositor thread helpers coordinate Viz raster tasks, and execute image decode tasks, paint worklets and fallback raster.
- Media, demuxer or audio output threads decode, process and synchronize video and audio streams. (Remember that video executes in parallel with the main rendering pipeline.)
Separating the main and compositor threads is critically important for performance isolation of animation and scrolling from main thread work.
There is only one main thread per render process, even though multiple tabs or frames from the same site may end up in the same process. However, there is performance isolation from work performed in various browser APIs. For example, generation of image bitmaps and blobs in the Canvas API run in a main thread helper thread.
Likewise, there is only one compositor thread per render process. It is generally not a problem that there is only one, because all of the really expensive operations on the compositor thread are delegated to either compositor worker threads or the Viz process, and this work can be done in parallel with input routing, scrolling or animation. Compositor worker threads coordinate tasks run in the Viz process, but GPU acceleration everywhere can fail for reasons outside of Chromium's control, such as driver bugs. In these situations the worker thread will do the work in a fallback mode on the CPU.
The number of compositor worker threads depends on the capabilities of the device. For example, desktops will generally use more threads, as they have more CPU cores and are less battery-constrained than mobile devices. This is an example of scaling up and scaling down .
The render process threading architecture is an application of three different optimization patterns:
- Helper threads : send long-running subtasks off to additional threads to keep the parent thread responsive to other, simultaneous requests. The main thread helper and compositor helper threads are good examples of this technique.
- Multiple buffering : show previously rendered content while rendering new content, to hide the latency of rendering. The compositor thread uses this technique.
- Pipeline parallelization: run the rendering pipeline in multiple places simultaneously. This is how scrolling and animation can be fast; even if a main thread rendering update is happening, scroll and animation can run in parallel.
Browser process
- The render and compositing thread responds to input in the browser UI, routes other input to the correct render process; lays out and paints browser UI.
- The render and compositing thread helpers execute image decode tasks and fallback raster or decode.
The browser process render and compositing thread are similar to the code and functionality of a render process, except that the main thread and compositor thread are combined into one. There is only one thread needed in this case because there is no need for performance isolation from long main thread tasks, since there are none by design.
Viz process
- The GPU main thread rasters display lists and video frames into GPU texture tiles, and draws compositor frames to the screen.
- The display compositor thread aggregates and optimizes compositing from each render process, plus the browser process, into a single compositor frame for presentation to the screen.
Raster and draw generally happen on the same thread, because both of them rely on GPU resources, and it's hard to reliably make multi-threaded use of the GPU (easier multi-threaded access to the GPU is one motivation for developing the new Vulkan standard). On Android WebView, there is a separate OS-level render thread for drawing because of how WebViews are embedded into a native app. Other platforms will likely have such a thread in the future.
The display compositor is on a different thread because it needs to be responsive at all times, and not block on any possible source of slowdown on the GPU main thread. One cause of slowdown on the GPU main thread is calls into non-Chromium code, such as vendor-specific GPU drivers, that may be slow in hard-to-predict ways.
Component structure
Within each render process main or compositor thread, there are logical software components that interact with each other in structured ways.
Render process main thread components
In the Blink Renderer:
- The local frame tree fragment represents the tree of local frames and the DOM within frames.
- The DOM and Canvas APIs component contains implementations of all of these APIs.
- The document lifecycle runner executes the rendering pipeline steps up to and including the commit step.
- The input event hit testing and dispatching component executes hit tests to find out which DOM element is targeted by an event, and runs the input event dispatching algorithms and default behaviors.
The rendering event loop scheduler and runner decides what to run on the event loop and when. It schedules rendering to happen at a cadence matching the device display.
Local frame tree fragments are a bit complicated. Recall that a frame tree is the main page and its child iframes, recursively. A frame is local to a render process if it is rendered in that process, and otherwise it is remote.
You can imagine coloring frames according to their render process. In the preceding image, the green circles are all frames in one render process; the orange ones are in a second, and the blue one is in a third.
A local frame tree fragment is a connected component of the same color in a frame tree. There are four local frame trees in the image: two for site A, one for site B, and one for site C. Each local frame tree gets its own Blink renderer component. A local frame tree's Blink renderer may or may not be in the same render process as other local frame trees. It's determined by the way render processes are selected, as described earlier.
Render process compositor thread structure
The render process compositor components include:
- A data handler that maintains a composited layer list, display lists and property trees.
- A lifecycle runner that runs the animate, scroll, composite, raster, and decode and activate steps of the rendering pipeline. (Remember that animate and scroll can occur in both the main thread and the compositor.)
- An input and hit test handler performs input processing and hit testing at the resolution of composited layers, to determine if scrolling gestures can be run on the compositor thread, and which render process hit tests should target.
Example architecture in practice
In this example there are three 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>
The process, thread and component structure for these tabs look as follows:
Let's walk through one example each of the four main tasks of rendering. A reminder:
- Render contents into pixels on the screen.
- Animate visual effects on the contents from one state to another.
- Scroll in response to input.
- Route input efficiently to the right places so that developer scripts and other subsystems can respond.
To render the changed DOM for tab one:
- A developer script changes the DOM in the render process for foo.com.
- The Blink renderer tells the compositor that it needs a render to occur.
- The compositor tells Viz it needs a render to occur.
- Viz signals the start of the render back to the compositor.
- The compositor forwards the start signal on to the Blink renderer.
- The main thread event loop runner runs the document lifecycle.
- The main thread sends the result to the compositor thread.
- The compositor event loop runner runs the compositing lifecycle.
- Any raster tasks are sent to Viz for raster (there are often more than one of these tasks).
- Viz rasters content on the GPU.
- Viz acknowledges completion of the raster task. Note: Chromium often doesn't wait for the raster to complete, and instead uses something called a sync token that has to be resolved by raster tasks before step 15 executes.
- A compositor frame is sent to Viz.
- Viz aggregates the compositor frames for the foo.com render process, the bar.com iframe render process, and the browser UI.
- Viz schedules a draw.
- Viz draws the aggregated compositor frame to the screen.
To animate a CSS transform transition on tab two:
- The compositor thread for the bar.com render process ticks an animation in its compositor event loop by mutating the existing property trees. This then re-runs the compositor lifecycle. (Raster and decode tasks may occur, but are not depicted here.)
- A compositor frame is sent to Viz.
- Viz aggregates the compositor frames for the foo.com render process, the bar.com render process, and the browser UI.
- Viz schedules a draw.
- Viz draws the aggregated compositor frame to the screen.
To scroll the web page on tab three:
- A sequence of
input
events (mouse, touch or keyboard) come to the browser process. - Each event is routed to baz.com's render process compositor thread.
- The compositor determines if the main thread needs to know about the event.
- The event is sent, if necessary, to the main thread.
- The main thread fires
input
event listeners (pointerdown
,touchstar
,pointermove
,touchmove
orwheel
) to see if listeners will callpreventDefault
on the event. - The main thread returns whether
preventDefault
was called to the compositor. - If not, the input event is sent back to the browser process.
- The browser process converts it to a scroll gesture by combining it with other recent events.
- The scroll gesture is sent once again to baz.com's render process compositor thread,
- The scroll is applied there, and the compositor thread for the bar.com render process ticks an animation in its compositor event loop. This then mutates scroll offset in the property trees and re-runs the compositor lifecycle. It also tells the main thread to fire a
scroll
event (not depicted here). - A compositor frame is sent to Viz.
- Viz aggregates the compositor frames for the foo.com render process, the bar.com render process, and the browser UI.
- Viz schedules a draw.
- Viz draws the aggregated compositor frame to the screen.
To route a click
event on a hyperlink in iframe #two on tab one:
- An
input
event (mouse, touch or keyboard) comes to the browser process. It performs an approximate hit test to determine that the bar.com iframe render process should receive the click, and sends it there. - The compositor thread for bar.com routes the
click
event to the main thread for bar.com and schedules a rendering event loop task to process it. - The input event processor for bar.com's main thread hit tests to determine which DOM element in the iframe was clicked, and fires a
click
event for scripts to observe. Hearing nopreventDefault
, it navigates to the hyperlink. - Upon load of destination page of the hyperlink, the new state is rendered, with steps similar to the "render changed DOM" previous example. (These subsequent changes are not depicted here.)
Afhaalmaaltijden
It can take a lot of time to remember and internalize how rendering works.
The most important takeaway is that the rendering pipeline, through careful modularization and attention to detail, has been split into a number of self-contained components. These components have then been split across parallel processes and threads to maximize scalable performance and extensibility opportunities.
Each component plays a critical role in enabling the performance and features of modern web apps.
Keep reading about the key data structures , which are just as important to RenderingNG as code components.
Illustrations by Una Kravets.