Pular para o conteúdo

Artigo

Benchmarks poliglotas: escolhendo a ferramenta certa para o trabalho certo

Oito tempos de execução (njs, Lua, Python, Go, Rust, Bun, Java, Kotlin), sete testes HTTP, equipamento Docker reproduzível: matriz de decisão, evidência ARB, repositório de exemplos de fluxo de trabalho e painel ao vivo polyglot-benchmarks.fictionally.org

  • 14 min de leitura

Este é o mergulho profundo de formato longo. Para uma versão mais rápida e legível, consulte o postagem complementar no blog.

Capa do Polyglot Benchmarks – ferramenta certa, trabalho certo

1. Introdução: pilhas de hábitos versus cargas de trabalho reais

As escolhas tecnológicas em organizações maduras raramente falham porque ninguém leu uma postagem de blog de referência. Eles falham porque o processo a escolha é fraca: a preferência de um engenheiro sênior, um pipeline de contratação cheio de um idioma ou uma única demonstração impressionante em uma conferência. Enquanto isso, o produto combina APIs sensíveis à latência, reconciliação em lote, autenticação de borda em NGINX, CLIs internos e picos ocasionais sem servidor. Um tempo de execução não pode ser ideal para todas essas formas.

Este artigo explica Benchmarks poliglotas — um painel de comparação ao vivo e o aberto exemplos/benchmarks de fluxo de trabalho arnês atrás dele - como um quadro de decisão, não uma tabela de classificação de fanboy. O objetivo é uma evidência que você pode anexar a um registro de decisão de arquitetura (ADR): mesmos endpoints, mesmo gerador de carga, mesmo layout de contêiner, vários idiomas.

Não vou inventar números de rendimento em prosa. Quando você executa o chicote, o painel mostra solicitações medidas e percentis de latência para esse hardware e configuração do Docker. Trate qualquer classificação estática aqui como padrões qualitativos alinhados com as famílias de testes do equipamento e a cópia do veredicto integrada do painel.

Abordagem de quatro etapas do Polyglot Benchmarks: definir a carga de trabalho, executar o aproveitamento, comparar, decidir
Visão geral da estrutura de decisão: defina a carga de trabalho, execute o aproveitamento, compare no painel ao vivo e, em seguida, decida com uma ADR apoiada por evidências medidas.

2. O que são benchmarks poliglotas?

Benchmarks poliglotas está hospedado em polyglot-benchmarks.fictionally.org (Infraestrutura de marca fictícia no ecossistema de exemplos de fluxo de trabalho). O título de destino compara:

  • NGINX njs — Módulos JavaScript dentro do estoque NGINX
  • OpenResty Lua — Lua no limite do OpenResty
  • Python FastAPI - Aplicativo Uvicorn ASGI
  • Acesse a rede/http — servidor de biblioteca padrão
  • Rust Actix-web — HTTP assíncrono no Actix
  • Pão — Tempo de execução JavaScript com servidor HTTP nativo
  • Java (Javalin/Jetty) — JVM HTTP leve em Jetty
  • Kotlin (Ktor/Netty) — JVM HTTP compatível com corrotinas em Netty

O título ao vivo é um 8 idiomas comparação: njs vs Lua vs Python vs Go vs Rust vs Bun vs Java vs Kotlin. A legenda enquadra a intenção: desempenho para cargas de trabalho longas de pesquisa/chat/fila/API - caminhos com muitas conexões, JSON e roteamento, em vez de uma única corrida de bigas do tipo “olá mundo”. As lojas JVM finalmente obtêm a mesma superfície justa que Go/Rust/Bun, em vez de uma anedota de “empresa” separada.

2.1 O que o painel mostra

Enquanto uma execução avança, a interface do usuário pesquisa /data/results.json a cada dois segundos e renderiza:

  • Solicitações/seg (taxa de transferência) - agregado de wrk por idioma por teste
  • Latência média e Latência da cauda P99 – em milissegundos do modelo de latência do wrk
  • TTFB (tempo até o primeiro byte) - do curl timing JSON ao lado do wrk
  • Tabela de resumo — vencedores por teste com ★ marcadores nas melhores células
  • Cartões de teste detalhados — gráficos de barras e tabelas métricas (P50, P90, P99.9, erros)
  • Distribuição percentil de latência - média entre testes
  • Veredicto – melhor para o seu caso de uso - narrativa uma vez que o status é complete

Essa estrutura é deliberadamente compatível com ARB: gráficos para slides, tabelas para planilhas, narrativa para a seção de risco de um ADR.

3. O recurso de exemplos de fluxo de trabalho

Tudo o que é reproduzível vive sob benchmarks/ no exemplos de fluxo de trabalho repositório. Layout de nível superior:

benchmarks/
  bench.sh              # orchestrates tests, writes results.json
  wrk_json.lua          # wrk done() → JSON summary (RPS, percentiles)
  docker-compose.yml    # eight app services + dashboard + bench runner
  njs/                  # NGINX + njs module
  lua/                  # OpenResty nginx.conf
  python/               # FastAPI + Dockerfile
  golang/               # net/http main.go
  rust/                 # Actix-web + Cargo
  bun/                  # Bun server.ts
  java/                 # Javalin on Jetty
  kotlin/               # Ktor on Netty
  dashboard/            # static index.html + nginx.conf

3.1 Topologia Docker Compose

docker-compose.yml define serviços isolados em uma rede compartilhada:

  • nginx-njs — porta 8081, configurações de ./njs
  • openresty-lua - porta 8082
  • python-fastapi — porta 8084, construída a partir de ./python
  • go-server - porta 8085
  • rust-actix - porta 8086
  • bun-server - porta 8087
  • java-server — porta 8088, Javalin / Jetty de ./java
  • kotlin-server — porta 8089, Ktor / Netty de ./kotlin
  • dashboard — porta 8083, serve HTML e monta o results volume em /data
  • bench — Contêiner alpino que instala curl, wrk, jq, espera por dependências, executa bench.sh

O corredor de banco compartilha o results volume com o painel para que os resultados apareçam ao vivo sem cópia manual.

3.2 metodologia bench.sh

O driver shell codifica regras de imparcialidade explicitamente:

  • Duração: 10s por endpoint por idioma
  • Tópicos: 4
  • Conexões: 100 simultâneos
  • Aquecimento: 50 rodadas acertando /hello em todos os servidores antes dos testes cronometrados
  • Por servidor: curl timing JSON (dns, connect, ttfb, total) mais wrk com wrk_json.lua

Sete testes são delimitados por barras verticais no script:

EU IA Nome Intenção Ponto final
1Texto SimplesLinha de base – resposta mínima, sobrecarga da estrutura/hello
2Serialização JSONConstruir e serializar array JSON de 100 itens/json
3Limite CPU (fib 30)Fibonacci recursivo (30) - CPU puro/cpu?n=30
4Manipulação de cordasConstruir, dividir, colocar letras maiúsculas e juntar novamente 1.000 segmentos/string
5Solicitar inspeçãoCabeçalhos, método, argumentos → JSON/request_info?foo=bar&baz=123
6Subsolicitação + TransformaçãoSubsolicitação interna, analisar JSON, transformar/subrequest
7Lógica de roteamentoRoteamento condicional em parâmetros de consulta/route?action=greet&name=bench

Cada linguagem implementa a mesma superfície de rota (veja golang/main.go, python/main.py, java/, kotlin/, configurações NGINX, etc.) para que as diferenças reflitam o tempo de execução e a estrutura, e não especificações incompatíveis.

4. Por que “poliglota” é importante (sem fanatismo)

A arquitetura poliglota não significa que todo engenheiro aprenda oito idiomas. Isso significa contextos limitados obtenha um tempo de execução adequado:

  • Plano de borda — autenticação, limites de taxa, roteamento: Lua ou njs dentro do NGINX você já opera
  • Plano central API — lógica de negócios com SLOs: Go ou Rust
  • Plano JVM — propriedades Spring/Jakarta existentes, bibliotecas compartilhadas, profundidade de contratação: Java (Javalin) ou Kotlin (Ktor)
  • Plano de dados — ETL, notebooks, cola ML: Python
  • Plano JS em tempo real — WebSockets, tipos compartilhados com frontend: Bun ou Node onde a velocidade vence

