Bun vs Node.js: Um Experimento de Teste de Carga
Desde o seu lançamento, o Bun tem se destacado como uma solução promissora para desenvolvedores que buscam otimizar o desempenho das suas aplicações JavaScript. Recentemente, há um interesse crescente em utilizar o Bun em ambientes de produção.
Com isso em mente, realizar um exame prático para avaliar as vantagens de usar o Bun agora parece uma boa ideia. Hoje, vamos realizar um experimento simples de teste de carga para comparar o desempenho de uma API Express.js rodando em dois runtimes JavaScript distintos: Node.js e Bun.
Nossa análise se concentrará na avaliação de desempenho de um endpoint responsável por calcular números da sequência Fibonacci sob um alto volume de requisições.
Vamos lá!
O Código
Você pode acessar o código usado para esses testes nos links abaixo:
- Bun: Repositório
- Node.js: Repositório
O mesmo código será usado para ambos os ambientes de runtime.
Configurando no zCloud
Em seguida, vamos proceder com o deploy de ambas as APIs no zCloud.
Felizmente, configurar e implantar aplicações no zCloud é fácil.
Conforme ilustrado na imagem abaixo, implantar um aplicativo simplesmente envolve selecionar os recursos computacionais desejados, definir o nome do aplicativo, escolher a região de deploy e definir as configurações relacionadas ao Docker, como o caminho do Dockerfile do seu projeto.
Com a configuração pronta, é hora de submeter esses endpoints a testes de carga pesados.
Disparando
Vou utilizar o Autocannon, uma ferramenta de benchmarking HTTP escrita em Node.js, para executar o teste de carga. Usaremos o seguinte comando:
npx -y autocannon -c 25 -w 4 -d 60 <URL>
- A flag c determina o número de conexões simultâneas.
- w especifica o número de threads de trabalho.
- Por último, d define a duração do teste do autocannon em segundos.
Este comando resultará em duas tabelas contendo dados sobre as requisições:
Bun:
Node.js:
Agora, vamos comparar os resultados.
O Bun exibiu uma latência média de 387,36 milissegundos, atingindo um pico de 3357 milissegundos. Em contraste, o Node.js registrou uma latência média de 1112,88 milissegundos, com um pico de 3608 milissegundos.
A tabela seguinte se concentra nas estatísticas das requests. O Bun processou com sucesso cerca de 3.700 requisições, alcançando uma média de 61 requisições por segundo. Enquanto isso, o Node.js gerenciou cerca de 1.700 requisições, com uma média de cerca de 21 requisições por segundo.
Também podemos comparar as métricas usando o Grafana do zCloud. Você pode acessar os Dashboards através do link disponível na página de App Env.
Comparação
Vamos começar avaliando o uso de recursos físicos: CPU e memória.
Enquanto o Node.js utilizava totalmente a CPU alocada para o aplicativo (0.5 zCloud), o Bun atingiu apenas 60% desse valor:
Bun:
Node.js:
Em termos de uso de memória, o Bun consumiu quase a metade da memória em comparação com o Node.js:
Bun (~50MiB):
Node.js (~80MiB):
Em seguida, vamos analisar os resultados das requisições no Dashboard do Ingress.
Conforme ilustrado no gráfico abaixo, a API do Bun demonstrou a capacidade de transmitir mais de 20 KiB/s de resposta, enquanto o Node.js atingiu apenas 8 KiB/s:
Além disso, a tabela abaixo categoriza as métricas de solicitação por path e response status.
Bun:
Node.js:
O Bun lidou com quase o triplo de requisições em comparação com o Node.js, com um tempo médio de resposta menor:
3704 / 1273 ≃ 2.9
Além disso, em relação às requisições malsucedidas, o Bun exibiu uma taxa de falha de 0.4% com códigos de erro 499, enquanto o Node.js encontrou uma taxa de falha de 1.7%:
Bun:
(15 * 100) / (3704 + 15) ≃ 0.4
Node.js:
(22 * 100) / (1273 + 22) ≃ 1.7
Conclusão
Em conclusão, o Bun mostrou métricas de desempenho superiores em comparação com o Node.js, exibindo maior throughput de requisições, menor latência e utilização de memória mais eficiente.
É crucial enfatizar que essas descobertas são derivadas de testes de benchmarking de um endpoint simples. Não estamos incentivando o abandono do Node.js, nem estamos implicando sua inferioridade. Em vez disso, esses resultados fornecem informações objetivas a serem consideradas.
Além disso, o recurso de observabilidade do zCloud se mostrou excepcional. Não requer configuração adicional, proporcionando um eficiente e valioso monitoramento dos seus apps.
Não investigamos por que o Bun se saiu muito melhor numa tarefa vinculada à CPU. Se você souber explicar essa diferença, deixe um comentário abaixo com mais detalhes.
Post original (em inglês) Assista também o vídeo abordando tudo que foi falado no post.
Bom demais Joao, ficou bem massa o post! Parabéns.
Seria top alguém conseguir explicar essa diferença.
Posso estar enganado, mas acredito que o resultado é ainda mais evidente quando usado agum framework feito para o Bun, com as APIs criadas para ele. Apesar de ele ter praticamente 100% de compatibilidade com as APIs do Node, as APIs dele são ainda mais poderosas.
Achei as latências bem altas e as RPS bem baixas, mas creio que pode ser pela máquina/conexão utilizada nos testes. Já que foi comparado desempenho de APIs, eu fiquei curioso para saber a comparação do Express/Bun com frameworks Python assíncronos geralmente utilizados para APIs, como FastAPI, LiteStar e Sanic. Eu encontrei um artigo comparando Express vs FastAPI: https://medium.com/deno-the-complete-reference/express-vs-fastapi-hello-world-performance-c6d18b0368e4 Mas estes testes com "Hello World" são muito simples. Gostaria de ver os frameworks Javascript vs LiteStar que consegue ter desempenho ainda melhor que FastAPI: https://docs.litestar.dev/2/benchmarks.html
Interessante, por mais comparações iguais essa. Foi incrível como você apresentou a diferença
- Acho que poderias incluir Deno na comparação.
- Não é a minha área mas acho que é difícil explicar. Talvez tenha dicas na documentação do Bun. Talvez sejam os algorítmos utilizados. Talvez seja a linguagem utilizada. Provavelmente todos e mais alguma coisa.
Seria interessante realizar esse teste também utilizando o Fastify em ambos! O Fastify é muito mais rápido e eficiente que o express, provavelmente vai extrair muito mais da performance do Bun, do que o express.
Curti bastante o experimento, principalmente por comparar tecnologias atuais o bun tem bastante potencial, ja faço algums testes com o elysia para testar a performance