Architettura RenderingNG

Chris Harrelson
Chris Harrelson

Qui scoprirai come il componente RenderingNG le parti preparate e il flusso della pipeline di rendering.

Partendo dal livello più alto, le attività del rendering sono:

  1. Esegui il rendering dei contenuti in pixel sullo schermo.
  2. Applica animazioni a effetti visivi sui contenuti da uno stato all'altro.
  3. Scorri in risposta a un input.
  4. Indirizza gli input in modo efficiente nelle posizioni giuste in modo che gli script degli sviluppatori e altri sottosistemi possano rispondere.

I contenuti di cui eseguire il rendering sono una struttura di frame per ogni scheda del browser, con in più i all'interfaccia del browser. E un flusso di eventi di input non elaborati dai touchscreen mouse, tastiere e altri dispositivi hardware.

Ogni frame include:

  • Stato DOM
  • CSS
  • Canvas
  • Risorse esterne, come immagini, video, caratteri e SVG

Un frame è un documento HTML insieme al relativo URL. Una pagina web caricata in una scheda del browser ha un frame di primo livello. frame secondari per ogni iframe incluso nel documento di primo livello, e i relativi discendenti iframe ricorrenti.

Un effetto visivo è un'operazione grafica applicata a una bitmap. come scorrimento, trasformazione, ritaglio, filtro, opacità o fusione.

Componenti dell'architettura

In RenderingNG, queste attività sono suddivise logicamente in più fasi e codice componenti. I componenti finiscono in vari processi CPU, thread i componenti secondari all'interno di questi thread. Ognuna gioca un ruolo importante nel raggiungere affidabilità, prestazioni scalabili ed estensibilità di tutti i contenuti web.

Struttura della pipeline di rendering

Diagramma della pipeline di rendering.
Le frecce indicano gli input e gli output di ogni fase. Fasi notate per colore, per dimostrare quale thread o processo eseguono. Nella alcuni casi, le fasi possono essere eseguite in più posti, a seconda di conseguenza, per questo alcuni hanno due colori. Thread principale del processo di rendering delle fasi verdi; i giallo sono compositori del processo di rendering; le fasi arancioni sono il processo di visualizzazione.

Il rendering procede in una pipeline con una serie di fasi e artefatti creati lungo il percorso. Ogni fase rappresenta il codice che esegue un'attività ben definita all'interno per il rendering delle immagini. Gli artefatti sono strutture di dati. cioè input o output delle fasi.

Le fasi sono:

  1. Animazione:modifica gli stili calcolati e gli alberi di proprietà nel tempo in base a tempistiche dichiarative.
  2. Stile: applica CSS al DOM e crea stili calcolati.
  3. Layout: determina le dimensioni e la posizione degli elementi DOM sullo schermo. e creiamo l'albero di frammenti immutabile.
  4. Pre-colorazione: alberi di proprietà di computing e invalidare Eventuali elenchi di visualizzazione e riquadri di texture GPU esistenti, a seconda dei casi.
  5. Scorri: aggiorna l'offset di scorrimento dei documenti e degli elementi DOM scorrevoli, modificando le strutture delle proprietà.
  6. Paint: calcola un elenco di visualizzazione che descrive come rasterare i riquadri di texture GPU dal DOM.
  7. Commit: copia le strutture delle proprietà e l'elenco di visualizzazione nel thread del compositore.
  8. Sovrapporre l'elenco: suddividi l'elenco di visualizzazione in un elenco di livelli composti per la rasterizzazione e l'animazione indipendenti.
  9. Raster, decodifica e colorazione dei worklet:trasforma, rispettivamente, gli elenchi di visualizzazione, le immagini codificate e il codice di colorazione del worklet in Riquadri texture GPU.
  10. Attiva: crea un frame composito che rappresenti come disegnare e posizionare i riquadri GPU sullo schermo, insieme a eventuali effetti visivi.
  11. Aggregate:combina i frame del compositore da tutti i frame del compositore visibili in un unico frame del compositore globale.
  12. Disegna: esegue il frame del compositore aggregato sulla GPU per creare pixel sullo schermo.

Se non sono necessarie, le fasi della pipeline di rendering possono essere ignorate. Ad esempio, le animazioni di effetti visivi e lo scorrimento possono saltare il layout, pre-colorare e colorare. Questo è il motivo per cui l'animazione e lo scorrimento sono contrassegnati con punti gialli e verdi nel diagramma. Se è possibile saltare layout, pre-colorazione e colorazione per gli effetti visivi, possono essere eseguiti interamente sul thread del compositore e saltano il thread principale.