Pilhas uniformes otimizam o RH e as compras. Benchmarks poliglotas otimizam ajuste por carga de trabalho com compensações mensuráveis ​​sobre a mesa.

5. Dimensões que importam

Req/s brutos é a métrica que viaja mais rápido no Slack. É também o mais fácil de interpretar mal. Use uma rubrica com várias colunas:

Critério Domina quando… Sinal de chicote
latência p50/p99APIs voltados para o usuário, bate-papo, pesquisa longapercentis de latência de trabalho; gráfico P99 do painel
Taxa de transferência (RPS)Gateways de alta distribuição, agregadores em lotetrabalho RPS; coluna vencedora do resumo
Memória por conexãoMilhares de WebSockets ociososPerfil qualitativo + de produção (não totalmente aproveitado)
TTFBFalta de CDN, caminhos frios, redes móveisenrolar time_starttransfer nos resultados JSON
LOC/complexidadeStartups, controle de mudanças regulamentadasCompare implementações entre pastas
Tempo de construção e CIImplantações frequentes, muitos serviçosDocker constrói perfis por idioma
Carga operacionalEquipe de plataforma pequenaHabilidades NGINX existentes → Lua/njs; outros contêineres
Custo de hospedagemSempre ativo versus escala até zeroDerivado da memória + CPU sob carga (produção)

6. Matriz de decisão

O diagrama abaixo é o mapa qualitativo que usamos nas análises – líderes ilustrativos, não um substituto para o uso do equipamento em seu kit.

Matriz de decisão de carga de trabalho versus critérios — o vencedor varia de acordo com a linha

Leia primeiro a linha: escolha o formato da carga de trabalho e, em seguida, pondere as colunas. Se dois critérios entrarem em conflito (por exemplo, melhor RPS versus menor LOC), essa tensão é a discussão sobre ADR que vale a pena ter.

7. Padrões de casos (exemplo de rotulagem)

Os mapas a seguir aproveitam as famílias de testes para escolhas arquitetônicas. Os líderes da sua máquina aparecem no painel após uma corrida — não trate esta seção como pontuações fixas.

7.1 API sensível à latência (Testes 1–2, 5–7)

JSON APIs e manipuladores com muito roteamento espelham os testes 2, 5 e 7. Tempos de execução assíncronos compilados (Rust Actix, Go) normalmente levam em taxa de transferência e latência final nesta classe de benchmarks HTTP sintéticos; Bun muitas vezes fica próximo de caminhos pesados ​​​​de JSON com ergonomia JS. Java (Javalin) e Kotlin (Ktor) forneça às equipes de JVM uma leitura justa em relação aos líderes nas mesmas rotas — útil quando a questão é “permanecer na JVM com uma pilha mais leve” versus “reescrever em Go/Rust”. Python FastAPI troca RPS bruto por velocidade de desenvolvimento – o veredicto do painel indica isso explicitamente.

7.2 Microtrabalho vinculado ao CPU (Teste 3)

Fibonacci(30) isola CPU sem E/S. Espere a ferrugem e vá brilhar; pilhas interpretadas pagam despesas gerais; O JVM JIT pode parecer mais forte após o aquecimento do que uma janela fria de 10 segundos sugere - estenda a duração se esse for o seu perfil real. Se o seu serviço real estiver vinculado a E/S, não sobrecarregue esta linha - é um teste de estresse para middleware de computação pesada, não um CRUD típico.

7.3 Transformação de borda (testes 6–7, variantes NGINX)

Os testes de subsolicitação e roteamento são onde OpenResty Lua e NGINX njs pertencem: zero salto extra, memória de trabalho compartilhada, equipes de operações já gerenciam o NGINX. O veredicto do chicote recomenda Go/Rust para back-ends principais de chat/fila e Lua/njs na borda – uma divisão sensata que muitas empresas já administram informalmente.

