坊间传言 fasthttp 在某些场景下比 nginx 还要快,说明 fasthttp 中应该是做足了优化。我们来做一些相关的验证工作。

先是简单的 hello server 压测。下面的结果是在 mac 上得到的,linux 下可能会有差异。

fasthttp:

wrk -c36 -t12 -d 5s http://127.0.0.1:8080
Running 5s test @ http://127.0.0.1:808012 threads and 36 connectionsThread Stats   Avg      Stdev     Max   +/- StdevLatency   267.58us   42.44us   0.90ms   79.18%Req/Sec    11.05k   391.97    11.79k    87.42%672745 requests in 5.10s, 89.18MB read
Requests/sec: 131930.78
Transfer/sec:     17.49MB

标准库:

wrk -c36 -t12 -d 5s http://127.0.0.1:8080
Running 5s test @ http://127.0.0.1:1000212 threads and 36 connectionsThread Stats   Avg      Stdev     Max   +/- StdevLatency   310.94us  163.45us  14.41ms   93.42%Req/Sec     9.74k     1.01k   12.80k    75.82%593327 requests in 5.10s, 63.37MB read
Requests/sec: 116348.87
Transfer/sec:     12.43MB

rust 的 actix,编译选项带 --release:

wrk -c36 -t12 -d 5s http://127.0.0.1:9999
Running 5s test @ http://127.0.0.1:999912 threads and 36 connectionsThread Stats   Avg      Stdev     Max   +/- StdevLatency   267.31us   20.52us 622.00us   86.07%Req/Sec    11.11k   364.03    11.64k    82.68%676329 requests in 5.10s, 68.37MB read
Requests/sec: 132629.68
Transfer/sec:     13.41MB

好家伙,虽然是 hello 服务,但是 fasthttp 在性能上竟然赶上 rust 编写的服务了,确实有点夸张。这也间接证明了,“某些场景”至少可能真的和不带 GC 的语言性能差不多。

说明 fasthttp 里所做的优化是值得我们做点研究的。不过 fasthttp 搞的这些优化点也并不是很神奇,首先是很常见的 goroutine workerpool,对创建的 goroutine 进行了重用,其本身的 workerpool 结构:

type workerPool struct {// Function for serving server connections.// It must leave c unclosed.WorkerFunc ServeHandler.....ready []*workerChan
}

核心就是 ready 数组,该数组的元素是已经创建出来的 goroutine 的 job channel。

type workerChan struct {lastUseTime time.Timech          chan net.Conn
}

这么多年过去了,基本的 workerpool 的模型还是没什么变化。最早大概是在 handling 1 million requests with go 提到,fasthttp 中的也只是稍有区别。

具体的请求处理流程也比较简单:

tcp accept -> workerpool.Serve -> 从 workerpool 的 ready 数组中获取一个 channel -> 将当前已 accept 的连接发送到 channel 中 -> 对端消费者调用 workerFunc

这里这个 workerFunc 其实就是 serveConn,之所以不写死成 serveConn 主要还是为了在测试的时候能替换掉做 mock,不新鲜。

主要的 serve 流程:

