Migrando nosso DOM para Zig – Blog

PUBLICIDADE

Migrando nosso DOM para Zig - Blog

Karl Seguin

Engenheiro de software

DR

Substituímos o LibDOM por nossa própria implementação DOM baseada em Zig. O design original criou atrito entre V8, nossa camada Zig e LibDOM, especialmente em torno de eventos, elementos personalizados e ShadowDOM. Após seis meses de prototipagem nas horas vagas, construímos o zigdom: um DOM mais enxuto e coeso que nos dá controle total sobre memória, eventos e melhorias futuras. Também trocamos o html5ever para análise e adicionamos snapshots V8 para reduzir o tempo de inicialização. Há ganhos de desempenho de um dígito%, mas a verdadeira vitória é uma base de código unificada que é mais fácil de estender.

Por que substituímos o LibDOM

Em alto nível, a base de código Lightpanda pode ser descrita como uma camada Zig situada entre V8 e LibDOM. Quando o JavaScript é executado, como o V8, chama a camada Zig, que então encaminha a solicitação para o objeto de documento LibDOM subjacente e, em seguida, encaminha o resultado de volta para o V8. Ao usar LibDOM, obtivemos uma implementação de DOM robusta e bastante abrangente com esforço mínimo.

No entanto, à medida que trabalhávamos para aumentar a compatibilidade com sites existentes, sentíamos um atrito cada vez maior entre nossas três camadas. Um exemplo é o sistema de eventos integrado ao LibDOM. Isto provou ser estranho para expandir além dos eventos baseados em DOM (por exemplo, eventos de entrada) ou mesmo apenas borbulhar eventos DOM para nossa implementação de janela baseada em Zig. Outro desafio maior foi integrar o suporte a Custom Elements e ShadowDOM, escrito em Zig, com LibDOM. Finalmente, havia alguma preocupação sobre a falta de coesão em relação a coisas como gerenciamento de memória e como isso impactaria possíveis mudanças futuras, como melhor suporte a multithreading.

Se recomeçarmos a integração do zero, sabendo o que sabemos agora, provavelmente conseguiríamos evitar a maior parte do atrito que estamos vendo atualmente. Embora modifiquemos o LibDOM conforme necessário, uma abordagem seria integrar V8 e LibDOM diretamente, aplicando correções e adições diretamente ao LibDOM. Mas, como escrevemos antes, as discussões e protótipos que construímos sempre tenderam a substituir o LibDOM por uma implementação Zig personalizada.

ziguezague

O trabalho em um protótipo para ter um DOM baseado em Zig começou há cerca de seis meses. Este foi um esforço casual em nosso tempo livre. No espírito de experimentação, este protótipo também substituiu o V8 pelo . Em meados de novembro, sentimos que o protótipo havia abordado incógnitas suficientes para começar a integrá-lo ao Lightpanda (com V8). Felizmente, a portabilidade de recursos foi relativamente simples; commits para o branch geralmente podem ser portados para o branch.

O design é simples. A tem uma lista vinculada de filhos e um opcional. Além disso, a possui um campo de união marcado para representar o tipo de nó e um campo para capturar seu supertipo:

Como um site moderno pode ter dezenas de milhares de nós e milhares de elementos, obviamente nos preocupamos com o tamanho dos nossos , e . É por isso que todo tipo em nosso sindicato é um ponteiro. Isso significa que quando criamos uma div, precisamos alocar Div, HTMLElement, Element, Node e EventTarget. Mas em vez de fazer cinco alocações separadas, fazemos uma grande alocação para o tamanho total e parcelamos.

Outra área onde conseguimos otimizar nosso caso de uso é analisar/carregar preguiçosamente certas propriedades. Embora um site possa ter milhares de elementos, a maior parte do JavaScript acessará apenas as classes, estilos, relLists, conjunto de dados, etc., de alguns elementos. Em vez de armazená-los em cada elemento, mesmo como contêineres vazios carregados lentamente, eles são anexados a uma página em um elemento -> pesquisa de propriedade. Embora isso adicione sobrecarga de pesquisa, remove cerca de 6 ponteiros de cada elemento.

A verdadeira vantagem é ter um design mais coeso para eventos, elementos personalizados e ShadowDOM e uma base mais simples para melhorias futuras. Dito isto, o desempenho, tanto em termos de uso de memória quanto de carga da CPU, foi ligeiramente melhorado (ambas melhorias de % de um dígito).

html5ever

Vimos benefícios em escrever nossa própria implementação de DOM, mas não nosso próprio analisador de HTML. Para isso, recorremos ao escrito em Rust. Quase esqueci de mencionar isso neste post porque a experiência foi tão indolor e funcionou desde o início que não tive que pensar nisso por um tempo. Você configura o html5ever com vários retornos de chamada (para criar um nó, anexar um nó a um pai, criar texto, etc.), alimentá-lo com seu HTML e pronto. Meu Rust é muito ruim, mas escrever uma ligação C para ele foi administrável.

Bônus – Instantâneo V8

Algumas das transferências eram tediosas. Para mudar o ritmo, reservei um tempo para ver como poderíamos aproveitar os snapshots do V8. Resumindo, sempre que você cria um ambiente V8 para executar código, é necessário fazer muitas configurações. Cada tipo (centenas) com todas as funções e propriedades precisa ser registrado no ambiente V8. Para uma página simples, isso pode representar de 10 a 30% do tempo total. Os snapshots V8 permitem configurar um pseudoambiente antecipadamente, extrair um snapshot (um blob binário) e usar esse blob para inicializar e acelerar ambientes futuros.

Quando no modo de depuração, geramos o instantâneo na inicialização. No modo de liberação, o instantâneo é gerado em tempo de compilação e incorporado ao binário, reduzindo o tempo de inicialização e a memória. O impacto geral depende do custo relativo de configuração do ambiente versus processamento da página. Sites complexos que carregam centenas de scripts externos provavelmente não serão beneficiados. Mas esperamos que melhorias incrementais sejam somadas e, pelo menos, ajudem a equilibrar o custo de desempenho de novos recursos e a complexidade.

Agente de codificação de IA

Este foi o primeiro grande recurso que desenvolvi com a ajuda de um agente de codificação de IA – especificamente Claude. A experiência foi positiva, mas não perfeita. Pessoalmente, sempre gostei de participar de revisões de código/PRs. Posso passar horas todos os dias revisando PRs, então trabalhar com Claude é divertido para mim. Se ler código não é algo que você considera divertido, pode ser uma experiência frustrante.

Quase sempre fiquei impressionado com a qualidade do código escrito e a “compreensão” que Claude exibiu. Estou apenas supondo aqui, mas devo imaginar que construir um DOM, algo que possui uma especificação muito explícita, toneladas de documentação e muitas implementações, era uma tarefa ideal para um agente de codificação.

Dito isto, penso que este é, antes de mais nada, um exercício de revisão de código, e o Claude CLI carece nesse aspecto. Ao tentar entender e refletir sobre uma mudança, você precisa de uma interface confortável que permita navegar e acessar qualquer contexto que esteja faltando. Qualquer coisa além de algumas linhas torna-se difícil de revisar, especialmente porque é apresentado para você aceitar uma peça de cada vez.

No final das contas, é uma ferramenta que complementa minhas próprias habilidades.

O que vem a seguir

Implementar nosso próprio DOM do zero deve facilitar a adição de novos recursos e melhorias. Algo que já vimos com melhor elemento personalizado e suporte para ShadowRoot. Muitos dos benefícios não vêm diretamente da implementação de um novo DOM, mas simplesmente de ter uma base de código mais coesa. Para nós, expandir o uso do Zig fazia mais sentido.

O zigdom agora está incorporado ao ramo principal do Lightpanda. Se você quiser ver como estruturamos o nó, o elemento e o sistema de eventos no Zig, confira o arquivo .


Karl Seguin

Engenheiro de software

Karl é engenheiro de software e criador de bibliotecas Zig de código aberto populares, como http.zig ou websocket.zig. Karl escreve sobre programação há anos em seu blog openmymind.net e é autor de Learning Zig, uma série de artigos para ajudar outros desenvolvedores a aprender a linguagem. Na Lightpanda, ele trabalha na construção do mecanismo principal do navegador.

Fonte: theverge

Mais recentes

PUBLICIDADE

WP Twitter Auto Publish Powered By : XYZScripts.com