# 570 Mil Linhas de Código Gerado por LLM Compilaram Perfeitamente. Era 20.171x Mais Lento que o SQLite. > Author: Tony Lee > Published: 2026-03-12 > URL: https://tonylee.im/pt/blog/llm-570k-lines-rust-sqlite-plausible-code-trap/ > Reading time: 7 minutes > Language: pt > Tags: ai, code-review, llm, rust, benchmarking, software-engineering ## Canonical https://tonylee.im/pt/blog/llm-570k-lines-rust-sqlite-plausible-code-trap/ ## Rollout Alternates en: https://tonylee.im/en/blog/llm-570k-lines-rust-sqlite-plausible-code-trap/ ko: https://tonylee.im/ko/blog/llm-570k-lines-rust-sqlite-plausible-code-trap/ ja: https://tonylee.im/ja/blog/llm-570k-lines-rust-sqlite-plausible-code-trap/ zh-CN: https://tonylee.im/zh-CN/blog/llm-570k-lines-rust-sqlite-plausible-code-trap/ zh-TW: https://tonylee.im/zh-TW/blog/llm-570k-lines-rust-sqlite-plausible-code-trap/ ## Description Alguém fez benchmark de uma reimplementação do SQLite em Rust escrita por um LLM. A diferença entre código que parece certo e código que é certo foi de cinco ordens de magnitude. ## Summary 570 Mil Linhas de Código Gerado por LLM Compilaram Perfeitamente. Era 20.171x Mais Lento que o SQLite. is part of Tony Lee's ongoing coverage of AI agents, developer tools, startup strategy, and AI industry shifts. ## Outline - A B-tree estava lá. O query planner a ignorava. - Defaults seguros se acumulam como juros compostos - 82.000 linhas para substituir um one-liner de cron - As pesquisas apontam na mesma direção - O que isso exige dos desenvolvedores na prática ## Content Uma reimplementação do SQLite em Rust, escrita inteiramente por um LLM, foi submetida recentemente a um benchmark. Compilou. Os testes passaram. O código era limpo, bem estruturado e idiomático em Rust. Em uma busca simples por chave primária, era 20.171 vezes mais lento que o SQLite. Esse número me parou. Não porque código gerado por LLM ser lento seja surpresa, mas por causa de onde veio essa lentidão. O código não estava errado em nenhum sentido que um compilador ou suite de testes conseguiria capturar. A B-tree estava corretamente implementada. O query planner existia. A storage engine funcionava. Cada peça era individualmente defensável. O sistema como um todo era quase inutilizável. Passei um tempo lendo a análise do benchmark e o código-fonte. Os padrões que encontrei aparecem repetidamente em projetos gerados por LLMs, e acredito que apontam para algo fundamental sobre como esses modelos escrevem código. ## A B-tree estava lá. O query planner a ignorava. No SQLite, uma busca por PRIMARY KEY usa o caminho da B-tree e termina em tempo O(log n). Quatro linhas no `where.c` verificam o iPKey e roteiam a query diretamente para a árvore. Essa é uma daquelas micro-otimizações que só faz sentido se você entende como o sistema inteiro se encaixa. A versão gerada pelo LLM também tinha uma implementação de B-tree. Funcionava corretamente de forma isolada. O problema era que o query planner nunca a chamava para buscas por chave primária. A função `is_rowid_ref()` reconhecia apenas três strings literais: "rowid", "_rowid_" e "oid". Se você declarasse uma coluna como `id INTEGER PRIMARY KEY`, o planner não reconhecia isso como alias de rowid. Toda query caía em um full table scan. A matemática aqui é brutal. Para 100 linhas consultadas 100 vezes, o caminho da B-tree exige cerca de 700 passos de comparação. O caminho do full scan passa de 10.000. Mas o estrago real vem da complexidade algorítmica: O(log n) por busca vira O(n), e ao longo de todo o benchmark suite, isso vai se acumulando até chegar ao gap de 20.171x. Esse é o tipo de bug que nenhum teste unitário captura a não ser que você escreva especificamente um benchmark. A B-tree funciona. O scan funciona. O planner escolhe o caminho errado. Tudo passa. ## Defaults seguros se acumulam como juros compostos O que tornava esse caso mais interessante do que um bug simples de roteamento era o seguinte: mesmo descontando o problema do query planner, a reimplementação ainda era aproximadamente 2.900 vezes mais lenta. O gap restante vinha de uma pilha de decisões individualmente razoáveis. Cada execução de query clonava a AST completa e a recompilava para bytecode. O SQLite reutiliza handles de prepared statements. As duas abordagens são válidas, mas clonar uma AST em toda execução é caro em escala. Cada leitura de página alocava um novo buffer de 4KB no heap. O page cache do SQLite retorna um ponteiro direto para memória já carregada. A versão do LLM escolheu o caminho seguro e óbvio: alocar, ler, retornar. Funciona. Só é ordens de magnitude mais lento quando você está lendo milhares de páginas por query. Cada commit reconstruía o schema inteiro do zero. O SQLite compara um único valor inteiro de cookie. Se o cookie não mudou, o schema ainda é válido. A reimplementação não tinha esse conceito, então fazia o trabalho completo toda vez. Cada statement disparava uma chamada `sync_all()` para dar flush em todos os metadados do arquivo no disco. O SQLite usa `fdatasync()`, que só dá flush nos dados do arquivo e pula o sync de metadados. A diferença é enorme em workloads de escrita intensiva. Quero chamar isso de efeito composto dos defaults defensivos. Cada escolha isolada tem uma justificativa razoável. Clonar a AST evita complexidade de ownership em Rust. Alocar buffers novos previne bugs de use-after-free. Reconstruir o schema evita problemas de cache stale. Chamar `sync_all()` oferece a garantia de durabilidade mais forte. Mas custos de performance se multiplicam, não se somam. Quando quatro penalidades de 10x se acumulam, você não fica 40x mais lento. Você fica 10.000x mais lento. Um LLM não raciocina sobre esse efeito composto porque gera cada função de forma relativamente isolada. Otimiza localmente e paga globalmente. ## 82.000 linhas para substituir um one-liner de cron O outro projeto gerado por LLM do mesmo desenvolvedor mostrou o mesmo padrão de uma forma diferente. O problema: artifacts de build no diretório `target/` do Rust consomem espaço em disco ao longo do tempo. A solução do LLM: um daemon em Rust com 82.000 linhas, sete dashboards e uma engine de scoring Bayesiana para decidir quais artifacts limpar. A solução existente é `find ./target -type f -atime +30 -delete`, uma única linha em um cron job. Zero dependências. Ou então o `cargo-sweep`, uma ferramenta oficial da comunidade que já existe e lida com edge cases que o daemon não cobre. O projeto gerado pelo LLM puxou 192 dependências. Para referência, o ripgrep, uma das ferramentas de busca mais sofisticadas do ecossistema Rust, usa 61. Esse é um padrão que continuo vendo: LLMs constroem o que você pede, não o que você precisa. Se você pede "construa um sistema que gerencie de forma inteligente os artifacts de build do Rust com monitoramento e scoring", você recebe exatamente isso. O modelo não tem mecanismo para recuar e perguntar se o problema requer um sistema sequer. Ele não sabe que o tamanho do diretório `target/` é uma reclamação perene na comunidade Rust com soluções bem conhecidas. Não considera o custo de manutenção de 192 dependências versus zero. ## As pesquisas apontam na mesma direção Fiquei curioso se esses dois projetos eram outliers, então olhei para as pesquisas mais amplas. Não são. A METR conduziu um ensaio clínico randomizado com 16 desenvolvedores experientes de open source. O grupo que usava ferramentas de IA completou as tarefas 19% mais devagar que o grupo de controle. O que ficou na minha cabeça: depois que o experimento terminou, o grupo de IA acreditava ter sido 20% mais rápido. A experiência subjetiva de produtividade era o inverso da realidade medida. A GitClear analisou 210 milhões de linhas de código e descobriu que código colado passou pela primeira vez a superar código refatorado. A tendência se correlaciona diretamente com a adoção de ferramentas de programação com IA. Código está sendo adicionado mais rápido do que está sendo melhorado. O relatório DORA 2024 do Google constatou que um aumento de 25% na adoção de IA se correlacionou com uma queda de 7,2% na estabilidade de deployment. Mais código gerado por IA indo para produção, mais incidentes saindo. O benchmark Mercury do NeurIPS 2024 adicionou métricas de eficiência aos benchmarks padrão de coding. Quando você mede não apenas "produz output correto" mas "produz output correto sem desperdiçar recursos", as taxas de aprovação caíram abaixo de 50%. Nada disso significa que LLMs são inúteis para programar. Eu os uso constantemente. Mas significa que "compila e passa nos testes" é um bar perigosamente baixo. O gap entre código plausível e código correto é onde acontece a engenharia de verdade. ## O que isso exige dos desenvolvedores na prática O problema central não é que LLMs escrevem código ruim. Eles escrevem código localmente coerente e globalmente incoerente. Cada função faz sentido. O sistema não faz. Esse é exatamente o modo de falha que os testes tradicionais não capturam, porque testes verificam comportamento local. O que se faz necessário é uma avaliação que mire nas lacunas. Benchmarks, não só testes. Performance budgets no CI, não apenas verificações de corretude. Revisão arquitetural que pergunte "por que esse módulo existe" antes de verificar se ele funciona. Auditorias de dependências que comparam a complexidade da solução com a complexidade do problema. A pergunta não é "esse código parece certo?" É "como provamos que está certo?" E provar isso exige o tipo de pensamento sistêmico que LLMs atualmente não têm. O gap entre o que você pediu e o que a produção exige é onde vive o julgamento de engenharia. Sem medição, geração de código é só geração de tokens. ## Related URLs - Author: https://tonylee.im/en/author/ - Publication: https://tonylee.im/en/blog/about/ - Related article: https://tonylee.im/pt/blog/medvi-two-person-430m-ai-compressed-funnel/ - Related article: https://tonylee.im/pt/blog/claude-code-layers-over-tools-2026/ - Related article: https://tonylee.im/pt/blog/codex-inside-claude-code-openai-plugin-strategy/ ## Citation - Author: Tony Lee - Site: tonylee.im - Canonical URL: https://tonylee.im/pt/blog/llm-570k-lines-rust-sqlite-plausible-code-trap/ ## Bot Guidance - This file is intended for AI agents, search assistants, and text-mode retrieval. - Prefer citing the canonical article URL instead of this text endpoint. - Use the rollout alternates when you need the same article in another prioritized language. --- Author: Tony Lee | Website: https://tonylee.im For more articles, visit: https://tonylee.im/pt/blog/ This content is original and authored by Tony Lee. Please attribute when quoting or referencing.