func (s *Server) serveConn(c net.Conn) (err error) {for {ctx := s.acquireCtx(c)br = acquireReader(ctx)   // or br, err = acquireByteReader(&ctx)// read request header && bodybw = acquireWriter(ctx)s.Handler(ctx) // 这里就是 listenAndServe 传入的那个 handlerif br != nil {releaseReader(s, br)}if bw != nil {releaseWriter(s, bw)}if ctx != nil {s.releaseCtx(ctx)}}
}

在整个 serve 流程中,几乎所有对象全部都进行了重用,ctx(其中有 Request 和 Response 结构),reader,writer,body read buffer。可见作者对于内存重用达到了偏执的程度。

同时,对于 header 的处理,rawHeaders 是个大 byte 数组。解析后的 header 的 value 如果是字符串类型,其实都是指向这个大 byte 数组的,不会重复生成很多小对象:

如果是我们自己写这种 kv 结构的 header,大概率就直接 map[string][]string 上了。

通过阅读 serveConn 的流程我们也可以发现比较明显的问题,在执行完用户的 Handler 之后,fasthttp 会将所有相关的对象全部释放并重新推进对象池中,在某些场景下,这样做显然是不合适的,举个例子:

当用户流程中异步启动了 goroutine,并且在 goroutine 中使用 ctx.Request 之类对象时就会遇到并发问题,因为在 fasthttp 的主流程中认为 ctx 的生命周期已经结束,将该 ctx 放回了 sync.Pool,然而用户依然在使用。想要避免这种问题,用户需要将各种 fasthttp 返回的对象人肉拷贝一遍。

从这点上来看,基于 sync.Pool 的性能优化往往也是有代价的,无论在什么场景下使用 sync.Pool,都需要对应用程序中的对象生命周期进行一定的假设,这种假设并不见得适用于 100% 的场景,否则这些手段早就进标准库,而非开源库了。

对于库的用户来说,这样的优化手段轻则带来更高的心智负担,重则是线上 bug。在使用开源库之前,还是要多多注意。非性能敏感的业务场景,还是用标准库比较踏实。

参考资料

[1] https://github.com/valyala/fasthttp

[2] https://medium.com/smsjunk/handling-1-million-requests-per-minute-with-golang-f70ac505fca

fasthttp 快在哪里相关推荐

  1. 开源HTTP解析器---http-parser和fast-http

    转载地址:https://www.cnblogs.com/arnoldlu/p/6497837.html 由于项目中遇到需要发送http请求,然后再解析接收到的响应.大概在网上搜索了一下,有两个比较不 ...

  2. 他山之石,可以攻玉, 改造fasthttp实现高性能网络通信

    前言 如果朋友看过在下上一篇文章<boot4go-gateway和nginx的性能测试大PK>,能在反向代理的性能PK中完胜Nginx的Gateway,是使用GO语言在基于比Go的标准ht ...

  3. light java框架_Java框架之light-4j( 比Spring Boot快44倍,性能好 )

    Java框架之light-4j(比Spring Boot快44倍,性能好) light-java是内置了undertow服务器的REST微服务轻量Java框架,它比Spring Boot内嵌Tomca ...

  4. 使用第三方SDK(如微信、qq、快看、头条等),调用接口405 Method Not Allowed

    使用第三方SDK(如微信.qq.快看.头条等),调用接口405 Method Not Allowed 错误描述:postman请求正常,但客户端调用后接口没有反应,但返回了405错误. 解决方法:第三 ...

  5. 2022-2028中国快时尚服装市场竞争及发展前景预测报告

    [报告类型]产业研究 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了快时尚服装行业相关概述.中国快时尚服装行业运行环境.分析了中国快时尚 ...

  6. 比Momentum更快:揭开Nesterov Accelerated Gradient的真面目NAG 梯度下降

    d为累计梯度 作为一个调参狗,每天用着深度学习框架提供的各种优化算法如Momentum.AdaDelta.Adam等,却对其中的原理不甚清楚,这样和一条咸鱼有什么分别!(误)但是我又懒得花太多时间去看 ...

  7. 使用现场总线更快更远

    使用现场总线更快更远 Going faster and further with Fieldbus PROCENTEC等行业专家表示,基于RS-485的现场总线技术(PROFIBUS®)和工业以太网( ...

  8. Battery electric vehicles (BEVs) 快充技术

    Battery electric vehicles (BEVs) 快充技术 BEVs: Not If, But When and How Fast 电池电动汽车(bev)已经开始走上一条陡峭的部署增长 ...

  9. TensorRT 3:更快的TensorFlow推理和Volta支持

    TensorRT 3:更快的TensorFlow推理和Volta支持 TensorRT 3: Faster TensorFlow Inference and Volta Support 英伟达Tens ...

最新文章

  1. 【NetApp】关于Snapmirror强制停止的一点记录
  2. Android Low Battery 低电量处理流程
  3. Surface pro镜像恢复详细图文步骤 2021最新版
  4. Centos7 单台服务器搭建Elasticsearch6.0.1集群
  5. 阿里云服务器部署php的laravel项目,在阿里云买ECS 搭建 Linux+Nginx+Mysql+PHP环境的
  6. BZOJ 1012 [JSOI2008]最大数maxnumber
  7. 一键发布到Maven Central的方法
  8. 重磅!英特尔终于挤出10nm芯片 六大技术战略,震动芯片届
  9. webstorm 设置js或者html文件自动缩进为4个空格不生效
  10. 空调开关html,酒店墙上空调开关图解—酒店墙上空调开关图案是什么意思
  11. 【ESD专题】案例:同样是RS485芯片,ESD的性能却天差地别?
  12. [PowerQuery]Excel 如何开启PowerQuery组件
  13. No20. i++/j++
  14. 基于SpringBoot+ Vue 音乐平台
  15. 【真人手势动画制作软件】万彩手影大师教程 | 如何让2个对象同时播放
  16. photoshop使用技巧_如何使用Photoshop创建逼真的漫画
  17. C++一本通题库1013
  18. 微信公众号运营实用小技巧分享
  19. PWA之 Service worker
  20. 11选5c语言代码,和山山哥一起学EXCEL和VBA,学以致用搞彩票11选5(一)

热门文章

  1. JavaFX 中 FX 一词的由来
  2. IDEA连接Mysql报错: 未找到驱动程序类 ‘com.mysql.cj.jdbc.Driver‘.  Change driver class
  3. 位操作/获取数组的个数
  4. redhat 安装Rabbitmq
  5. java一些常用并发工具示例
  6. EcStore中的App是什么东西?
  7. HTML5 — 让拖放变的流行起来
  8. ActiveMQ点对点消息通信demo
  9. php开启与关闭错误提示
  10. Kalileo中DiagramGroup布局