后端Web代码性能对比:C语言、Go、Node.js、Nim、Bun


用C++编写一个小型Web应用程序
源码

include <lithium_http_server.hh>
            
int main() {
  li::http_api my_api;
              
  my_api.get("/simple") = 
  [&](li::http_request& request, li::http_response& response) {
    response.write(
"hello world.");
  };
  li::http_serve(my_api, 3000);
}

Go语言:

package main
import (
  "io"
 
"fmt"
 
"log"
 
"net/http"
)
func main() {
  http.HandleFunc(
"/simple", func(w http.ResponseWriter, r *http.Request){
    io.WriteString(w,
"Hello!")
  })
  fmt.Printf(
"Starting server at port 3000\n")
  if err := http.ListenAndServe(
":3000", nil); err != nil {
    log.Fatal(err)
  }
}

 JavaScript (Node.js) :

const f = require('fastify')()
f.get('/simple', async (request) => {
  return "hello"
})
f.listen({ port: 3000})
  .then(() => console.log('listening on port 3000'))
  .catch(err => console.error(err))

BunJS:
为了充分利用Bun 运行时,您可能需要编写特定于 Bun 的代码:

const server = Bun.serve({
  port: 3000,
  fetch(req) {
   let url = new URL(req.url);
   let pname = url.pathname;
   if(pname == '/simple'){
     return Response('Hello');
   }
   return new Response("Not Found.");
  }
});

Nim
Nim 是一种静态类型编译系统编程语言。它结合了 Python、Ada 和 Modula 等成熟语言的成功概念。

  • Nim 生成本机无依赖性可执行文件,不依赖于虚拟机,这些可执行文件很小并且允许轻松重新分发。
  • Nim 编译器和生成的可执行文件支持所有主要平台,如 Windows、Linux、BSD 和 macOS。
  • Nim 的内存管理是确定性的,并且可以通过析构函数和移动语义进行自定义,其灵感来自于 C++ 和 Rust。它非常适合嵌入式硬实时系统。
  • 现代概念(如零开销迭代器和用户定义函数的编译时评估)与在堆栈上分配的基于值的数据类型的偏好相结合,可以产生极其高性能的代码。
  • 支持各种后端:它编译为 C、C++ 或 JavaScript,以便 Nim 可以用于所有后端和前端需求。


Nim 提供了一种很好的方法来达到同样的效果:

import options, asyncdispatch
import httpbeast
proc onRequest(req: Request): Future[void] =
  if req.httpMethod == some(HttpGet):
    case req.path.get()
    of "/simple":
      req.send(
"Hello World")
    else:
      req.send(Http404)
run(onRequest, initSettings(port=Port(3000)))

基准测试
bombardier -c 10 http://localhost:3000/simple

结果表明 Nim 在这个玩具示例上做得很好:

Nim 2.0和httpbeast :
请求/秒(10 个连接):315,000 +/- 18,000
请求/秒(1000 个连接):350,000 +/- 60,000

GCC12 (C++) + lithium:
请求/秒(10 个连接):190,000 +/- 60,000
请求/秒(1000 个连接):385,000 +/- 80,00

Go 1.19:
请求/秒(10 个连接):95,000 +/- 30,000
请求/秒(1000 个连接):250,000 +/- 45,000

Node.js 20 and uWebSockets.js:
请求/秒(10 个连接):100,000 +/- 25,000
请求/秒(1000 个连接):100,000 +/- 35,000

Bun 1.04:
80,000 +/- 15,000
65,000 +/- 20,000

Node.js 20 (JavaScript):
45,000 +/- 7,000
41,000 +/- 10,000

Bun + fastify:
40,000 +/- 6,000
35,000 +/- 9,000

建议您尝试自己运行基准测试。


一些博客文章结论都认为 Go 更快: