7 pontos por GN⁺ 3 시간 전 | Ainda não há comentários. | Compartilhar no WhatsApp
  • Quando vazamentos e falhas continuaram ocorrendo em Zig, que não tem segurança de memória, o Bun migrou 535.496 linhas de código para Rust com 64 agentes de IA, reduzindo para 11 dias um trabalho que levaria de 1 a 2 anos
  • O ponto de partida do sucesso foi um PORTING.md de 600 linhas, e o processo seguiu esta ordem: conversão paralela por arquivo, duas revisões adversariais, correção de erros de compilação, testes locais e aprovação no CI
  • Para gerar 6.500 commits, foram usados US$ 165 mil em preços de API, além de 5,9 bilhões de tokens de entrada sem cache, 690 milhões de tokens de saída e 72 bilhões de leituras de tokens de entrada em cache
  • Se fosse manual, estimou-se que 3 engenheiros com profundo conhecimento da base de código teriam de parar por cerca de 1 ano de melhorar o produto, corrigir bugs e falhas de segurança e desenvolver novos recursos, o que tornaria a própria reescrita difícil de viabilizar
  • Para repetir a mesma abordagem, é preciso ter um engenheiro que entenda profundamente a base de código, uma suíte de testes forte o suficiente para confiar no resultado e disposição para bancar o custo em tokens mesmo sem garantia de sucesso

Por que o Bun escolheu uma reescrita em Rust

  • O Bun é um projeto de produção complexo que oferece vários recursos além de um runtime JavaScript
    • Transformação, bundling e minificação de JavaScript, TypeScript e CSS
    • Test runner e gerenciador de pacotes compatível com npm
    • Resolução de módulos, cliente WebSocket, implementação de Node.js e vários módulos
  • Tem 22 milhões de downloads mensais, é dependência do Claude Code e do OpenCode, e recebe suporte direto de Vercel, Railway e DigitalOcean
  • Como Zig não é uma linguagem com segurança de memória, mesmo nas versões mais recentes do Bun continuavam ocorrendo vazamentos de memória, falhas causadas por problemas de memória e escritas fora dos limites do heap
    • A equipe do Bun aplicou patches no compilador Zig e introduziu testes de vazamento de memória de ponta a ponta, mas não conseguiu eliminar o problema
    • No processo de lidar ao mesmo tempo com a vida útil de valores com garbage collection e de valores gerenciados manualmente, surgiam pequenos vazamentos e falhas intermitentes
    • Era preciso revisar, em cada alocação de memória, onde ela seria liberada, se havia double-free, o tratamento de exceções JavaScript e a visibilidade de ponteiros para o scanner conservador de stack
  • Em Rust seguro, use-after-free e double-free viram erros de compilação, e problemas de esquecer liberações em caminhos de erro podem ser tratados com limpeza automática baseada em Drop
  • Também foi avaliada a possibilidade de introduzir ponteiros inteligentes ao estilo Rust no código do Bun, mas isso teria pior usabilidade do que Rust e não ofereceria as mesmas garantias

Por que projetos de reescrita costumam demorar

  • Durante a reescrita, novos recursos continuam sendo adicionados à base original, então a conclusão tende a ser adiada repetidamente
    • Um trabalho estimado em 9 meses pode ainda precisar de mais 6 meses ao fim desses 9 meses
    • Mesmo após 15 meses, ainda podem restar vários meses de trabalho só para alcançar os novos recursos
    • Mesmo com sorte, seria necessário congelar recursos por 2 meses e concluir em cerca de 18 meses, fazendo a estimativa inicial de 9 meses virar mais de 2 anos
  • O código Zig do Bun, sem contar comentários, tem 535.496 linhas, então estimou-se que uma pequena equipe de engenharia levaria cerca de 1 ano para migrá-lo para outra linguagem
  • Como não era realista passar 1 ano sem melhorias visíveis para o usuário, decidiu-se testar com a Fable se seria possível validar em uma semana a viabilidade da migração para Rust

Projeto prévio e validação da migração

  • Na primeira etapa, discutiu-se com Claude por cerca de 3 horas como mapear padrões de Zig para equivalentes próximos em Rust, e isso foi organizado em um PORTING.md com 600 linhas
  • As diretrizes de migração incluíam restrições específicas para preservar a estrutura de execução existente do Bun
    • Não usar tokio, rayon, hyper, async-trait, futures
    • Proibir módulos com acesso a I/O como std::fs, std::net, std::process
    • Como o Bun controla seu próprio event loop e suas system calls, usar callbacks e máquinas de estado como no Zig existente em vez de async fn
    • Se houver conflito com o borrow checker, armazenar os valores escalares necessários em variáveis locais, encerrar o empréstimo e então emprestar novamente
    • Proibir o uso de ponteiros brutos para contornar o borrow checker e deixar notas de migração nos pontos em que a estrutura foi alterada
  • Dos 1.448 arquivos no total, 3 arquivos foram reescritos primeiro e depois Claude fez duas revisões adversariais em uma sessão separada da sessão de alteração

