8 pontos por GN⁺ 2026-01-30 | 3 comentários | Compartilhar no WhatsApp
  • O PgDog, um proxy de extensão para PostgreSQL, adotou bindings diretos em Rust em vez de serialização com Protobuf para aumentar o desempenho do parsing de SQL
  • A estrutura anterior baseada em Protobuf foi substituída por conversão direta C–Rust (bindgen + wrappers gerados pelo Claude), resultando em ganhos de 5,45x no parsing e 9,64x no deparsing
  • O gargalo de desempenho foi identificado na função pg_query_parse_protobuf, e após tentativas com cache, uma mudança estrutural foi feita para obter uma melhoria fundamental
  • Usando o Claude LLM, a equipe gerou automaticamente 6.000 linhas de código de conversão Rust–C e aplicou isso a funções principais como parse, deparse, fingerprint e scan
  • Com essa otimização, o uso de CPU e a latência do PgDog diminuíram, melhorando bastante sua eficiência como proxy de escalabilidade horizontal para PostgreSQL

PgDog e os limites do Protobuf

  • O PgDog é um proxy para escalar o PostgreSQL e usa internamente o libpg_query para fazer o parsing de consultas SQL
    • Ele é escrito em Rust e, antes, se comunicava com a biblioteca em C por meio de serialização/desserialização com Protobuf
  • Embora o Protobuf seja rápido, a abordagem com bindings diretos é ainda mais rápida
    • A equipe do PgDog fez um fork de pg_query.rs, removeu o Protobuf e implementou bindings diretos C–Rust
    • Como resultado, o parsing de consultas ficou 5,45x mais rápido, e o deparsing 9,64x mais rápido

Resultados do benchmark

  • O benchmark pode ser reproduzido no repositório forkado do PgDog
    • pg_query::parse (Protobuf): 613 QPS
    • pg_query::parse_raw (C–Rust direto): 3357 QPS
    • pg_query::deparse (Protobuf): 759 QPS
    • pg_query::deparse_raw (Rust–C direto): 7319 QPS

Análise do gargalo e tentativa com cache

  • Ao analisar o tempo de uso de CPU com o profiler samply, a função pg_query_parse_protobuf foi identificada como o gargalo
  • Houve uma tentativa de melhorar parcialmente com cache
    • Foi usado um cache HashMap com algoritmo LRU, armazenando a AST com o texto da consulta como chave
    • Em casos com prepared statements, a reutilização era possível
  • Porém, alguns ORMs geravam milhares de consultas únicas, e drivers antigos do PostgreSQL não suportavam prepared statements, o que reduzia a eficiência do cache

Removendo o Protobuf com ajuda de LLM

  • A equipe do PgDog usou o Claude LLM para gerar bindings em Rust sem Protobuf
    • A IA funcionou bem dentro de um escopo de trabalho claro e verificável
  • Com base na especificação Protobuf do libpg_query, o Claude mapeou structs em C para structs em Rust
    • Após 2 dias de trabalho iterativo, foram concluídas 6.000 linhas de código Rust recursivo
  • Isso foi aplicado às funções parse, deparse, fingerprint e scan, confirmando uma melhora de 25% no pgbench

Detalhes da implementação

  • A conversão entre Rust e C usa funções unsafe para mapear diretamente as structs
    • As structs em C são passadas para a API do Postgres para gerar a AST, depois convertida recursivamente para Rust
  • Cada nó da AST é tratado pela função convert_node, que mapeia centenas de tokens da gramática SQL
    • Há funções de conversão separadas para cada tipo de nó, como SELECT e INSERT
  • O resultado da conversão reutiliza a struct Protobuf existente (protobuf::ParseResult), permitindo validação por comparação em nível de bytes durante os testes
  • O algoritmo recursivo faz menos alocações de memória e aproveita melhor o cache de CPU, sendo mais rápido do que uma implementação baseada em loops
    • A implementação com loops acabou ficando mais lenta por causa de alocações desnecessárias de memória e consultas a HashMap