Il rendering dell'interfaccia utente del browser non è mostrato direttamente qui, ma può essere considerata una versione semplificata di questa stessa pipeline (di fatto, la sua implementazione condivide gran parte del codice). Video (anche non raffigurato direttamente) il rendering viene generalmente eseguito con un codice indipendente che decodifica i frame in riquadri di texture GPU collegati ai frame del compositore e al passaggio di disegno.

Struttura dei processi e dei thread

Processi CPU

L'uso di più processi di CPU consente di isolare le prestazioni e la sicurezza tra i siti e dallo stato del browser e l'isolamento di sicurezza e stabilità dall'hardware GPU.

Diagramma delle varie parti dei processi della CPU

  • Il processo di rendering esegue il rendering, l'animazione, lo scorrimento e il routing dell'input per un singola combinazione di sito e scheda. Esistono diversi processi di rendering.
  • Il processo del browser esegue il rendering, l'animazione e il routing dell'input per l'UI del browser (tra cui barra degli indirizzi, titoli delle schede e icone) e i percorsi rimanenti al processo di rendering appropriato. Esiste un solo processo del browser.
  • Il processo di visualizzazione aggrega la composizione da più processi di rendering più il processo del browser. Rafforza e disegna usando la GPU. C'è un processo Viz.

Siti diversi in diversi processi di rendering.

In genere più schede o finestre del browser dello stesso sito vengono visualizzate in un rendering diverso. processi, a meno che le schede non siano correlate, ad esempio una aprendo l'altro. Se la memoria è molto ridotta su Chromium desktop, potrebbero essere inserite più schede in Chromium dallo stesso sito allo stesso processo di rendering, anche se non correlati.

In un'unica scheda del browser, frame di siti diversi sono sempre in processi di rendering diversi l'uno dall'altro, ma i frame dello stesso sito si trovano sempre nello stesso processo di rendering. Per quanto riguarda il rendering, Il vantaggio importante di più processi di rendering è che gli iframe tra siti e le schede isolano le prestazioni l'uno dall'altro. Inoltre, le origini possono attivare un isolamento ancora maggiore.

Esiste esattamente un processo Viz per tutto Chromium, dato che di solito c'è una GPU e uno schermo a cui attirare.

Separare Viz in un proprio processo è un vantaggio per la stabilità nonostante i bug in Driver o hardware GPU. È utile anche per l'isolamento di sicurezza, il che è importante per le API GPU, Vulkan e la sicurezza in generale.

Poiché il browser può avere molte schede e finestre, e tutti hanno pixel da disegnare nell'interfaccia utente del browser, potresti chiederti perché esiste esattamente un processo del browser. Il motivo è che solo uno di questi è focalizzato su uno alla volta: di fatto, le schede del browser non visibili vengono per lo più disattivate e perdono tutta la memoria GPU. Tuttavia, sempre più spesso vengono implementate complesse funzionalità di rendering dell'interfaccia utente del browser. anche nei processi di rendering (noti WebUI). Ciò non è dovuto a motivi di isolamento delle prestazioni, ma per sfruttare la facilità d'uso del motore di rendering web di Chromium.

Sui dispositivi Android meno recenti, il processo di rendering e del browser vengono condivisi quando sono utilizzati in un componente WebView (questo non vale in generale per Chromium su Android, ma solo per WebView). Su WebView, il processo del browser è condiviso anche con l'app di incorporamento, e WebView ha un solo processo di rendering.

A volte esiste anche una procedura di utilità per la decodifica dei contenuti video protetti. Questo processo non è descritto nei diagrammi precedenti.

Thread

I thread aiutano a raggiungere l'isolamento delle prestazioni e la reattività nonostante le attività lente, la parallelizzazione della pipeline e più buffering.

Diagramma del processo di rendering.

  • Il thread principale esegue gli script, il loop di eventi di rendering, il ciclo di vita del documento test degli hit, invio di eventi di script e analisi di HTML, CSS e altri formati di dati.
    • Gli aiutanti dei thread principali svolgono attività come la creazione di bitmap e BLOB di immagini che richiedono la codifica o la decodifica.
    • Web worker eseguire lo script e un loop di eventi di rendering per OffscreenCanvas.
  • Il thread del compositore elabora gli eventi di input, esegue scorrimento e animazioni dei contenuti web, calcola la stratificazione ottimale dei contenuti web, e coordina la decodifica delle immagini, la colorazione dei worklet e le attività di raster.
    • Gli aiutanti dei thread del compositore coordinano le attività raster di Viz. ed eseguire attività di decodifica delle immagini, colorazione di worklet e raster di fallback.
  • Thread di contenuti multimediali, demuxer o output audio decodificano, ed elaborare e sincronizzare gli stream video e audio. Ricorda che il video viene eseguito in parallelo con la pipeline di rendering principale.

