golang主流高性能web框架性能测试

测试目的

go语言中文文档:www.topgoer.com

转自:https://segmentfault.com/a/1190000023224253

由于K8s缘故涉猎go语言,发现golang的web框架很多,都号称高性能标杆;之前一直致力于c++高性能服务端框架研究,出于好奇,想单从性能层面客观比较一下go的众多web框架,另一方面也希望看看c++的实现与go语言实现之间究竟存在多大差异。

高性能服务框架评估指标很多,但一般来讲吞吐量与QPS是关键考量指标,吞吐量衡量带宽利用率,QPS主要考验框架调度性能(几乎所有可称之为“高性能”的服务框架都没有吞吐量问题,毕竟网络瓶颈很轻易就达到了)。由于是框架本身QPS测试,为了屏蔽http协议实现差异选择最精简的协议头(协议处理一般不会有锁,为cpu密集型),因此要求请求/返回报文尽可能小,本文测试基于http协议,返回空报文。

为了实现测试的第二个目的,特将一个自撸的c++服务框架作为c++实现的”砖头”,加入到对比测试中。此框架尚未开源,其高性能特性保障体现在如下设计上:

PS:

好吧,这样一来貌似更接近测试socket服务框架调度性能…… 不要纠结keep-alive,因为wrk使用HTTP/1.1,默认都是keep-alive的

测试环境

env

环境设置

ulimit -n 2000

压测工具

wrk
由于环境限制,只能wrk客户端和待测试服务端在一台机器上运行

c++自研框架

$ curl -i http://localhost:8080/ HTTP/1.1 200 OK Content-Length: 0 Connection: keep-alive

$wrk -d 100s -c 1024 -t 8 http://localhost:8080/ Running 2m test @ http://localhost:8080/  8 threads and 1024 connections  Thread Stats   Avg      Stdev     Max   +/- Stdev    Latency    13.03ms    3.80ms 100.73ms   86.97%    Req/Sec     9.43k     1.64k   39.35k    88.23%  7509655 requests in 1.67m, 444.03MB read  Socket errors: connect 0, read 794, write 2, timeout 0 Requests/sec:  75018.11 Transfer/sec:      4.44MB

proxy_server

go-restful框架:

package main import (   "github.com/emicklei/go-restful"   "net/http" ) func main(){    ws := new(restful.WebService)    ws.Route(ws.GET("/").To(hello))    restful.Add(ws)    http.ListenAndServe(":8080",nil) } func hello(req *restful.Request,resp *restful.Response){    resp.Write([]byte("")) }

$curl -i http://localhost:8080/ HTTP/1.1 200 OK Date: Mon, 21 Oct 2019 03:54:27 GMT Content-Length: 0

$wrk -d 100s -c 1024 -t 8 http://localhost:8080/ Running 2m test @ http://localhost:8080/  8 threads and 1024 connections  Thread Stats   Avg      Stdev     Max   +/- Stdev    Latency    19.72ms   10.57ms 331.94ms   87.67%    Req/Sec     6.52k     1.24k   23.75k    80.42%  5180908 requests in 1.67m, 370.57MB read  Socket errors: connect 0, read 844, write 3, timeout 0 Requests/sec:  51757.61 Transfer/sec:      3.70MB

go_restful

go-echo框架:

package main import (    "net/http"    "github.com/labstack/echo" ) func main() {    e := echo.New()    e.GET("/", func(c echo.Context) error {        return c.String(http.StatusOK, "")    })    e.Logger.Fatal(e.Start(":8080")) }

$ curl -i http://localhost:8080/ HTTP/1.1 200 OK Content-Type: text/plain; charset=UTF-8 Date: Mon, 21 Oct 2019 04:09:24 GMT Content-Length: 0