7.4 ETL em lote e pipeline de dados

O chicote HTTP não emula cargas do Spark ou do warehouse. Para lote, as equipes geralmente priorizam o ecossistema Python e a orquestração (Airflow, Dagster) ou trabalhadores Go para produtividade. Use benchmarks poliglotas para o Superfícies API e planos de controle esses trabalhos expõem, não para o mecanismo de lote em si.

7.5 Ferramenta interna rápida

Administradores internos APIs com baixo QPS e alta taxa de alteração: Python ou Bun/Node geralmente ganham em velocidade e contratação. Execute o Teste 2 (JSON) e o Teste 5 (inspeção) para garantir que a sobrecarga seja aceitável; se o p99 atingir menos de 100 conexões, reconsidere antes de promover para camadas voltadas para o cliente.

7.6 Propriedade JVM (Java e Kotlin)

Muitas empresas já executam Java ou Kotlin para bibliotecas compartilhadas, ferramentas de conformidade e profundidade de contratação. O arnês java-server (Javalin em Jetty, porta 8088) e kotlin-server (Ktor em Netty, porta 8089) implementam os mesmos sete endpoints que Go e Rust, para que você possa quantificar se uma pilha JVM HTTP mais leve é ​​“boa o suficiente” para um determinado SLO antes de reescrever. Prefira o Kotlin quando a simultaneidade no estilo corrotina e as equipes Kotlin-first forem importantes; prefira Java quando a propriedade circundante e o gráfico da biblioteca já forem centrados em Java. Use as linhas do painel ativo - não presuma que os números do Spring Boot sejam iguais aos números Javalin/Ktor.

8. Diagrama de fluxo de trabalho

Poliglota compara raias de fluxo de trabalho

O loop reproduzível: especifique a carga de trabalho → execute o chicote do Compose → publique os resultados no painel Fictionally (ou seu clone interno) → registre um ADR com metadados de configuração → execute novamente quando os tempos de execução ou o hardware mudarem.

9. Como fazer sua própria comparação

  1. Clone: git clone https://github.com/bwalia/workflow-examples.git && cd workflow-examples/benchmarks
  2. Pilha inicial: docker compose up --build — cria todas as imagens de linguagem, inicia o painel na porta 8083, executa o bench automaticamente.
  3. Assistir: abrir http://localhost:8083 (ou o site público quando uma execução hospedada está ativa).
  4. Estender: adicionar uma pasta myruntime/, espelhe caminhos de endpoint, registre um serviço em docker-compose.yml, anexe o servidor a SERVERS em bench.sh.
  5. Personalizar carga: editar DURATION, THREADS, CONNECTIONS no topo de bench.sh — documentar alterações no seu ADR.
  6. Adicione testes em formato de produção: por exemplo middleware de autenticação, consulta ORM, carga útil de 50 KB — mantenha a paridade entre idiomas.

Para CI, execute o Compose em um fluxo de trabalho noturno, arquive results.json como um artefato e falha apenas nos limites de regressão definidos (por exemplo, p99 +20% semana após semana no Teste 2).

10. Antipadrões

  • Escolhendo o vencedor apenas do Teste 1 — o texto simples favorece pilhas mínimas; ele ignora JSON, CPU e problemas de roteamento.
  • Ignorando as habilidades da equipe — A ferrugem na produção sem mentores custa caro em termos de incidentes.
  • Ignorando o custo de hospedagem — 2× RPS é inútil se a memória por pod dobrar sua conta.
  • Obrigação de um idioma em toda a organização - destrói divisões legítimas de borda versus núcleo.
  • Substituindo o perfil de produção — HTTP sintético ≠ seu ORM, cache ou latência regional.
  • Comparando hardware diferente — laptop Docker ≠ bare metal ≠ limites K8s; observe a classe no ADR.

