Node.js vs Java: Comparação de desempenho do servidor HTTP nativo para o caso hello world
Os artigos recentes sobre a série de comparação de desempenho ficaram bastante populares na comunidade média. Inicialmente, fiz uma comparação do servidor nativo do Node/Deno/Bun com o SpringBoot. Recebi comentários de que essa era uma comparação injusta. SpringBoot é um framework e deve ser comparado com um framework do outro lado. Honrando os comentários, fiz uma comparação de acompanhamento do SpringBoot com Node/Deno/Bun rodando em express/fastify. Ainda recebi comentários de que uma comparação de servidores HTTP nativos em ambos os lados seria muito útil.
Neste e em alguns artigos subsequentes, compararei os servidores nativos fornecidos por Node.js, Deno, Bun e Go com o servidor nativo de Java. Este artigo compara o servidor nativo do Node com o servidor nativo do Java.
Todos os artigos recentes podem ser vistos na minha página de autor .
a configuração
Os testes são executados no MacBook Pro M1 com 16G de RAM.
As versões de software são:
- Node.js v19.8.1
- Java 20
Node.js
import http from "node:http";
http.createServer((req, resp) => {
try {
if (req.method !== "GET") {
return resp.writeHead(405).end();
}
if (req.url !== "/") {
return resp.writeHead(404).end();
}
resp.writeHead(200, {
"content-type": "text/plain",
});
resp.end("Hello world");
} catch (e) {
resp.writeHead(500).end();
}
}).listen(3000);
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
public class NativeHelloWorldServer {
public static void main(String[] args) throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress(3000), 0);
server.createContext("/", new MyHandler());
server.setExecutor(Executors.newCachedThreadPool());
server.start();
}
static class MyHandler implements HttpHandler {
@Override
public void handle(HttpExchange t) throws IOException {
String response = "Hello world!";
t.sendResponseHeaders(200, response.length());
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
}
Cada teste é executado para 5 milhões (5 milhões) de solicitações.
Os testes são executados para 25, 100 e 300 conexões simultâneas.
O teste de carga é realizado usando a ferramenta de teste HTTP da Bombardier.
A seguir estão as tabelas que mostram os resultados para cada nível de simultaneidade:
O servidor HTTP nativo do Node acaba sendo mais rápido que o servidor nativo do Java. A diferença não é muito se é RPS ou números de latência, mas há uma diferença. Além disso, o Node usa muito menos recursos do sistema, como CPU e memória.
VENCEDOR: Node.js
Pode haver uma discussão sobre o uso do pool de encadeamentos em cache em Java. A outra opção é alocar um pool de encadeamentos de tamanho fixo no início. Aqui está um teste rápido usando 100 conexões simultâneas com um pool de threads de tamanho fixo de 125 threads. A única alteração de linha no código Java é:
//server.setExecutor(Executors.newCachedThreadPool());
server.setExecutor(Executors.newFixedThreadPool(125));
Não vejo nenhuma melhoria de desempenho com um pool de threads de tamanho fixo.
Nos próximos artigos, a comparação com Java será apresentada para Deno, Bun e Go.
ATUALIZAR:





































![O que é uma lista vinculada, afinal? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)