$ wrk -d 100s -c 1024 -t 8 http://localhost:8080/ Running 2m test @ http://localhost:8080/  8 threads and 1024 connections  Thread Stats   Avg      Stdev     Max   +/- Stdev    Latency    17.32ms    8.19ms 252.60ms   90.70%    Req/Sec     7.52k     1.35k   39.96k    80.55%  5974370 requests in 1.67m, 660.92MB read  Socket errors: connect 0, read 431, write 67, timeout 0 Requests/sec:  59686.09 Transfer/sec:      6.60MB

go_echo

go-iris框架:

package main import(    "time"    "github.com/kataras/iris"    "github.com/kataras/iris/cache" ) func main(){    app := iris.New()    app.Logger().SetLevel("error")    app.Get("/",cache.Handler(10*time.Second),writeMarkdown)    app.Run(iris.Addr(":8080")) } func writeMarkdown(ctx iris.Context){    ctx.Markdown([]byte("")) }

$ curl -i http://localhost:8080/ HTTP/1.1 200 OK Content-Type: text/html; charset=UTF-8 Date: Mon, 21 Oct 2019 04:11:59 GMT Content-Length: 0

$ wrk -d 100s -c 1024 -t 8 http://localhost:8080/ Running 2m test @ http://localhost:8080/  8 threads and 1024 connections  Thread Stats   Avg      Stdev     Max   +/- Stdev    Latency    22.03ms    7.99ms 140.47ms   84.58%    Req/Sec     5.79k   775.23    19.31k    80.35%  4608572 requests in 1.67m, 505.43MB read  Socket errors: connect 0, read 726, write 22, timeout 0 Requests/sec:  46041.23 Transfer/sec:      5.05MB

go_iris

go-gin框架

package main import (    "fmt"    "net/http"    "log"    "github.com/julienschmidt/httprouter" ) func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {    fmt.Fprint(w, "") } func main() {    router := httprouter.New()    router.GET("/", Index)    log.Fatal(http.ListenAndServe(":8080", router)) }

$ curl -i http://localhost:8080/ HTTP/1.1 200 OK Date: Mon, 21 Oct 2019 04:15:33 GMT Content-Length: 0

$ wrk -d 100s -c 1024 -t 8 http://localhost:8080/ Running 2m test @ http://localhost:8080/  8 threads and 1024 connections  Thread Stats   Avg      Stdev     Max   +/- Stdev    Latency    16.71ms    7.72ms 268.45ms   87.79%    Req/Sec     7.71k     1.58k   21.27k    82.12%  6130281 requests in 1.67m, 438.47MB read  Socket errors: connect 0, read 693, write 36, timeout 0 Requests/sec:  61243.74 Transfer/sec:      4.38MB

go_gin

go-chi框架:

package main import (    "net/http"    "github.com/go-chi/chi" ) func main() {    r := chi.NewRouter()    r.Get("/", func(w http.ResponseWriter, r *http.Request) {        w.Write([]byte(""))    })    http.ListenAndServe(":8080", r) }

$ curl -i http://localhost:8080/ HTTP/1.1 200 OK Date: Mon, 21 Oct 2019 04:18:42 GMT Content-Length: 0

$ wrk -d 100s -c 1024 -t 8 http://localhost:8080/ Running 2m test @ http://localhost:8080/  8 threads and 1024 connections  Thread Stats   Avg      Stdev     Max   +/- Stdev    Latency    17.17ms    8.47ms 253.47ms   90.07%    Req/Sec     7.65k     1.42k   26.08k    79.76%  6071695 requests in 1.67m, 434.28MB read  Socket errors: connect 0, read 110, write 2, timeout 0 Requests/sec:  60658.49 Transfer/sec:      4.34MB

go_chi

结论:

-cpu-freemem-usageqpsc++15%-20%6M75018.11go-gin0%-1.5%28M61243.74go-chi0%-1%28M60658.49go-echo0%-0.5%28M59686.09go-restful0%-0.5%34M51757.61go-iris0%-1%37M46041.23


-- --
  • 投诉或建议
评论