Aqui você verá como o componente RenderingNG são configuradas e como o pipeline de renderização flui por elas.
Começando no nível mais alto, as tarefas de renderização são:
- Renderizar o conteúdo em pixels na tela.
- Animar efeitos visuais no conteúdo de um estado para outro.
- Rolar em resposta à entrada.
- Direcione a entrada com eficiência para os lugares certos para que os scripts do desenvolvedor e outros subsistemas possam responder.
O conteúdo a ser renderizado é uma árvore de frames para cada guia do navegador, mais o do navegador da Web. E um fluxo de eventos de entrada brutos a partir de telas sensíveis ao toque, mouses, teclados e outros dispositivos de hardware.
Cada frame inclui:
- Estado DOM
- CSS
- Telas
- Recursos externos, como imagens, vídeos, fontes e SVG
Um frame é um documento HTML mais seu URL. Uma página da Web carregada em uma guia do navegador tem um frame de nível superior, frames filhos para cada iframe incluído no documento de nível superior, e seus descendentes de iframe recursivos.
Um efeito visual é uma operação gráfica aplicada a um bitmap como rolagem, transformação, corte, filtro, opacidade ou mesclagem.
Componentes da arquitetura
No RenderingNG, essas tarefas são divididas de maneira lógica entre vários estágios e códigos componentes de solução. Os componentes acabam em vários processos de CPU, linhas de execução subcomponentes dessas linhas. Cada uma desempenha um papel importante confiabilidade, performance escalonável e extensibilidade para todo o conteúdo da Web.
Estrutura do pipeline de renderização
A renderização continua em um pipeline com vários estágios e artefatos criados pelo caminho. Cada estágio representa um código que realiza uma tarefa bem definida dentro renderização. Os artefatos são estruturas de dados que são entradas ou saídas das fases.
As fases são:
- Animar:altere os estilos calculados e as árvores de propriedade ao longo do tempo com base em linhas do tempo declarativas.
- Estilo: aplique CSS ao DOM e crie estilos calculados.
- Layout:determina o tamanho e a posição dos elementos DOM na tela e criar a árvore de fragmentos imutável.
- Pré-pintura: computações de árvores de propriedades e invalidar as listas de exibição e os blocos de textura da GPU, conforme apropriado.
- Rolar:atualize o deslocamento de rolagem de documentos e elementos DOM roláveis mudando as árvores de propriedades.
- Paint:calcula uma lista de exibição que descreve como fazer a varredura dos blocos de textura da GPU no DOM.
- Commit:copie as árvores de propriedades e a lista de exibição para a linha de execução do compositor.
- Criar camadas:divida a lista de exibição em uma lista de camadas compostas para rasterização e animação independentes.
- Raster, decode e paint worklets: transforma listas de exibição, imagens codificadas e o código do worklet de pintura, respectivamente, em Blocos de textura da GPU.
- Ativar:cria um frame de composição que representa como desenhar e posicionar blocos da GPU na tela, junto com quaisquer efeitos visuais.
- Agregação:combina frames do compositor de todos os frames visíveis em um único frame global.
- Draw:executa o frame do compositor agregado na GPU para criar pixels na tela.
As etapas do pipeline de renderização podem ser ignoradas se não forem necessárias. Por exemplo, animações de efeitos visuais e rolagem podem pular o layout, a pré-pintura e a pintura. É por isso que a animação e a rolagem estão marcadas com pontos amarelos e verdes no diagrama. Se for possível pular o layout, a pré-pintura e a pintura para efeitos visuais, elas podem ser executadas inteiramente na linha de execução do compositor e ignorar a linha de execução principal.
A renderização da interface do navegador não é representada diretamente aqui, mas pode ser considerada uma versão simplificada desse mesmo pipeline (e, na verdade, sua implementação compartilha grande parte do código). Vídeo (também sem representação direta) geralmente renderiza com código independente que decodifica frames em blocos de textura da GPU que são conectados aos frames do compositor e à etapa de desenho.
Estrutura do processo e da linha de execução
Processos da CPU
O uso de vários processos de CPU garante isolamento de segurança e desempenho entre sites e do estado do navegador, e isolamento de estabilidade e segurança do hardware da GPU.
- O processo de renderização renderiza, anima, rola e encaminha a entrada para um uma única combinação de site e guia. Há vários processos de renderização.
- O processo do navegador renderiza, anima e encaminha a entrada para a interface do navegador. (incluindo a barra de endereço, títulos de guias e ícones) e encaminha todos os entrada para o processo de renderização apropriado. Há um processo de navegador.
- O processo Viz agrega a composição de vários processos de renderização além do processo do navegador. Ela faz a varredura e desenha usando a GPU. Há um processo de visualização.
Sites diferentes sempre acabam em diferentes processos de renderização.
Várias guias ou janelas do navegador do mesmo site geralmente ficam em renderização diferente processos, a menos que as guias estejam relacionadas, como abrir a outra. Sob forte pressão de memória em computadores, o Chromium pode colocar várias guias do mesmo site para o mesmo processo de renderização, mesmo que não estejam relacionados.
Em uma única guia do navegador, frames de diferentes sites estão sempre em processos de renderização diferentes. mas os frames do mesmo site estão sempre no mesmo processo de renderização. Da perspectiva da renderização, a vantagem importante de ter vários processos de renderização é que os iframes entre sites e as guias tenham isolamento de desempenho e se relacionam entre si. Além disso, as origens podem aceitar ainda mais isolamentos.
Existe exatamente um processo Viz para todo o Chromium, já que geralmente há apenas uma GPU e uma tela para desenhar.
Separar o Viz em um processo próprio é bom para estabilidade diante de bugs no Drivers ou hardware da GPU. Também é bom para isolamento da segurança, o que é importante para APIs de GPU como Vulkan e segurança em geral.
Como o navegador pode ter muitas guias e janelas, e todos eles têm pixels de interface do navegador para desenhar, você pode se perguntar: por que existe exatamente um processo de navegador? O motivo é que apenas um deles é focado por vez. na verdade, as guias não visíveis do navegador são desativadas na maioria das vezes e descartam toda a memória da GPU. No entanto, recursos complexos de renderização de IU do navegador estão sendo implementados cada vez mais nos processos de renderização (conhecidos como WebUI). Isso não acontece por motivos de isolamento do desempenho, mas para aproveitar a facilidade de uso do mecanismo de renderização da web do Chromium.
Em dispositivos Android mais antigos, o processo de renderização e do navegador são compartilhados quando usados em um WebView. Em geral, isso não se aplica ao Chromium no Android, apenas ao WebView. No WebView, o processo do navegador também é compartilhado com o app de incorporação, e a WebView tem apenas um processo de renderização.
Às vezes, também há um processo utilitário para decodificar conteúdo de vídeo protegido. Esse processo não é descrito nos diagramas anteriores.
Linhas de execução
As linhas de execução ajudam a alcançar o isolamento do desempenho e a capacidade de resposta apesar das tarefas lentas. carregamento em paralelo de pipelines e vários armazenamentos em buffer.
- A linha de execução principal executa scripts, o loop de eventos de renderização, o ciclo de vida do documento,
teste de hits, envio de eventos de script e análise de HTML, CSS e outros formatos de dados.
- Os principais auxiliares de linha de execução realizam tarefas, como criar bitmaps e blobs de imagem que exigem codificação ou decodificação.
- Web Workers script de execução e um loop de evento de renderização para OffscreenCanvas.
- A linha de execução combinável processa eventos de entrada.
realiza rolagem e animações de conteúdo da web,
calcula a camada ideal de conteúdo da Web em camadas,
e coordena decodificação de imagens, worklets de pintura e tarefas rasterizadas.
- Os auxiliares de linha de execução do criador coordenam as tarefas de varredura do Viz, e executar tarefas de decodificação de imagem, worklets de pintura e varredura de substituto.
- Decodificação de linhas de execução de mídia, demuxer ou saída de áudio processam e sincronizam streams de vídeo e áudio. Lembre-se de que o vídeo é executado em paralelo com o pipeline de renderização principal.
Separar as linhas de execução principal e do compositor é fundamental para isolamento de desempenho de animação e rolagem do trabalho da linha de execução principal.
Há apenas uma linha de execução principal por processo de renderização, mesmo que várias guias ou frames do mesmo site acabem no mesmo processo. No entanto, existe um isolamento de desempenho do trabalho realizado em várias APIs de navegador. Por exemplo, a geração de bitmaps e blobs de imagem na API Canvas é executada em uma linha de execução auxiliar da linha de execução principal.
Da mesma forma, há apenas um thread de compositor por processo de renderização. Geralmente, não é um problema ter apenas um, porque todas as operações realmente caras no thread do compositor são delegados a linhas de execução de worker do compositor ou ao processo Viz, Esse trabalho pode ser feito em paralelo com roteamento de entrada, rolagem ou animação. As linhas de execução de worker do criador coordenam as tarefas executadas no processo Viz. mas aceleração de GPU em todos os lugares podem falhar por motivos que estão fora do controle do Chromium, como bugs de drivers. Nessas situações, a linha de execução de worker faz o trabalho em um modo substituto na CPU.
O número de threads de worker do compositor depende dos recursos do dispositivo. Por exemplo, os computadores geralmente usam mais linhas de execução, já que elas têm mais núcleos de CPU e têm menos limitações de bateria do que os dispositivos móveis. Este é um exemplo de aumentar e reduzir o escalonamento vertical.
A arquitetura de encadeamento do processo de renderização é uma aplicação de três padrões de otimização:
- Conversas auxiliares: envie subtarefas de longa duração a outras linhas de execução para manter a linha de execução pai responsiva a outras solicitações simultâneas. A linha de execução principal linhas de execução auxiliares e compositor são bons exemplos dessa técnica.
- Armazenamento em buffer múltiplo: mostrar conteúdo renderizado anteriormente ao renderizar conteúdo novo, para ocultar o latência de renderização. O thread do compositor usa essa técnica.
- Carregamento em paralelo do pipeline: execute o pipeline de renderização em vários lugares ao mesmo tempo. É assim que a rolagem e a animação podem ser rápidas: mesmo que um a atualização da renderização da linha de execução principal está acontecendo, a rolagem e a animação podem são executados em paralelo.
Processo do navegador
- A linha de execução de renderização e composição responde a entradas na interface do navegador. encaminha outras entradas para o processo de renderização correto; mostra e pinta a interface do navegador.
- Os auxiliares de linha de execução de renderização e composição executar tarefas de decodificação de imagem e rasterizar ou decodificar substituto.
A renderização do processo do navegador e a linha de execução de criação são semelhantes ao código e à funcionalidade de um processo de renderização, exceto que o thread principal e o thread do compositor são combinados em um. Existe apenas uma linha de execução necessária nesse caso, porque não há necessidade de isolamento de desempenho de tarefas de linha de execução principais longas, já que não existem por padrão.
Processo de visualização
- Os rasters da linha de execução principal da GPU mostram listas e frames de vídeo em blocos de textura da GPU. e desenha frames do compositor na tela.
- O thread do compositor de exibição agrega e otimiza a composição de cada processo de renderização. além do processo do navegador, em um único frame do compositor para apresentação na tela.
A varredura e o desenho geralmente acontecem na mesma linha de execução, porque ambos dependem de recursos da GPU, além de dificultar o uso confiável da GPU em várias linhas de execução. (o acesso multithread mais fácil à GPU é uma das motivações para desenvolver a nova Vulkan). No Android WebView, há uma linha de execução separada no nível do SO para desenhar. devido à forma como as WebViews são incorporadas a um aplicativo nativo. Outras plataformas provavelmente terão uma conversa no futuro.
O compositor de exibição está em uma linha de execução diferente porque precisa ser responsivo o tempo todo. e não bloquear em nenhuma possível fonte de lentidão na linha de execução principal da GPU. Uma causa de lentidão na linha de execução principal da GPU são chamadas para códigos que não são do Chromium, como drivers de GPU específicos do fornecedor, que podem demorar para serem previstos.
Estrutura do componente
Em cada linha de execução do processo de renderização principal ou do compositor, há componentes lógicos de software que interagem entre si de forma estruturada.
Principais componentes da linha de execução do processo de renderização
No renderizador do Blink:
- O fragmento de árvore de frames local representa a árvore de frames locais e o DOM nos frames.
- O componente das APIs DOM e Canvas contém implementações de todas essas APIs.
- O executor do ciclo de vida do documento executa as etapas do pipeline de renderização até e incluindo a etapa de confirmação.
- O componente de teste e envio de hits de eventos de entrada executa testes de hits para descobre qual elemento DOM é segmentado por um evento e executa o evento de entrada de envio de algoritmos e comportamentos padrão.
O programador e executor do loop de eventos de renderização decidem o que executar no evento. repetição e quando. Ela programa a renderização para que ocorra em uma cadência correspondente ao dispositivo. exibição.
Os fragmentos da árvore de frames locais são um pouco complicados. Lembre-se de que uma árvore de frames é a página principal e seus iframes filhos de maneira recursiva. Um frame é local para um processo de renderização se for renderizado nesse processo. Caso contrário, ele é remoto.
Imagine a coloração de frames de acordo com o processo de renderização. Na imagem anterior, os círculos verdes são todos frames em um processo de renderização. as laranjas em um segundo e a azul em uma terceira.
Um fragmento de árvore de frames local é um componente conectado da mesma cor em uma árvore de frames. Há quatro árvores de frames locais na imagem: duas para o site A, uma para o site B e uma para o site C. Cada árvore de frames local recebe seu próprio componente do renderizador Blink. O renderizador Blink da árvore de frames local pode ou não estar no mesmo processo de renderização que outras árvores de frames locais. Ele é determinado pela forma como os processos de renderização são selecionados, conforme descrito anteriormente.
Estrutura de linha de execução do compositor do processo de renderização
Os componentes do compositor do processo de renderização incluem:
- Um gerenciador de dados que mantém uma lista de camadas compostas, listas de exibição e árvores de propriedades.
- Um executor do ciclo de vida que executa as funções de animação, rolagem, composição, varredura e decodificar e ativar as etapas do pipeline de renderização. Lembre-se de que a animação e a rolagem podem ocorrer tanto na linha de execução principal quanto no compositor.
- Um gerenciador de testes de hit e de entrada realiza o processamento de entradas e o teste de hits na resolução de camadas compostas. para determinar se gestos de rolagem podem ser executados no encadeamento do compositor, e qual será o destino dos testes de hit do processo de renderização.
Exemplo de arquitetura na prática
Neste exemplo, há três guias:
Guia 1: foo.com
<html>
<iframe id=one src="foo.com/other-url"></iframe>
<iframe id=two src="bar.com"></iframe>
</html>
Guia 2: bar.com
<html>
…
</html>
Guia 3: baz.com
html
<html>
…
</html>
O processo, linha de execução e estrutura de componentes dessas guias tem a seguinte aparência:
Vamos examinar um exemplo de cada uma das quatro tarefas principais de renderização. Lembrete:
- Renderizar o conteúdo em pixels na tela.
- Animar efeitos visuais no conteúdo de um estado para outro.
- Rolar em resposta à entrada.
- Rotear a entrada de forma eficiente para os lugares certos, para que os scripts do desenvolvedor e outros subsistemas possam responder.
Para renderizar o DOM alterado para a guia 1:
- Um script de desenvolvedor altera o DOM no processo de renderização para foo.com.
- O renderizador Blink informa ao compositor que ele precisa de uma renderização para ocorrer.
- O compositor informa ao Viz que é necessária uma renderização para ocorrer.
- O Viz sinaliza o início da renderização de volta para o compositor.
- O compositor encaminha o sinal inicial para o renderizador Blink.
- O executor de loop do evento da linha de execução principal executa o ciclo de vida do documento.
- A linha de execução principal envia o resultado para a linha de execução do compositor.
- O executor do loop de eventos do compositor executa o ciclo de vida de composição.
- Todas as tarefas de varredura são enviadas ao Viz para varredura (geralmente há mais de uma dessas tarefas).
- O Viz faz a varredura do conteúdo na GPU.
- O Viz confirma a conclusão da tarefa de varredura. Observação: o Chromium geralmente não espera a conclusão da varredura, e, em vez disso, usa algo chamado token de sincronização que precisa ser resolvido por tarefas de varredura antes da execução da etapa 15.
- Um frame do compositor é enviado para o Viz.
- O Viz agrega os frames do compositor para o processo de renderização de foo.com. o processo de renderização bar.com iframe e a interface do navegador.
- O Viz programa um desenho.
- O Viz desenha o frame do compositor agregado na tela.
Para animar uma transição de transformação CSS na segunda guia:
- O thread do compositor para o processo de renderização de bar.com marca uma animação. no loop de eventos do compositor mutando as árvores de propriedades existentes. Em seguida, isso executa novamente o ciclo de vida do compositor. Tarefas de varredura e decodificação podem ocorrer, mas não estão descritas aqui.
- Um frame do compositor é enviado para o Viz.
- O Viz agrega os frames do compositor para o processo de renderização de foo.com, para o processo de renderização bar.com e para a interface do navegador.
- O Viz programa um desenho.
- O Viz desenha o frame do compositor agregado na tela.
Para rolar a página da Web na terceira guia:
- Uma sequência de eventos
input
(mouse, toque ou teclado) ocorre no processo do navegador. - Cada evento é roteado para o thread do compositor do processo de renderização do baz.com.
- O compositor determina se a linha de execução principal precisa saber sobre o evento.
- Se necessário, o evento é enviado para a linha de execução principal.
- A linha de execução principal dispara listeners de eventos
input
(pointerdown
,touchstar
,pointermove
,touchmove
ouwheel
) para ver se os listeners vão chamarpreventDefault
no evento. - A linha de execução principal retorna se
preventDefault
foi chamado para o compositor. - Caso contrário, o evento de entrada será enviado de volta para o processo do navegador.
- O processo do navegador a converte em um gesto de rolagem, combinando-a com outros eventos recentes.
- O gesto de rolagem é enviado novamente ao thread do compositor do processo de renderização de baz.com.
- A rolagem é aplicada nesse local, e o thread de compositor para bar.com
processo de renderização marca uma animação no loop de evento do compositor.
Em seguida, ele modifica o deslocamento de rolagem nas árvores de propriedade e executa novamente o ciclo de vida do compositor.
Ele também instrui a linha de execução principal a disparar um evento
scroll
(não mostrado aqui). - Um frame do compositor é enviado para o Viz.
- O Viz agrega os frames do compositor para o processo de renderização de foo.com. o processo de renderização bar.com e a interface do navegador.
- O Viz programa um desenho.
- O Viz desenha o frame do compositor agregado na tela.
Para encaminhar um evento click
em um hiperlink no iframe #two na primeira guia:
- Um evento
input
(mouse, toque ou teclado) chega ao processo do navegador. Ela realiza um teste de hit aproximado para determinar se o processo de renderização do iframe bar.com deve receber o clique e enviá-lo para lá. - A linha de execução do compositor para bar.com roteia o evento
click
para a linha de execução principal para bar.com e programa uma tarefa de loop de evento de renderização para processá-la. - O processador de eventos de entrada dos testes de hit da linha de execução principal de bar.com para determinar qual
O elemento DOM no iframe foi clicado e dispara um evento
click
para que os scripts observem. Ou seja, não ouvirápreventDefault
e a pessoa navegará para o hiperlink. - Após o carregamento da página de destino do hiperlink, o novo estado é renderizado, com etapas semelhantes às "renderizar o DOM alterado" exemplo anterior. Essas alterações subsequentes não são descritas aqui.
Para viagem
Pode levar muito tempo para lembrar e internalizar como a renderização funciona.
A conclusão mais importante é que o pipeline de renderização, após uma análise modularização e atenção aos detalhes, foi dividida em vários componentes independentes. Esses componentes foram divididos em paralelo e linhas de execução para maximizar performance escalonável e de extensibilidade.
Cada componente desempenha um papel fundamental para garantir o desempenho e os recursos aplicativos da Web modernos.
Continue lendo sobre as principais estruturas de dados, que são tão importantes para o RenderingNG quanto os componentes de código.
Ilustrações de Una Kravets.