Trabalho paralelo com 64 agentes de IA

  • O trabalho foi dividido para que os arquivos pudessem ser tratados de forma independente, e 64 agentes de IA foram executados em paralelo
  • No início, houve conflitos porque vários agentes mexiam ao mesmo tempo no mesmo estado do repositório
    • Um agente executava git stash, depois outro executava git stash pop e git reset HEAD --hard
    • Atribuir um worktree separado a cada agente esbarrava na falta de espaço em disco por causa do tamanho do repositório do Bun, além da restrição de que as mudanças precisariam ser compiladas juntas no fim
  • O workflow foi corrigido para proibir comandos Git como git stash e git reset, exceto comandos que faziam commit imediato de arquivos específicos, e também para impedir o uso de cargo e de comandos com longa duração
  • No fim, o trabalho foi dividido em 4 worktrees, cada um com 16 instâncias do Claude fazendo commits e push de arquivos
  • Em dois dias, os agentes migraram 535.496 linhas de código Zig, e cada commit passou por duas revisões adversariais antes de ser aplicado

Correção de erros de compilação e testes

  • A conversão inicial terminou, mas o código não compilava, então Claude corrigiu os erros por crate, a unidade superior de compilação em Rust
  • O título da etapa fala em cerca de 1.600 erros de compilação, mas a citação diz que, ao resolver dependências circulares, surgiram cerca de 16.000 erros
  • O processo de correção também foi paralelizado
    • Executar cargo check em cada crate
    • Agrupar a saída por arquivo e salvar os arquivos de erro
    • Corrigir todos os erros de compilação daquele crate
    • Dois revisores adversariais verificam as mudanças
    • Um agente responsável por correções aplica o resultado da revisão
  • Os agentes corrigiram erros de compilação da meia-noite até 11h30 da manhã sem intervenção humana
  • Depois disso, foram necessários cerca de dois dias para fazer a enorme suíte de testes rodar localmente sem erros de compilação, e mais alguns dias para corrigir testes que falhavam e passar no CI
  • Depois que todos os testes passaram e o funcionamento foi confirmado, as mudanças foram mescladas, totalizando 11 dias do planejamento à conclusão
    • Cerca de 550 mil linhas de código migradas
    • 6.500 commits
    • 64 agentes usados

Custos e comparação com trabalho manual

  • Pelo preço da API da Fable, o custo total da reescrita foi de US$ 165 mil
    • 5,9 bilhões de tokens de entrada sem cache
    • 690 milhões de tokens de saída
    • 72 bilhões de leituras de tokens de entrada em cache
  • A Anthropic vende tokens de API com margem, então o custo interno real seria menor
  • O custo de API é parecido com o salário-base anual de um engenheiro de software corporativo de nível intermediário nos EUA, mas avalia-se que um único engenheiro nessa faixa salarial não conseguiria entregar o mesmo resultado em 11 dias
  • Isso também bate com a avaliação de Mitchell Hashimoto de que a Fable se destaca especialmente em tarefas difíceis e concentradas com uma função de recompensa clara
  • Se fosse manual, seriam necessários cerca de 3 engenheiros que conhecessem totalmente a base de código por aproximadamente 1 ano
    • Nesse período, seria difícil avançar em compatibilidade com Node.js, correção de bugs e falhas de segurança e implementação de novos recursos
    • A alternativa realista seria não reescrever e continuar corrigindo os bugs de memória existentes

Condições para aplicar isso em outros projetos

  • Se a IA consegue reduzir para uma semana uma reescrita ou migração que levaria 1 ano, projetos antes difíceis de considerar também passam a ser viáveis
  • Para reutilizar o fluxo de trabalho do Bun, são necessárias três condições
    • Um engenheiro que conheça muito bem a base de código e tenha forte disposição para conduzir o trabalho
    • Uma suíte de testes forte o bastante para que passar nos testes seja uma base confiável do funcionamento real
    • Disposição para investir um custo considerável em tokens mesmo sem saber de antemão se dará certo
  • Como tarefas repetitivas como migração de código costumam ser relativamente bem tratadas por LLMs, as chances de sucesso são altas se houver bons testes e um engenheiro para estruturar o problema
  • Nem todo projeto precisa de US$ 165 mil
    • Em projetos mais simples, o custo pode ser menor
    • É possível usar o modelo mais caro no planejamento de alto nível e modelos mais baratos para codificação e revisão
  • As migrações baseadas em IA estão ficando mais rápidas, mas velocidades como a do Bun só podem ser alcançadas em projetos bem projetados do ponto de vista de engenharia

Ainda não há comentários.

Ainda não há comentários.