11. Benefícios para a liderança em engenharia

  • Pacotes ARB — exportar capturas de tela do painel + results.json + Compor hash.
  • Evidência neutra em relação ao fornecedor — nenhuma apresentação de vendas de um único fornecedor de nuvem ou estrutura.
  • Clareza de integração — novas contratações vejam *por que* o serviço A é Go e o serviço B é Python.
  • Redução de risco - pilotar o segundo colocado em um serviço paralelo antes de reescrever.
  • Conversas sobre FinOps - vincule a latência final ao escalonamento automático e ao espaço de memória.
  • Roteiro da plataforma - justifique o investimento em habilidades NGINX em comparação com outro microsserviço K8s.

12. Limitações

  • Cargas de trabalho sintéticas — sete testes HTTP não podem representar consumidores Kafka, trabalhos GPU ou gráficos ORM complexos.
  • Rede Docker — adiciona sobrecarga; os números absolutos diferem do metal puro.
  • Classe de máquina única — os resultados hospedados refletem qualquer hardware usado ficcionalmente; seus números serão diferentes.
  • Sem camada de persistência — os efeitos do banco de dados e do cache estão ausentes por design.
  • Duração curta — 10s por teste não podem expor pausas do GC ou interrupções no aquecimento; estender para campanhas de estresse.

Mantenha o perfil contínuo (eBPF, APM, testes de carga contra preparação) como a fonte da verdade para a produção. Benchmarks poliglotas restringem o linguagem e estrutura debate com linhas de base reproduzíveis.

13. Conclusão

A polarização da pilha padrão é confortável; é também como as equipes fornecem o tempo de execução errado para o trabalho. Benchmarks poliglotas e o exemplos de fluxo de trabalho aproveitar a vez “qual idioma vence?” em “qual idioma vence para esta linha de carga de trabalho?” – com gráficos que seu ARB pode citar.

Bifurque o repositório, adicione os endpoints que se parecem com seus hot paths, execute o Compose e anexe os resultados à próxima decisão de arquitetura. O companheiro postagem no blog é a versão de cinco minutos para compartilhar; este artigo é a referência.

Publicado por TenthMatrix (tenthmatrix.com). Painel de referência hospedado em polyglot-benchmarks.fictionally.org no ecossistema de exemplos ficcionais.


Instantâneo de SEO para este artigo

  • Título SEO: Benchmarks poliglotas: ferramenta certa para o trabalho
  • Meta descrição: Compare njs, Lua, Python, Go, Rust, Bun, Java e Kotlin nas mesmas cargas de trabalho HTTP. Arnês reproduzível, painel ao vivo, matriz de decisão para arquitetos.
  • Palavras-chave primárias: benchmarks poliglotas, comparação de linguagens, decisões de arquitetura, exemplos de fluxo de trabalho, benchmark de desempenho, Rust vs Go, Java vs Kotlin, FastAPI, Javalin, Ktor
  • Twitter / X (menos de 280 caracteres): Benchmarks poliglotas: os mesmos 7 testes HTTP em njs, Lua, Python, Go, Rust, Bun, Java, Kotlin - painel ao vivo + aproveitamento de exemplos de fluxo de trabalho. Nenhum vencedor; um quadro de decisão. #Rust #GoLang #Java #Kotlin #Bunjs #poliglota
  • Postagem no LinkedIn: Publicamos um mergulho profundo nos benchmarks poliglotas – como parar de escolher uma pilha para toda a organização por hábito e começar a combinar tempos de execução com cargas de trabalho. Oito linguagens (incluindo Java/Javalin e Kotlin/Ktor), sete testes comparáveis, Docker Compose + wrk, resultados ao vivo em polyglot-benchmarks.ficctionally.org, fonte em github.com/bwalia/workflow-examples/tree/main/benchmarks. Inclui matriz de decisão, antipadrões e orientação de ADR. Da engenharia TenthMatrix. #Rust #GoLang #Java #Kotlin #Bunjs #Lua #Python #njs #FastAPI #Javalin #Ktor #OpenResty #polyglot #benchmarks