Conclusão

  • Ao reduzir a sobrecarga do parser do Postgres, o PgDog corta latência, memória e uso de CPU
  • Com essa otimização, o PgDog evolui como um proxy de escalabilidade para PostgreSQL mais rápido e mais barato de operar
  • O PgDog está recrutando engenheiros para construir junto a próxima iteração da escalabilidade horizontal do PostgreSQL

3 comentários

 
a1eng0 2026-01-31

Talvez eu esteja interpretando mal o texto original, mas especialmente os textos sobre Rust parecem ser escritos como se tivesse ficado mais rápido "por ser Rust", deixando a essência de lado.

O ponto principal deste texto é que o desempenho melhorou por reduzir a sobrecarga de serialização desnecessária.

Agora, revendo, talvez também não seja exatamente um texto exaltando Rust desse jeito, mas será que acabei criando uma percepção negativa por causa de outros textos?

 
xguru 2026-01-31

Eu também achei que o título original parecia "Rust demais" em relação ao conteúdo real, dando a impressão de que o foco era a melhora de desempenho, então fiz um pequeno ajuste.
Como textos sobre Rust costumam mostrar essa tendência com frequência, acho que é preciso ler filtrando um pouco.

 
GN⁺ 2026-01-30
Comentários no Hacker News
  • O título faz parecer ironicamente que Rust deu um ganho de desempenho de 5x, quando na verdade o sistema estava mais lento
    O problema era que um software escrito em Rust precisava usar a libpg_query, escrita em C, mas como não conseguia se conectar diretamente, acabou usando um binding Rust–C baseado em Protobuf
    Como essa abordagem era lenta, no fim reescreveram os bindings com ajuda de LLM, de forma menos portátil porém muito mais otimizada
    Se tivesse sido escrito em C desde o começo, esse processo de conversão não teria sido necessário. Ou seja, o título mais correto seria algo como “reduziu a perda de desempenho causada pelo uso de Rust”
    Camadas de conversão trazem portabilidade e segurança, mas no fim acabam repetindo cópia, conversão e serialização, e isso é uma das causas de lentidão em aplicações

    • Não era o Rust que era lento, e sim o design ineficiente da biblioteca externa
      Chamar bibliotecas C a partir de Rust é muito fácil, e já existem muitos wrappers seguros
      Quase nunca se vê uma arquitetura com Protobuf no meio, e esse era o gargalo
      O título parece mais um meme do tipo “reescrevemos em Rust” para gerar cliques
    • Dizer que em C teria sido mais rápido não é justo
      A biblioteca original tinha um design ruim, repetindo serialização/desserialização, e o ponto principal foi remover isso
      Um título mais preciso seria “trocaram Protobuf por uma API comum e ficou 5x mais rápido”
    • Fico pensando por que não usaram FFI logo de cara
      Bindings de C em Rust estão entre os casos mais simples e, se a API não for grande, tudo fica bem direto
      Protobuf me parece uma ferramenta inadequada para troca de dados em memória
    • Se usaram LLM para otimização, talvez fosse melhor ter usado para portar completamente a biblioteca C para Rust
      Acho que, com ajuda de LLM, veremos uma explosão de ports para várias linguagens
    • Colocar Protobuf entre Rust e Postgres é praticamente um pesadelo de desempenho. É surpreendente que uma biblioteca assim tenha ficado popular
  • O título é um pouco enganoso
    Na prática, a história é “ficou mais rápido depois que removeram a etapa de serialização em Protobuf”

    • Protobuf oferece compatibilidade de versão que uma simples cópia de memória não consegue dar
      Ele permite que cliente e servidor sejam atualizados de forma independente e continuem funcionando, além de facilitar comunicação entre várias linguagens
      Em sistemas grandes, esse tipo de flexibilidade é muito importante
    • O fato de a serialização em Protobuf ser só 5x mais lenta que uma simples cópia de memória até passa a impressão de ser mais rápida do que eu esperaria
    • memcpy ou mmap são bem mais rápidos, mas o ecossistema Rust tende a evitar essas abordagens inseguras
    • Num caso desses, talvez fosse melhor usar um formato zero-copy padronizado, como Arrow. Ele resolve automaticamente problemas de padding entre linguagens e verificações de segurança
  • Talvez a lentidão não fosse por causa de Rust, nem de Protobuf em si, mas por usarem Protobuf como formato genérico de armazenamento
    No fim, o principal foi simplificar tudo para o objetivo específico

    • Um título como “substituímos Protobuf por uma implementação nativa otimizada” teria chamado menos atenção
      Colocar Rust no título parece ter sido uma escolha para atrair cliques
    • O título da matéria gera polêmica, mas o texto reconhece isso
    • Na prática, quase não tem relação com Rust, mas sem Rust provavelmente não teria chegado à página principal
  • O autor original de pg_query explicou o contexto
    Originalmente, isso era usado na pganalyze para analisar queries do Postgres, encontrar referências a tabelas e reescrever ou formatar queries
    No início usavam JSON, mas depois migraram para Protobuf para facilitar bindings com segurança de tipos em várias linguagens (Ruby, Go, Rust, Python etc.)
    Para linguagens como Rust, FFI é melhor, mas em outras o custo de manutenção é maior
    Ele apoia a tentativa do Lev e pretende adicionar, no futuro, funções para acessar libpg_query diretamente via FFI
    Ainda assim, quando desempenho não é essencial, Protobuf continua sendo uma opção mais conveniente

  • O “5x mais rápido” lembra a piada do Cap’n Proto de ser “infinitamente rápido”

    • O Cap’n Proto foi criado pelo autor do Protobuf e usa uma estrutura que não exige parsing, daí esse tipo de frase
    • Mas, na prática, Cap’n Proto tem baixa usabilidade
  • O título é exagerado, mas o trabalho em si é impressionante
    Não eliminaram completamente o Protobuf; eles otimizaram a forma de uso
    A frase “trocamos X e ficou 5x mais rápido” normalmente quer dizer “consertamos uma implementação bagunçada”
    A principal lição é:

    1. serialização/desserialização vira gargalo oculto com facilidade
    2. implementações padrão raramente são otimizadas para todos os cenários
    3. é preciso usar profiling para localizar o gargalo correto
      O FFI de Rust também tem overhead, então o mérito real não veio da linguagem, e sim do redesenho do fluxo de dados e do esforço de otimização
  • FlatBuffers é mais rápido, mas Protobuf continua sendo usado porque é mantido por uma grande empresa

    • Mas o FlatBuffers também é mantido pelo Google
      No fim, essa ideia de que “se foi feito pelo Google, então é seguro” não tem muito fundamento
    • Eu mesmo já coloquei código na antiga plataforma do Google (code.google.com) e vi tudo morrer depois
      Se o objetivo é só uma estrutura zero-copy com memória compartilhada e campos de versão, não vejo motivo para usar Protobuf
    • O Google ainda não publicou uma otimização zero-copy para campos de string
  • Acho o desempenho do Protobuf uma piada
    O certo seria usar um formato zero-copy em que serialização é praticamente gratuita
    Por exemplo, o Lite³, que eu criei, é 242x mais rápido que FlatBuffers

    • Só que essa biblioteca só apareceria depois de novembro de 2025
      Existem muitos motivos práticos para escolher Protobuf: ecossistema, schema, tooling por linguagem etc.
  • Na prática, o problema não era Rust nem Protobuf, e sim a implementação ineficiente de serialização na camada de abstração do PostgreSQL
    O pgdog removeu essa camada e passou os dados diretamente para a API em C
    Se você remove funcionalidade desnecessária, é natural que fique mais rápido
    Mas ainda existem casos em que algumas pessoas precisam de serialização
    Para essas pessoas, um título dizendo “troque para Rust” passa a mensagem errada
    No fim, na maioria dos casos JSON já basta, e se realmente for preciso mais velocidade, o ideal é evitar serialização por completo

  • Isso é uma comparação injusta
    Usar um protocolo de serialização em comunicação IPC obviamente traz overhead
    É um caso perfeito para a frase: “se melhorou 20%, foi otimização; se melhorou 10x, então já estava mal feito desde o início”