Construindo o Bencher em 2026: Open Source, Autofinanciado e Convertido aos Agentes

Everett Pompeii
Este ensaio foi submetido originalmente ao The Pragmatic Engineer’s How Software Engineering is Changing Essay Challenge em 04 de outubro de 2026.
Este ano marcou uma mudança radical na forma como eu construo software. Sou staff software engineer. Nos últimos seis anos, trabalhei profissionalmente com Rust tanto em um unicórnio apoiado pela YC e pela a16z quanto em uma empresa da Fortune 500. Como um desenvolvedor C++ em recuperação, me vi atraído pela profundidade e pela habilidade que o Rust exigia. Eu tinha me tornado um artesão especialista em cinzelar à mão software de sistemas de tempo real. Nos últimos dez meses, tive que enterrar essa identidade. Embora meu cargo ainda diga “engenheiro de software”, meu trabalho agora é o de um “engenheiro de contexto”.
Nos últimos quatro anos, passei minhas noites e fins de semana construindo um negócio open source e autofinanciado, o Bencher. O Bencher é uma plataforma de benchmarking contínuo que ajuda engenheiros de software de sistemas a detectar regressões de desempenho antes que sejam mescladas. É preciso um conjunto de ferramentas para isso: uma CLI, um servidor de API e uma interface web de console no frontend. Cada um desses componentes foi escrito, salvo um erro de arredondamento, por mim. Tive alguns colaboradores open source notáveis ao longo dos anos, mas a grande maioria do Bencher, o projeto open source, e 100% do Bencher, o negócio, foram projetados e implementados por mim mesmo.
Nesses quatro anos, eu não vivi debaixo de uma pedra. Fiquei noivo, me casei e tive meu primeiro filho. Eu levava semanas e às vezes meses para concluir a implementação de uma funcionalidade grande e colocá-la no ar. Eu tinha que conciliar desenvolvimento e suporte. O Bencher já tinha muitos usuários, então eu passava um bom tempo respondendo perguntas e corrigindo um ou outro bug.
Lá em 2022, meu uso de LLMs consistia na versão freeware para Rust do TabNine, uma ferramenta de desenvolvimento de autocompletar com tab criada por um estudante, que também foi um dos primeiros estagiários da OpenAI, trabalhando em um projetinho curioso chamado Codex. Quando o GitHub Copilot foi lançado e adicionou suporte não oficial a Rust, abri a carteira e paguei os $10/mês por uma licença pessoal.
Era tosco. Mas ainda parecia um pouco com mágica. Lembro de ficar impressionado, logo depois que o chat foi adicionado à extensão do GitHub Copilot para o VSCode, com o quão bom ele era em criar macros procedurais em Rust. Normalmente eu tinha que ajustar um pouco a saída, mas algumas vezes ele conseguiu acertar de primeira. Que doideira! Isso era legal e provavelmente ajudou a economizar algum tempo, mas eu ainda trabalhava predominantemente da mesma forma de antes.
A partir daí, fiquei com essa mentalidade de que a Microsoft estava na vanguarda com o GitHub Copilot. Mesmo que esses laboratórios recém-chegados estivessem lançando “agentes” por aí, eu podia confiar que o GitHub Copilot acompanharia se houvesse algo que valesse a pena. Eu ouvia pessoas como Dan Shipper no Lenny’s Podcast, e o relato deles sobre as capacidades dos modelos simplesmente não batia nem com a minha experiência nem com o meu padrão de qualidade.
No início do ano passado, escrevi um post refletindo sobre três anos de desenvolvimento do Bencher, Revisão de Engenharia: Edição 2025. Naquele post, cobri todas as minhas principais decisões de engenharia para construir o Bencher, abrangendo frontend, backend, ambiente de desenvolvimento, CI, e por aí vai. Passei um parágrafo inteiro desabafando sobre o quanto eu tinha sofrido, dois anos antes, para tentar entender a linguagem CUE. Ainda assim, não há uma única menção a IA, LLMs ou mesmo ao Copilot em nenhum lugar daquele texto de 3.500 palavras.
Avance para menos de um ano depois, e lá estou eu me compadecendo com We mourn our craft.
Claude Ajuda a Salvar o Natal
Como muita gente, durante as festas de fim de ano de 2025 tive a chance de usar o Claude Opus 4.5 para valer. Eu estava em Londres visitando a família da minha irmã com minha esposa e nosso filho. Minha irmã tinha acabado de ter gêmeos, então a ideia era que eu estivesse lá para ajudar. Em vez disso, eu estava entrincheirado no andar de cima tentando combater spam de email e ataques DDoS contra o Bencher. O Claude foi superútil para diagnosticar o que estava acontecendo e para idealizar possíveis soluções.
Acabei migrando o Bencher para trás da Cloudflare e configurando o reCAPTCHA. Ainda era eu quem fazia a maior parte do trabalho, mas o Opus 4.5 foi um salto perceptível na capacidade de resolver problemas com muitas restrições de design concorrentes. Se bem que ele sugeriu uma mudança que deixou inutilizável o script de conveniência para instalar a CLI do Bencher por meio dia. Ops.
Ano Novo, Harness Novo
Em janeiro deste ano, eu já vinha ouvindo havia meses o quão impressionante o Claude Code era. Eu tinha adiado experimentá-lo porque o Opus 4 simplesmente não atingia o meu padrão de qualidade para que eu confiasse no seu trabalho. Agora que o Opus 4.5 tinha atingido esse padrão, eu quis experimentar o Claude Code também. O nível de melhoria que vi ao passar do Copilot como harness para o Claude Code foi um salto tão grande quanto passar do Opus 4/GPT-5.2/Gemini 2.5 Pro como modelo para o Opus 4.5.
No meu primeiro fim de semana com o Claude Code, fiz um teste não muito controlado contra o Copilot. Eu queria que o Copilot transformasse um PDF em um audiolivro. Mesmo no “Agent Mode”, o Copilot avançava cinco ou seis passos e então simplesmente parava até eu cutucá-lo de novo. Enquanto isso, o Claude Code estava trabalhando a todo vapor tentando construir um hipervisor personalizado, depois de passar por um Plan mode minucioso. Fiquei absolutamente convencido de que o nível de abstração tinha subido do modelo para o harness e de que o Copilot nunca mais ia conseguir alcançar.
Sonhando com o Bencher Bare Metal
Desde os primeiros dias do Bencher, eu sonhava em construir uma frota de benchmarking bare metal. Os runners de CI tradicionais, por serem máquinas virtuais, são ruidosos demais para fornecer resultados de benchmark consistentes. Você conseguiria detectar, digamos, um aumento de 200% na latência, mas nunca conseguiria detectar de forma confiável um aumento de 20%. Contagens de instruções são uma possibilidade para benchmarking no CI. Elas são, em grande parte, determinísticas. No entanto, contagens de instruções são um proxy para aquilo que realmente importa, o tempo de relógio de parede. Qualquer coisa que rode em uma “simulação de CPU” e cuspa contagens de instruções só pode ter correlação com a velocidade. O problema é que você nunca sabe se ela erra por muito ou por pouco, a menos que realmente meça em bare metal.
Um dos primeiríssimos usuários do Bencher foi o projeto Rustls. Ajudei a contribuir com o Rustls bench runner deles. No entanto, essa não era uma boa base sobre a qual construir uma frota de benchmarking bare metal. Ele ficava em um único host e tratava todas as cargas de trabalho de benchmark como confiáveis. Isso significa nada de PRs vindos de forks e nada de multitenancy. Além disso, a maioria das equipes não quer pagar mais de $100 por mês por servidor de benchmarking bare metal.
Eu tinha considerado usar o GitHub Actions para a camada de orquestração, mas essa abordagem tinha algumas deficiências fundamentais. Para começar, o GitHub Actions Runner é escrito em C#. Isso significa que o coletor de lixo dele pode entrar em ação no meio da sua execução, distorcendo os resultados do seu benchmark. Ah, e não esqueça de desligar o atualizador automático para que ele não entre em ação no meio da execução, mas também não se esqueça dele por tempo demais, senão seus jobs vão parar de rodar!
Mesmo que o GitHub Actions Runner fosse um binário Rust bonitinho e silencioso, o problema mais fundamental era que ele estava atrelado ao GitHub Actions. O Bencher, desde o início, prioriza a CLI. Para o bem ou para o mal, eu nunca quis atrelar o Bencher profundamente demais a nenhum provedor de CI específico. Existe uma Ação do GitHub da CLI do Bencher, mas tudo o que ela faz é instalar a CLI para você. Eu queria que o Bencher Bare Metal funcionasse de qualquer lugar onde a CLI funciona, não apenas no GitHub Actions.
A ideia que tive foi usar imagens OCI para empacotar a carga de trabalho de benchmarking e um sandbox opcional e bem pequeno para executar sempre apenas um job por vez em um determinado host bare metal. A perspectiva de construir isso sozinho, em noites e fins de semana, era assustadora. Com um emprego e uma família, eu teria levado pelo menos um ano indo aos pouquinhos, sozinho.
Construindo o Bencher Bare Metal
Com o Opus 4.5 e o Claude Code em mãos em janeiro deste ano, senti que finalmente conseguia enxergar o caminho prático para construir o Bencher Bare Metal. Mais uma vez abri a carteira, desta vez desembolsando $200/mês pelo plano Claude Max 20x. Provavelmente a melhor despesa empresarial de todos os tempos.
Comecei a produzir a todo vapor e fiz o meu melhor para esgotar o uso do meu plano do Claude toda semana. Parei de escrever código à mão, tanto no Bencher quanto no meu emprego. Nesse ponto, eu ainda iterava em ciclos bem curtos, usando o Plan mode, lendo toda a saída e rodando no modo Accept edits. Eu não confiava no agente para mexer no git/jj nessa época, então eu mesmo cuidava de todo o controle de versão. Eu me via como um Ralph Loop com um humano no loop. Por volta de cinco agentes rodando em paralelo, meu cérebro começava a derreter.
Uma sugestão que eu tinha ouvido era ter agentes separados fazendo a implementação e a revisão, então comecei a fazer revisões adversariais separadas. Essas revisões adversariais realmente pareciam ajudar a melhorar a qualidade da saída. Criei meu próprio bot de revisão no GitHub Actions que usava a chave de API da minha assinatura do Claude Code. Depois, eu fazia meu agente local iterar com esse revisor de CI para poupar ciclos na minha máquina local.
Em algum momento no meio disso, achei que ia fazer o Claude construir seu próprio hipervisor para o sandbox de benchmarking. Então pedi ao Claude para fazer uma revisão adversarial do plano como se fosse o Linus Torvalds, e ele me disse que eu era burro e que aquela era uma ideia muito, muito, muito idiota. Nada de bajulação quando o Linus está no seu contexto! Então descartei esse plano e fui de Firecracker.
O inimigo de um bom benchmarking é a variância, não a velocidade em si. Então, mesmo que o Firecracker adicione overhead como hipervisor, é um overhead muito consistente, principalmente com apenas uma microVM rodando por vez. Isso permite que os runners compartilhados do Bencher Bare Metal tenham ao mesmo tempo multitenancy e resultados de benchmarking muito consistentes. Também trabalhei com o Claude usando o Plan mode para projetar as coisas de modo que o sandbox fosse opcional. Se um usuário quiser rodar no seu próprio servidor dedicado, onde ele de fato confia em todas as cargas de trabalho, ele pode rodar sem o Firecracker com overhead quase zero.
Desenvolver o runner do Bare Metal foi uma grande lição para mim sobre a importância de os agentes terem um ciclo de feedback curto. Mesmo depois que o Opus 4.6 saiu, o Claude parecia ter dificuldade para fazer tudo funcionar de forma consistente. Assim que dei a ele acesso a um ambiente de desenvolvimento com KVM habilitado (necessário para rodar o Firecracker), as coisas realmente começaram a se encaixar. Esses agentes não são oniscientes, eles só são muito persistentes.
O nível de escrutínio a que eu submetia o trabalho do Claude dependia da parte da base de código em que ele estava trabalhando. O código que era puramente do Bare Metal, como o registro OCI e o binário runner, eu revisei só superficialmente. Desde que passasse na revisão adversarial, os testes end-to-end passassem e as coisas não parecessem terríveis demais, eu fazia o merge. Para o código que tocava o núcleo existente, o enfileiramento de jobs e o processamento de relatórios, fui tão minucioso quanto sempre.
No fim de março deste ano, lancei o Bencher Bare Metal como parte da v0.6.0. Para a frota pública de bare metal, eu estava considerando usar o AWS EC2 Bare Metal. No entanto, essas máquinas são ao mesmo tempo gigantescas e apenas ARM. Para corresponder à maioria das cargas de trabalho do mundo real, eu queria máquinas Intel x86 pé de boi. Pesquisei com o Claude para encontrar o melhor lar para a frota que atendesse às restrições de design. Acabamos conseguindo oferecer no Bencher Cloud a Spec intel-v1, que dá aos usuários 4 vCPUs, 48 GB de memória e 128 GB de disco, cobrados por minuto. Em benchmarks bem estruturados, eu obtinha consistentemente <2% de variância entre execuções em toda a frota.
Autenticação de Agentes
Até o Bencher Bare Metal, toda a autenticação era feita com JWTs. JWTs grandes, lindos e incompreensíveis. A autenticação dos runners do Bare Metal era uma chave de API com um prefixo de nome, por ex. bencher_runner_abc123....
No lado do cliente, eu queria dar aos agentes algo com que trabalhar além do próprio token de API JWT do usuário. O meio-termo a que cheguei foi finalmente implementar uma funcionalidade pedida havia muito tempo: a autenticação com escopo de projeto. O Claude me ajudou a criar chaves de API seguras, com prefixo e com escopo de projeto. Essas chaves de API são limitadas às permissões equivalentes ao que o comando bencher run da CLI realiza: leituras com escopo de projeto e escritas não destrutivas. Isso também faz dessas chaves de API uma escolha natural para uso em fluxos de trabalho de CI de benchmarking contínuo.
Mais tarde, quando adicionei o Bencher MCP, essas chaves de API com escopo de projeto também passaram a ser usadas para a autenticação lá. O padrão MCP adota o OAuth 2.1, mas ele ainda está em rascunho, então eu não quis implementá-lo ainda. Sinceramente, sou meio cético em relação ao MCP. Ainda acho que uma boa CLI + skills é uma forma mais eficaz e portável de expor um serviço a um agente. O maior problema das CLIs, porém, é a falta de um mecanismo de autenticação padrão. Então, mesmo que o OAuth 2.1 ainda esteja em rascunho, pelo menos o MCP tem isso resolvido. E uma boa história de authn importa muito para clientes enterprise.
Claude, o Poliglota
Lá em 2023, decidi que queria que a documentação do Bencher estivesse disponível em 9 idiomas: inglês, chinês, espanhol, português brasileiro, russo, japonês, francês, alemão e coreano. Como escolhi esses nove idiomas? São os idiomas em que a documentação do GitHub estava, então imaginei que fosse uma aproximação boa o suficiente. O único problema é que eu só sou fluente em inglês. Então pedi ao GPT-4 que traduzisse a documentação para mim. Na época, o GPT-4 tinha uma janela de contexto de apenas 8k tokens. Isso significava que eu tinha que dividir todas as minhas páginas de documentação em “chunks” com menos de 8k tokens. Depois, tive que criar uma ferramenta de CLI para cuidar da tradução e, muitas vezes, da retradução dos chunks depois que eles eram atualizados.
Era um processo muito tedioso e propenso a erros. Eu tinha que editar à mão os arquivos traduzidos porque, mesmo com instruções bem explícitas no system prompt, o modelo ainda estragava os caminhos de importação ou enfiava tudo dentro de mais uma camada de bloco Markdown, especialmente em japonês, por algum motivo.
Quando comecei a usar o Claude Code com o Opus 4.5, tudo isso desapareceu. Agora o agente simplesmente faz. A convenção do que constitui um chunk está lá na base de código, e o Claude simplesmente a segue. Quando eu estava escrevendo a documentação técnica do Bencher Bare Metal, o Claude simplesmente cuidou da divisão em chunks e da orquestração das traduções. Mesmo que o tamanho do contexto agora seja mais do que suficiente para lidar com uma página inteira, eu gosto de ter os chunks. Eles ajudam a manter as alterações isoladas, de modo que apenas as seções relevantes de uma página sejam retraduzidas durante uma revisão.
Quem Não Construiu um Harness em 2026?
Enquanto construía o Bencher Bare Metal, também fiz o Claude criar ferramentas para si mesmo para gerenciar a frota. Isso consistia em duas partes: uma CLI no repositório bencher para tarefas de rotina e um novo meta-repositório (meta-repo). Esse meta-repo guarda toda a documentação e o contexto do Bencher como produto. Todos os outros repositórios da organização bencherdev no GitHub são submódulos nesse meta-repo. O meta-repo permite que o agente trabalhe facilmente em uma tarefa que pode abranger vários repositórios e escreva documentos que eu prefiro não deixar públicos (estratégia de produto, relatórios de incidentes etc.).
Eu queria construir meu próprio agente em cima da CLI do Claude Code, que levaria esse meta-repo de um artefato a uma parte proativa do ciclo de desenvolvimento. Assim que o Fable 5 ficou disponível, concentrei boa parte do meu foco na construção desse agente. Eu queria poder confiar nesse agente para rodar de forma autônoma. Uma grande parte disso era segurança (ou seja, mitigar prompt injections). Projetei tudo para que os agentes trabalhadores nunca guardem nenhum segredo. Todos os segredos são injetados por um proxy de rede e restritos a endpoints de uma allow-list. Os próprios agentes rodavam em mais uma microVM Firecracker, desta vez com paralelismo. A máquina de controle dos agentes e o proxy de rede + sandboxes rodavam em hosts completamente diferentes.
Minha grande visão era que a interface fosse uma fila ordenada pela prioridade das tarefas. Ou seja, o objetivo desse agente seria me mostrar a tarefa mais importante naquele dado momento. Enquanto os feeds do Facebook/Instagram/Twitter/X/TikTok são otimizados para engajamento, esse feed seria otimizado para a importância para mim.
Eu queria criar a ferramenta que me colocaria abaixo da API. Eu tinha percebido que passava a maior parte do tempo trocando de contexto e pulando de uma thread para outra. Minha esperança era que o agente pudesse ajudar a aliviar esse malabarismo ordenando as coisas por mim. Com um sistema de voto positivo/voto negativo no estilo do Reddit, eu poderia treinar o agente para saber se aquela nova mensagem do Slack era realmente a coisa mais importante a que eu deveria prestar atenção.
Também percebi que boa parte do meu trabalho agora é ser o Rúbeo Hagrid do meu agente, seu “guardião das chaves”. A injeção no nível do proxy de rede, com uma allow-list restrita de endpoints, foi a melhor forma que o Claude e eu conseguimos encontrar para, ao mesmo tempo, impedir que o agente tivesse acesso a qualquer segredo e ainda permitir que ele usasse ferramentas como a CLI gh direto da caixa.
A outra meta principal era nunca sair da interface do agente. Sair do agente por qualquer motivo é visto como uma falha do harness. Criei um sistema de componentes de UI procedural para que o agente trabalhando em uma tarefa pudesse construir uma interface inédita na hora ou escolher um dos componentes existentes na biblioteca com base na tarefa em questão. Código, email, Slack, calendário, dados de telemetria de produção, monitoramento de erros, tudo em uma única interface, tudo em uma única fila priorizada.
Consegui colocar no ar uma versão mínima de tudo isso. No entanto, ainda há muitas arestas a aparar. No momento, sou muito mais produtivo se simplesmente usar o app desktop do Claude. E, neste exato momento, preciso de toda a produtividade imediata que eu conseguir para dar conta da demanda.
O que acontece quando o número de desenvolvedores se multiplica por 100?
Lá em 2022, eu estava procurando um novo projeto paralelo. Eu tinha encerrado minha empreitada anterior de aspirante a empreendedor em 2020. Dica de ouro: ouça o Jason Cohen, não tente fazer bootstrap de um marketplace.
Eu estava construindo um parser e analisador estático de bash em Rust no meu emprego, e percebi que estava tendo que usar uma planilha para acompanhar os resultados dos meus benchmarks. O projeto Rust tem o rustc-perf para acompanhar o desempenho do próprio compilador. Ainda assim, não havia uma boa ferramenta para fazer isso com o meu próprio código.
Fiz muita pesquisa sobre a arte anterior na área. Ao longo de alguns meses, conversei por chamada com vários desenvolvedores que tinham construído ou defendido a construção de ferramentas de benchmarking contínuo. Todo mundo estava reinventando a roda. Achei que tinha encontrado um cantinho tranquilo nas águas do mercado. Havia uma necessidade óbvia e contínua. Muitas equipes já pagavam mais de $100/mês pelos seus próprios runners bare metal. Então havia disposição para pagar. Ainda assim, o caso de uso era de nicho. A maior parte do software moderno é implantada como serviço, então antecipar os testes de desempenho no ciclo (shift left) não era tanta prioridade para a maioria das equipes. Elas simplesmente configuravam alertas no Grafana depois do deploy e pegavam a posteriori qualquer coisa que tivesse escapado.
Com a chegada de agentes altamente capazes, porém, dois fatores aumentaram muito o uso do Bencher:
- A necessidade de adotar boas práticas de engenharia de software para testar de forma determinística a saída dos agentes
- A facilidade de adotar boas práticas de engenharia de software com a ajuda dos agentes
LLMs e, por extensão, agentes são sistemas não determinísticos e estocásticos. Assim como os desenvolvedores humanos, eles precisam de proteções para garantir que mantenham a qualidade do código. As formas de fazer isso não são novas: um sistema de tipos robusto, um formatador padrão, um linter no volume 11, testes, testes e mais testes. Tudo rodando no CI. Para cargas de trabalho sensíveis a desempenho, esses testes incluem benchmarks que são acompanhados. Acompanhar o desempenho do software ao longo do tempo permite detectar regressões de desempenho no CI. Isso se chama benchmarking contínuo. Implementar benchmarking contínuo sempre foi meio trabalhoso. Só as equipes que realmente, realmente se importavam com desempenho faziam isso, e elas se tornavam ótimos usuários do Bencher!
Com o advento dos agentes, porém, o esforço de adicionar benchmarking contínuo ao seu fluxo de trabalho usando o Bencher passou a estar a apenas um prompt curto de distância. É difícil medir com precisão, mas eu apostaria que a grande maioria dos cadastros orgânicos do Bencher agora vem da recomendação de um agente ou de um agente fazendo isso por conta própria. Isso só vai se tornar mais verdadeiro com o tempo, à medida que mais desenvolvedores adotarem agentes e os capacitarem com comércio agêntico. Pode ser ou não o protocolo x402, mas acho que boa parte dos gastos com ferramentas de desenvolvimento no futuro será intermediada por agentes. Recomendo que você reserve a sua Cloudflare Wallet e a sua Stripe Wallet, se ainda não fez isso.
Quase todas as ferramentas de desenvolvimento vão precisar migrar para preços baseados em uso na era agêntica. Preços por assento não fazem sentido quando são os agentes que usam o seu serviço. O Bencher sempre teve preços baseados em uso. No entanto, com a ajuda do Claude, reformulei recentemente o modelo de preços para ser ainda mais amigável aos agentes. Antes, o Bencher cobrava por Métrica. Uma Métrica é um único resultado de benchmark em um ponto no tempo. Por exemplo, se você tem 1 benchmark e o executa 5 vezes, isso cria 5 Métricas. O Claude me ajudou a analisar o feedback dos usuários e os padrões de uso. Cheguei à conclusão de que a unidade que estávamos usando no nosso modelo de preços baseado em uso precisava mudar. Agora o Bencher cobra por Série de Benchmark. Uma Série de Benchmark é um benchmark acompanhado ao longo do tempo. Voltando ao nosso exemplo, se você tem 1 benchmark e o executa 5 vezes, isso é 1 Série de Benchmark. Esse novo modelo de preços dá aos usuários muito mais previsibilidade. Você pode entregar um problema de otimização a um agente, e ele pode fazer hill climbing nos seus benchmarks históricos sem incorrer em nenhum custo adicional.
Uma das coisas que não vi mudar neste último ano são as contribuições open source. O Bencher recebeu alguns PRs de AI slop. O principal problema desses PRs era que eles corrigiam bugs aleatórios e sem relação que tinham encontrado pelo caminho. Mas ainda eram bugs genuínos! Então eu meio que dei de ombros e fiz o merge dos PRs, depois de pedir ao meu próprio agente que os revisasse, é claro. É um pouco triste, mas já não vejo muito benefício em atrair colaboradores open source. Sejam os tokens deles ou os meus, eu ainda preciso dedicar o mesmo esforço para revisar o código. Hoje dá muito mais trabalho revisar o PR de um colaborador do que iterar com o Claude eu mesmo.
Qual é o futuro do Benchmarking Contínuo?
Ao tentar adivinhar o que o futuro nos reserva, o padrão parece ser que devemos olhar para o que os próprios laboratórios de fronteira estão fazendo. Ao que parece, todos nós estaremos lá em seis a doze meses. O artigo Inside OpenAI’s agentic software factory, do The Pragmatic Engineer, lança uma luz interessante sobre isso do ponto de vista do benchmarking contínuo:
Novo: um “perf harness”: o agente também usa um perf harness para enviar PRs problemáticos ao framework A/B de Synthetics para avaliar as implicações de desempenho. Como mencionado acima, a carga sobre os sistemas de CI aumentou muito nos últimos seis meses.
O “perf harness” da OpenAI parece muito semelhante à prática estabelecida do benchmarking contínuo relativo. A peça nova de IA é a parte sintética do framework A/B. Dados de teste sintéticos não são novidade. Mas conseguir moldar esses dados sintéticos de forma autônoma para avaliar o desempenho do changeset em questão certamente é novidade! Fazer um desenvolvedor realmente escrever os benchmarks sempre foi a luta. Agora isso é automatizado. Da mesma forma que os agentes aumentaram drasticamente a cobertura de testes de funcionalidades, eles também estão nos permitindo aumentar drasticamente a cobertura de testes de desempenho.
A OpenAI não está sozinha nessa busca. A Anthropic publicou logo depois How we made claude.ai 3x faster in two weeks. Nele, eles também descrevem a construção de benchmarks na hora. Uma diferença importante foi que a Anthropic encontrou contagens determinísticas que se correlacionam com o desempenho: instruções, commits por interação, chamadas de função, recálculos de estilo e mutações do DOM. O Claude então fez hill climbing nessas contagens para otimizar o desempenho do app deles. Ao final da rodada de otimização, eles verificaram se as otimizações baseadas em contagens realmente resultaram em melhorias reais no tempo de relógio de parede.
Essas metodologias batem com o que eu mesmo tenho vivido trabalhando no Bencher. Se bem que os meus testes de desempenho A/B foram todos executados localmente ou na máquina de trabalho de um agente, não em um loop de CI. Sempre que estou prestes a fazer uma grande mudança em uma consulta ou uma migração de schema significativa, peço ao Claude que faça uma avaliação de desempenho exaustiva da mudança. Isso sempre inclui o tempo de relógio de parede e, às vezes, algumas contagens determinísticas correlatas (por ex. instruções da máquina virtual do SQLite).
Por causa de problemas com vizinhos barulhentos, essas rodadas de otimização de desempenho conduzidas por agentes têm tido barras de erro bem largas. Pretendo adicionar fixtures (entradas adicionais de benchmark) e artifacts (saídas adicionais de benchmark) ao Bencher Bare Metal para permitir que meu agente execute essas tarefas de otimização de desempenho com mais confiança. O agente ainda fará a maior parte do trabalho de otimização localmente, fazendo hill climbing da melhor forma que puder no tempo de relógio de parede ou em contagens determinísticas. Depois, ele usará o Bencher Bare Metal para conferir o próprio trabalho, como uma espécie de paquímetro de tempo de relógio de parede.
Mesmo achando que a maioria dos “usuários” do Bencher serão agentes dentro de mais ou menos um ano, ainda acho que a maioria dos humanos vai querer uma interface visual para quando forem dar uma olhada. Atualmente estou mergulhado até o pescoço em um redesign total da UI do Bencher com a ajuda do Claude. Como um engenheiro Rust escrevendo Anyscript na época do autocompletar com tab do GitHub Copilot, a UI atual deixa muito a desejar. A reescrita da UI está bloqueada por outra reformulação ainda mais ambiciosa, porém: uma nova versão do Bencher Metric Format (BMF).
O BMF é o formato central para o qual os resultados de benchmark são normalizados dentro do Bencher. Ele permeia tudo. Essa nova versão do BMF vai permitir que os benchmarks sejam parametrizados. Você vai poder dizer my_benchmark com os parâmetros size: 16 MB e size: 32 MB, em vez de ter dois benchmarks separados, my_benchmark_16_mb e my_benchmark_32_mb. A nova versão do BMF também vai permitir nomes arbitrários de métricas. Você vai poder fornecer as métricas mean, p95 e p99 para suas medidas de Latency, em vez de ter apenas mean ou precisar criar Latency (mean), Latency (p95) e Latency (p99) como medidas separadas.
Dar suporte a essa nova versão do BMF é uma reformulação enorme do núcleo do Bencher. Eu não me sentiria confortável fazendo esse trabalho com nada anterior ao Fable 5. Como discutido acima, a maior parte do trabalho do Bare Metal era ortogonal ao núcleo do Bencher: acompanhar o desempenho ao longo do tempo e alertar sobre regressões. O BMF é central para essa proposta de valor principal. Minha confiança no Fable 5, e mais ainda no Fable 5.1 e no Opus 5.5, mais uma vez me permitiu começar um projeto que teria levado anos de noites e fins de semana para concluir. Antes, eu tive que passar um bom tempo otimizando o SQLite para o Bencher. Agora, toda vez que evoluo o modelo, simplesmente peço ao Claude que inicie um agente para fazer uma investigação de desempenho minuciosa e garantir que tudo continua com bom desempenho. No futuro, acho que nem vou precisar pedir.
Como Eu Programo Hoje
Na época em que eu usava o GitHub Copilot, ele era uma extensão no VSCode. Quando mudei para o Claude Code, eu usava a CLI. Eu tinha três janelas de terminal, cada uma em seu próprio Space do macOS. Cada janela de terminal tinha duas abas. Uma aba era para o Claude e a outra para o Jujutsu (jj). Eu ainda gerenciava o controle de versão e os workspaces do jj eu mesmo.
Hoje em dia, eu só uso o app desktop do Claude Code. Toda nova sessão que inicio parte do meu meta-repo com a caixa de seleção worktree marcada. Parei de usar o Plan mode há alguns meses. Nunca instalei a skill /grill-me do Matt Pocock. Eu só peço ao Claude no prompt para “me sabatinar sobre todas as decisões de design”, e a esta altura o modelo sabe o que fazer. Meu CLAUDE.mdAGENTS.md está bem ajustado para o jeito como quero que o modelo se comporte.
Praticamente desativei meu fluxo de trabalho de CI do Claude Review. Agora o agente cuida de iniciar um revisor adversarial localmente sem que eu sequer precise pedir. Depois eles iteram até convergir, às vezes por até meia dúzia de rodadas. Comecei a experimentar transferir o trabalho de desenvolvimento para máquinas de trabalho externas e deixar minha máquina local apenas como orquestradora.
A única vez que mexo no controle de versão eu mesmo é quando quero fazer checkout de um build para testar coisas por conta própria ou quando estou criando um release versionado e com tag do Bencher. Isso acontece cerca de uma vez por semana e uma vez por mês, respectivamente. Fora isso, agora eu simplesmente deixo o Claude cuidar disso. Faço amplo uso de PRs em draft e, agora que estão disponíveis no GitHub, de PRs empilhados. Não olho para o código até o PR estar aberto. Eu ainda passo os olhos pelo código do Bencher, mas a esta altura é mais uma checagem de sanidade do que uma revisão de código de verdade.
Quando eu olhar para trás daqui a um ano e reler o que escrevi aqui, terei outro momento de “Você nem mencionou IA‽”? Metade de mim acha que isso seria incrível. A outra metade está absolutamente apavorada.
Bencher: Benchmarking Contínuo
Bencher é um conjunto de ferramentas de benchmarking contínuo. Já teve algum impacto de regressão de desempenho nos seus usuários? Bencher poderia ter prevenido isso. Bencher permite que você detecte e previna regressões de desempenho antes que sejam mescladas.
- Execute: Execute seus benchmarks localmente ou no CI usando os exatos mesmos runners bare metal e suas ferramentas de benchmarking favoritas. O CLI
bencherorquestra a execução dos seus benchmarks em bare metal e armazena seus resultados. - Rastreie: Acompanhe os resultados de seus benchmarks ao longo do tempo. Monitore, consulte e faça gráficos dos resultados usando o console web do Bencher baseado na branch de origem, testbed e medida.
- Capture: Capture regressões de desempenho localmente ou no CI usando o exato mesmo hardware bare metal. Bencher usa análises personalizáveis e de última geração para detectar regressões de desempenho antes que sejam mescladas.
Pelos mesmos motivos que os testes de unidade são executados para prevenir regressões de funcionalidades, benchmarks deveriam ser executados com o Bencher para prevenir regressões de desempenho. Bugs de desempenho são bugs!
Comece a capturar regressões de desempenho — experimente o Bencher Cloud gratuitamente.