La separazione dei thread principale da quello del compositore è di fondamentale importanza isolamento delle prestazioni di animazione e scorrimento dal lavoro del thread principale.

Esiste un solo thread principale per processo di rendering, anche se più schede o frame dello stesso sito potrebbero finire nello stesso processo. Tuttavia, le prestazioni sono isolate dal lavoro svolto in varie API del browser. Ad esempio, la generazione di bitmap e BLOB delle immagini nell'API Canvas viene eseguita in un thread helper del thread principale.

Allo stesso modo, esiste un solo thread del compositore per processo di rendering. In genere non è un problema se ne esiste uno solo, perché tutte le operazioni molto costose sul thread del compositore sono delegati ai thread worker del compositore o al processo Viz, e può essere svolto in parallelo con il routing dell'input, lo scorrimento o l'animazione. I thread worker del compositore coordinano le attività eseguite nel processo di Viz, ma l'accelerazione GPU ovunque potrebbero non riuscire per motivi che esulano dal controllo di Chromium, ad esempio i bug del conducente. In queste situazioni il thread di lavoro svolgerà il lavoro in modalità di riserva sulla CPU.

Il numero di thread worker del compositore dipende dalle capacità del dispositivo. Ad esempio, i computer solitamente usano più thread, in quanto hanno più core CPU e hanno meno limiti di batteria rispetto ai dispositivi mobili. Ecco un esempio fare lo scale up e lo scale down.

L'architettura di thread del processo di rendering è un'applicazione di tre diverse schemi di ottimizzazione:

  • Thread helper: invia attività secondarie di lunga durata a thread aggiuntivi per mantenerli il thread principale che risponde ad altre richieste simultanee. Il thread principale i thread helper e compositore sono buoni esempi di questa tecnica.
  • Buffering multiplo: mostrare i contenuti sottoposti a rendering in precedenza durante il rendering di nuovi contenuti, per nascondere latenza di rendering. Il thread del compositore utilizza questa tecnica.
  • Parallelizzazione della pipeline: esegue la pipeline di rendering in più posizioni contemporaneamente. Lo scorrimento e l'animazione possono essere così veloci: anche se l'aggiornamento del rendering del thread principale è in corso, lo scorrimento e l'animazione possono vengono eseguite in parallelo.

Processo del browser

Un diagramma del processo del browser che mostra la relazione tra il thread di rendering e di composizione e l'helper del thread di rendering e composizione.

  • Il thread di rendering e composizione risponde all'input nell'interfaccia utente del browser, instrada altri input al corretto processo di rendering; definisce e colora l'UI del browser.
  • Gli aiutanti dei thread per il rendering e la composizione eseguire attività di decodifica delle immagini e operazioni di raster o decodifica di fallback.

I thread di rendering e compositing del processo del browser sono simili al codice e alla funzionalità di un processo di rendering, tranne per il fatto che il thread principale e il thread del compositore sono combinati in un unico thread. In questo caso è necessario un solo thread perché non è necessario l'isolamento delle prestazioni da attività lunghe del thread principale, poiché non ce ne sono per progettazione.

Processo di visualizzazione

Il processo Viz include il thread principale della GPU e il thread del compositore di visualizzazione.

  • Il thread principale GPU esegue il raster degli elenchi di visualizzazione e dei frame video nei riquadri di texture GPU, e disegna sullo schermo i frame del compositore.
  • Il thread compositore display aggrega e ottimizza la composizione di ogni processo di rendering, più il processo del browser in un unico frame del compositore per la presentazione sullo schermo.

