经过再次重写之后,性能已经是 Nginx 的 1.76 倍

2018-01-25 16:12:47 +08:00
 herozem

guard 是一个高性能熔断器+代理

RT。上周末发了 https://www.v2ex.com/t/424778#reply14

然后最近几天一直在迭代。从把锁丢掉,到重写 radix tree 和融合统计模块,到把 net/http 换成 fasthttp, 在我的笔记本上,QPS 从 7k 左右到了 22k,对比 Nginx,性能从 Nginx 的 0.55 到 1.76 倍。改写的过程非常 累,因为写好的测试需要一遍一遍推翻重写。数据结构也需要仔细设计。hot-path 需要非常注意避免性能问题。

但是改写的过程也学到了很多东西,例如怎么去优化 Go 的性能,期间尝试了 prefork 模式,减少锁,缩小临界区,使用 CAS,调整 GOGC参数 等等等等。

项目链接:

https://github.com/jiajunhuang/guard

核心模块的设计基本上已经稳定了,接下来要做的事情是:

欢迎大家关注和 star,以及提出意见,建议和 PR !

18498 次点击
所在节点    分享创造
45 条回复
LuckCode
2018-01-25 16:35:54 +08:00
不懂 bd,star 学习
xwhxbg
2018-01-25 16:41:56 +08:00
厉害了,不知道有木有跟 traefik 对比一下性能,另外 string 和 byte 不是应该有相同的 underlying value 吗?这俩之间转换有什么特别大的消耗呀?
herozem
2018-01-25 16:48:43 +08:00
@LuckCode star 也是贡献~~鼓励开发者哈哈

@xwhxbg 暂时还没有和 trafik 对比,trafik 说 [自己是 Nginx 的 85%]( https://docs.traefik.io/benchmarks/) 左右,起初我也是以这个为目标的。[]byte 是 mutable 的, string 是 immutable 的,如果底层共享的话,会发大乱子的。

参考: https://syslog.ravelin.com/byte-vs-string-in-go-d645b67ca7ff
xwhxbg
2018-01-25 16:54:51 +08:00
@herozem 学习了,厉害厉害,那已经是 traefik 的两倍了,看了下配置方式很新颖啊,是不是应该以后会有一个界面看 access log 和 register app
herozem
2018-01-25 16:59:53 +08:00
@xwhxbg 讲真,重写之后原来的配置方式被删掉了 :joy: 之后的话这些功能应该都可以慢慢加上的。不过当务之急是完善核心功能+继续压榨 Go 的性能。

之前是有一个接口返回 app 和对应的统计数据的,不过如上所说,暂时被删掉了 :joy:

欢迎贡献代码
ryd994
2018-01-25 17:24:50 +08:00
希望能看到具体的测试场景和 nginx 配置,否则单凭 req/s 说服力不大
xwhxbg
2018-01-25 17:25:49 +08:00
@herozem 我看了下代码,位运算好销魂。。。表示理解不能,超出了我的能力范围,贡献代码怕是不可能了
bramblex
2018-01-25 17:28:10 +08:00
讲真 go 这种带着 runtime 的语言是怎么超越 nginx 那种 *****ptr 的优化的。nginx 在很多方面都已经是性能压榨的极限了。
zhs227
2018-01-25 17:31:55 +08:00
初学者,怀着敬畏点评一下
fasthttp 的头部都是在使用的时候才解析,之前都是一堆的 byte 地址传来传去。如果要逐个解析头部字段,速度就会明显慢下来。
另外,fasthttp 前端目前不支持 http2。后面做一些 web 选型就没有再考虑这个。
不过基于 traefik 的 benchmark 来看,大概 80%相当于 nginx 是靠谱的
herozem
2018-01-25 17:35:13 +08:00
@bramblex 尽可能的重复利用已经申请的对象,尽可能的避免锁。pprof,哪里耗时打哪里

@xwhxbg 目前还在开发,变更比较大,等稳定了,注释多了就好读了 :)

@ryd994 目前还只有简单的测试,等稳定了之后会把 benchmark 做的更详细更专业的 :) 目前是:Nginx 4 worker 返回默认的 index.html。Nginx 4 worker 监听 9999 做代理,guard 监听 23456 做代理。max fd 都是设置 2048000。

因为都只能在自己的笔记本上跑跑,互相影响是肯定的,之后如果有机会的话,可以用强大的机器+虚拟机的模式来跑分
herozem
2018-01-25 17:39:09 +08:00
@zhs227 是的,原本我计划自己实现 proxy 也是这种思路。因为作为 proxy server,并不需要读 body。另外 net/http 实现里申请了太多的内存,相当的影响性能。 另外 guard 暂时也不会支持 http2。http/1.x 比 2 的工具等
都成熟很多。更专业的 benchmark 我会在把功能做成熟做稳定之后再来,目前还只是一个粗略的跑分
caola
2018-01-25 17:50:49 +08:00
不支持最新的 QUIC 就一切免谈,
之前用 caddy 的 quic,最高只支持到 quic 38 版本,跟不上时代了
果断放弃,改投 trafficserver 大法,可以支持到 quic 41 版本,爽。。
zhujinliang
2018-01-25 18:22:47 +08:00
time.Now 这块能详细说一下么
如何取当前时间的,精确度有多少?
我想弄一个能精确到 1ms 或 0.5ms 的,但 linux 时间片好像就需要 10ms
gouchaoer
2018-01-25 18:25:10 +08:00
你能跑个火焰图和 nginx 火焰图说明一下你哪里更厉害么?
herozem
2018-01-25 18:56:28 +08:00
est
2018-01-25 19:54:01 +08:00
不太可能超过 nginx 贴配置看看? nginx worker 数量要等于 GOMAXPROC 才公平?
miketeam
2018-01-25 21:26:11 +08:00
楼主,我搭你的车来了,已给 star
cholerae
2018-01-26 00:28:11 +08:00
@zhujinliang 带 runtime 和调度器的语言就要求别太高了,1ms 的精度基本不可能的
cholerae
2018-01-26 00:32:07 +08:00
@herozem 那位朋友想要高精度时钟,这个 coarseTime 精度应该比 time.Now 还低啊
herozem
2018-01-26 00:42:54 +08:00
@cholerae 应该还是可以的,有写一个 benchmark,发现 time.Now 损耗大概在 40ns 左右,用 coarse 实现应该是可以控制到这位朋友要的精度的。毕竟 CPU 非常的快

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/425910

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX