Compilando Código em JIT em 5μs
A compilação JIT para bancos de dados está sendo reavaliada com abordagens ultrarrápidas de “copy-and-patch” que conseguem gerar código de máquina em microssegundos, evitando a alta latência do LLVM e ainda assim trazendo ganhos consideráveis sobre a interpretação. Os comentaristas ponderam esses ganhos de desempenho contra preocupações de segurança relacionadas ao relaxamento de políticas rígidas de W^X, à complexidade e à superfície de ataque dos JITs (especialmente para entradas não confiáveis) e aos domínios limitados em que JIT compensa o custo extra de portabilidade e manutenção. Vários apontam frameworks JIT mais leves, técnicas manuais de JIT em linguagens como Common Lisp e até geração de código assistida por LLM como formas de tornar JITs especializados mais viáveis.
Segurança de JIT e W^X
- Um lado argumenta que JIT é inerentemente menos seguro porque requer memória gravável e executável, enfraquecendo políticas rígidas de W^X e possibilitando explorações mais poderosas.
- Outros contrapõem que JITs modernos normalmente alocam páginas RW, escrevem o código e depois as convertem para RX, de modo que W^X é preservado por mapeamento.
- Há debate sobre se isso tem “implicações em todo o sistema” ou se é apenas uma escolha de hardening por processo; alguns dizem que o SO já precisa gerenciar tais permissões, outros enfatizam que permitir execução dinâmica de código aumenta o impacto de bugs.
- São citados exemplos de plataformas que restringem fortemente JIT (iOS, GrapheneOS) e de técnicas como verificação de bytecode e marcação de memória por hardware para tornar JIT mais seguro.
- Vários comentários observam que JITs aumentam a superfície de ataque do processo hospedeiro (especialmente ao executar entrada não confiável, como navegadores ou consultas de banco de dados), mas não concedem novas capacidades além das que o processo já possui.
- ROP e técnicas semelhantes são invocados para argumentar que, se um processo pode executar qualquer código, a execução arbitrária de código é efetivamente possível com ou sem JIT.
Projeto de JIT, desempenho e LLVM vs abordagens leves
- Vários comentários enfatizam que JITs baseados em LLVM têm alta latência e podem ser inadequados para cargas de trabalho que precisam compilar muito rápido (por exemplo, consultas do Postgres).
- Abordagens leves de JIT — modelos copy-and-patch, pequenas bibliotecas (por exemplo, SLJIT, GNU Lightning, AsmJit) ou backends personalizados — trocam menos otimizações por tempo de compilação muito menor.
- Benchmarks discutidos nas postagens vinculadas mostram que JITs simples podem obter ganhos significativos de velocidade sobre interpretação com tempo de compilação desprezível, enquanto o LLVM pode gastar dezenas de milissegundos compilando.
- Comentários focados em bancos de dados destacam que a otimização do plano de consulta (por exemplo, ordenação de joins) importa muito mais do que o JIT; a granularidade atual do JIT do Postgres (por expressão, não por pipeline) é vista como uma limitação fundamental.
Geração de código baseada em templates é “JIT de verdade”?
- Alguns descartam a abordagem como “apenas templates de assembly”, mas outros rebatem que:
- Compiladores não otimizadores ainda são compiladores.
- Copy-and-patch é uma técnica de JIT padrão e legítima.
- São dados exemplos em que geradores de código muito simples (sem alocação de registradores, com forte uso de stack) ficam apenas algumas vezes mais lentos do que binários altamente otimizados com -O3, mas ainda muito mais rápidos do que interpretadores.
Common Lisp e JIT manual
- Implementações de Common Lisp são discutidas como um meio-termo:
- Algumas compilam todo o código antecipadamente; outras oferecem bytecode com compilação nativa opcional.
evale compile-on-load são apresentados como uma forma de JIT.- Há chaves para alternar entre interpretador e compilador no uso de REPL, trocando tempo de compilação por velocidade de execução.
- Um estilo de “JIT manual” — escolher explicitamente o que compilar para velocidade — é elogiado como um compromisso prático e mais simples.
O papel da IA ao escrever JITs e sistemas complexos
- As opiniões divergem fortemente:
- Alguns dizem que os modelos atuais produzem código ruim em domínios complexos, servindo principalmente para boilerplate, CRUD, ligação de APIs e simples detecção de bugs.
- Outros relatam grandes ganhos de produtividade usando IA para estruturar componentes complexos (incluindo JITs), transformando uma semana de trabalho em horas, desde que um engenheiro competente decomponha as tarefas e revise a saída.
- Há debate sobre:
- Quanto conhecimento de domínio ainda é necessário (muitos dizem “muito”).
- Se a qualidade do código gerado por IA é objetivamente ruim ou apenas estilisticamente diferente.
- O risco de usuários sem experiência entregarem código escrito por IA aparentemente bom, mas frágil.
Outras aplicações e observações
- Comentadores sugerem usar ideias semelhantes de JIT baseada em stencil para firewalls e geração dinâmica de eBPF.
- Motores de regex, sistemas históricos de BASIC e Lisp, e SGBDs modernos são mencionados como domínios clássicos ou naturais para JIT.
- A discussão também aborda brevemente interpretadores formalmente verificados e binários estáticos assinados como uma alternativa extrema de segurança ao JIT e ao código nativo.