Go与Nodejs性能简单对比

背景

大半夜忽然想起来,之前同事提到的Go与Nodejs的性能比较,具体的数据差距很大。当时没有太在意,后来慢慢对Go了解了一些。从原理上来说

Nodejs采用的是Reactor这种结构,与Nginx类似,一个连接就是一个数据结构,通过Epoll等来实现IO异步。
Go底层也是Reactor,每一个Go程就可以认为是单个数据结构,调度是由Go本身来提供的。

同事的测试数据记不清了,我的观点是Go和Nodejs应该是一个数量级的,但是Go默认是多核,而Nodejs天生就是单核,所以造成了巨大的差异。因此初步的想法就是验证多核和单核的影响。

过程

centos7 ,虚拟机,cpu 4核。

package main

import (
    "fmt"
    "runtime"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello World")
}

func main() {
    runtime.GOMAXPROCS(1)   //关键点
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}
var http = require("http"); 

http.createServer(function(request, response) { 
    response.end("hello World"); 
}).listen(8888,"0.0.0.0");

测试使用Wrk,Nodejs使用pm2。

wrk -t12 -c400 -d30s http://localhost:8080
pm2 start app.js -i 0 --name "api"
Running 30s test @ http://localhost:8888
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    23.88ms    6.97ms 265.19ms   91.13%
    Req/Sec     1.37k   301.01     4.35k    84.09%
  487168 requests in 30.10s, 51.57MB read
Requests/sec:  16187.38
Transfer/sec:      1.71MB

Running 30s test @ http://localhost:8080
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    14.05ms    3.83ms 212.71ms   73.18%
    Req/Sec     2.35k   241.08     5.11k    75.92%
  843218 requests in 30.05s, 102.93MB read
Requests/sec:  28059.36
Transfer/sec:      3.43MB

Running 30s test @ http://localhost:8888
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     8.92ms    8.48ms 310.50ms   90.90%
    Req/Sec     4.11k     1.40k   19.47k    69.56%
  1471190 requests in 30.09s, 155.74MB read
Requests/sec:  48888.35
Transfer/sec:      5.18MB

Running 30s test @ http://localhost:8080
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     5.15ms    4.34ms 222.96ms   80.88%
    Req/Sec     7.04k     2.19k   61.53k    71.45%
  2512607 requests in 30.10s, 306.71MB read
Requests/sec:  83475.03
Transfer/sec:     10.19MB

使用postman看了下两个的response,略有差别,Go有keep-alive,Node没有。是不是因为close再重连影响的?使用 netstat -tnp | grep “8888” | wc -l 发现在过程中并没有变化,所以排除重连。Go和Node都是793。wrk并发调为1000的时候为1993。还是奇数。单独的奇数我看了,只要wrk一启动就会有一个TIME_WAIT状态,猜测是wrk测试连接。所以,还是差8个,8/2=4,也就是说wrk少连了4个,再找,应该是1000/12=83,83*12=996,所以有4个。400是33*12=396,无意中挑的1000和400竟然结果一样。

结论

有差距,是一个数量级,但是差距比较大。再找找原因。