Raster e disegno avvengono generalmente sullo stesso thread, perché entrambi si basano su risorse GPU, ed è difficile fare un uso multi-thread della GPU in modo affidabile (L'accesso multi-thread più semplice alla GPU è uno dei motivi per lo sviluppo del nuovo Vulkan). Su Android WebView, è presente un thread di rendering separato a livello di sistema operativo per disegnare per via dell'incorporamento dei componenti WebView in un'app nativa. È probabile che altre piattaforme abbiano questo thread in futuro.

Il compositore display si trova su un thread diverso perché deve essere sempre reattivo, e non bloccare qualsiasi possibile fonte di rallentamento sul thread principale della GPU. Una causa del rallentamento del thread principale della GPU sono le chiamate a codice non Chromium, come i driver GPU specifici del fornitore, che possono risultare lenti in modi difficili da prevedere.

Struttura componente

All'interno di ogni thread principale o del compositore del processo di rendering, ci sono componenti software logici che interagiscono tra loro in modi strutturati.

Componenti del thread principale del processo di rendering

Diagramma del renderer Blink.

Nel renderer di Blink:

  • Il frammento ad albero di frame locali rappresenta l'albero dei frame locali e il DOM all'interno dei frame.
  • Il componente API DOM e Canvas contiene le implementazioni di tutte queste API.
  • L'esecutore del ciclo di vita del documento esegue i passaggi della pipeline di rendering fino al passaggio di commit incluso.
  • Il componente hit test e invio degli eventi di input esegue i test degli hit per trova l'elemento DOM scelto come target da un evento ed esegue l'evento di input algoritmi di tracciamento e comportamenti predefiniti.

Lo scheduler e runner del loop dell'evento di rendering decide cosa pubblicare sull'evento e quando. La programmazione del rendering viene programmata in modo che avvenga a una frequenza corrispondente al dispositivo. display.

Un diagramma dell'albero di frame.

I frammenti di frame di frame locali sono un po' complicati. Ricorda che una struttura di frame è la pagina principale e i suoi iframe secondari, in modo ricorsivo. Un frame è locale rispetto a un processo di rendering se quest'ultimo viene sottoposto a rendering. altrimenti da remoto.

Puoi immaginare di colorare i frame in base al processo di rendering. Nell'immagine precedente, i cerchi verdi sono tutti frame in un processo di rendering; quelle arancioni sono in un secondo e quella blu è in un terzo.

Un frammento ad albero di frame locale è un componente connesso dello stesso colore in un albero di frame. Nell'immagine sono presenti quattro strutture di frame locali: due per il sito A, uno per il sito B e uno per il sito C. Ogni struttura di frame locale riceve il proprio componente di rendering Blink. Il renderer Blink di un albero di frame locale potrebbe trovarsi o meno nello stesso processo di rendering come gli altri frame Tree locali. Dipende dal modo in cui vengono selezionati i processi di rendering, come descritto in precedenza.

Struttura dei thread del compositore del processo di rendering

Diagramma che mostra i componenti del compositore del processo di rendering.

I componenti del compositore del processo di rendering includono:

  • Un gestore di dati che gestisce un elenco di livelli compositi, elenchi di visualizzazione e strutture di proprietà.
  • Un runner del ciclo di vita che esegue i contenuti animati, di scorrimento, composito, raster e decodificare e attivare i passaggi della pipeline di rendering. Ricorda che l'animazione e lo scorrimento possono verificarsi sia nel thread principale che nel compositore.
  • Un gestore di input e hit test esegue l'elaborazione degli input e gli hit test alla risoluzione dei livelli compositi per determinare se è possibile eseguire gesti di scorrimento sul thread del compositore, e i test di hit del processo di rendering che devono scegliere come target.

Architettura di esempio nella pratica

In questo esempio sono presenti tre schede:

Scheda 1: foo.com

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

Scheda 2: bar.com

<html>
 …
</html>

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

Il processo, il thread e la struttura dei componenti per queste schede hanno il seguente aspetto:

Diagramma della procedura per le schede.

Vediamo un esempio per ognuna delle quattro attività principali del rendering. Promemoria:

  1. Esegui il rendering dei contenuti in pixel sullo schermo.
  2. Applicare animazioni a effetti visivi sui contenuti da uno stato all'altro.
  3. Scorri in risposta a un input.
  4. Indirizza in modo efficiente l'input nei punti giusti in modo che gli script degli sviluppatori e altri sottosistemi possano rispondere.

Per eseguire il rendering del DOM modificato per la prima scheda:

  1. Uno script dello sviluppatore modifica il DOM nel processo di rendering per foo.com.
  2. Il renderer Blink comunica al compositore che è necessario eseguire il rendering.
  3. Il compositore comunica a Viz che è necessario eseguire il rendering.
  4. Viz segnala l'inizio del rendering al compositore.
  5. Il compositore inoltra il segnale di avvio al renderer Blink.
  6. Il runner del loop di eventi del thread principale esegue il ciclo di vita del documento.
  7. Il thread principale invia il risultato al thread del compositore.
  8. L'esecutore del loop di eventi del compositore esegue il ciclo di vita della composizione.
  9. Tutte le attività raster vengono inviate a Viz per il raster (spesso ce ne sono più di una).
  10. Visualizzazione dei contenuti raster sulla GPU.
  11. Viz conferma il completamento dell'attività di raster. Nota: spesso Chromium non attende il completamento del raster, e utilizza invece un elemento token di sincronizzazione da risolvere per attività di raster prima dell'esecuzione del passaggio 15.
  12. Un frame del compositore viene inviato a Viz.
  13. Viz aggrega i frame del compositore per il processo di rendering foo.com, il processo di rendering dell'iframe bar.com e l'interfaccia utente del browser.
  14. Visualizzazione pianifica una estrazione.
  15. Viz disegna il frame del compositore aggregato sullo schermo.

Per animare una transizione Transform CSS nella scheda due:

  1. Il thread del compositore per il processo di rendering bar.com seleziona un'animazione nel suo loop di eventi del compositore modificando le strutture di proprietà esistenti. Viene quindi eseguito di nuovo il ciclo di vita del compositore. (potrebbero verificarsi attività raster e decodificate, ma non sono rappresentate qui.)
  2. Un frame del compositore viene inviato a Viz.
  3. Viz aggrega i frame del compositore per il processo di rendering foo.com, il processo di rendering bar.com e l'interfaccia utente del browser.
  4. Visualizzazione pianifica una estrazione.
  5. Viz disegna il frame del compositore aggregato sullo schermo.

Per scorrere la pagina web nella scheda tre:

  1. Una sequenza di eventi input (mouse, tocco o tastiera) arriva nel processo del browser.
  2. Ogni evento viene instradato al thread del compositore del processo di rendering di baz.com.
  3. Il compositore determina se il thread principale deve conoscere l'evento.
  4. L'evento viene inviato, se necessario, al thread principale.
  5. Il thread principale attiva input listener di eventi (pointerdown, touchstar, pointermove, touchmove o wheel) per vedere se i listener chiameranno preventDefault per l'evento.
  6. Il thread principale restituisce se preventDefault è stato chiamato al compositore.
  7. In caso contrario, l'evento di input viene inviato nuovamente al processo del browser.
  8. Il processo del browser lo converte in un gesto di scorrimento combinandolo con altri eventi recenti.
  9. Il gesto di scorrimento viene inviato di nuovo al thread del compositore del processo di rendering di baz.com,
  10. Qui viene applicato lo scorrimento e il thread del compositore per il bar.com. il processo di rendering attiva un'animazione nel loop di eventi del compositore. Questa operazione modifica l'offset di scorrimento nelle strutture delle proprietà ed esegue nuovamente il ciclo di vita del compositore. Inoltre, indica al thread principale di attivare un evento scroll (non mostrato qui).
  11. Un frame del compositore viene inviato a Viz.
  12. Viz aggrega i frame del compositore per il processo di rendering foo.com, il processo di rendering di bar.com e l'interfaccia utente del browser.
  13. Visualizzazione pianifica una estrazione.
  14. Viz disegna il frame del compositore aggregato sullo schermo.
di Gemini Advanced.

Per indirizzare un evento click su un link ipertestuale nell'iframe #due nella scheda uno:

  1. Nel processo del browser si verifica un evento input (mouse, tocco o tastiera). Esegue un test hit approssimativo per stabilire che il processo di rendering dell'iframe bar.com riceva il clic e lo invii lì.
  2. Il thread del compositore per bar.com instrada l'evento click al thread principale per bar.com e pianifica un'attività di loop di eventi di rendering per elaborarla.
  3. Il processore di eventi di input per i principali test di hit dei thread di bar.com per determinare quale È stato fatto clic sull'elemento DOM nell'iframe e attiva un evento click affinché gli script possano osservare. Se sente l'assenza di preventDefault, apre il link ipertestuale.
  4. Al caricamento della pagina di destinazione del link ipertestuale, il nuovo stato viene visualizzato. con passaggi simili a quelli del DOM di rendering modificato dell'esempio precedente. (Queste modifiche successive non sono descritte qui.)

Conclusione

Può essere necessario molto tempo per ricordare e rendere interno il funzionamento del rendering.

L'aspetto più importante è che la pipeline di rendering, attraverso un'attenta la modularizzazione e l'attenzione ai dettagli è stata suddivisa in diverse indipendenti. Questi componenti sono stati quindi suddivisi tra processi e thread per massimizzare prestazioni scalabili ed estensibilità.

Ogni componente svolge un ruolo fondamentale nell'abilitazione delle prestazioni e delle funzionalità e moderne app web.

Continua a leggere le strutture principali di dati. che sono importanti per il renderingNG quanto i componenti del codice.


Illustrazioni di Una Kravets.