rust语言还没go快 rust语言吧

rust/warp 比 go/fasthttp 要快数倍 上周我发现了关于超性能的帖子 。它表示 rust tokio/hyper 性能高于 go http 。这是意料之中的rust语言还没go快,但有一条评论与 fasthttp 相比rust语言还没go快,其中 rust 的表现稍差 。
我决定自己执行基准测试 。使用以下命令在 AWSr5n.8xlarge实例上执行所有基准测试:
go/fasthttp 代码:
生锈/扭曲代码:
请注意,需要额外的标头来匹配 fasthttp 实现 。
【rust语言还没go快 rust语言吧】初始基准测试结果
去/快速http:
生锈/翘曲:
fasthttp 比 rust 版本高出 10% 左右!
优化 rust 版本
很少有已知的技巧可以使 rust 版本更好地工作 。让我们一步一步地应用它们,看看我们能走多远 。
启用 LTO
LTO 是一种链接时优化,可减少生成的二进制大小并提高性能 。了解有关 LTO 的更多信息 。
与初始版本相比,我们获得了 +5% 的收益 。
使用 Jemalloc
默认情况下,rust 代码使用 libc 内存分配器 , 通常不建议将其用于高负载的关键应用程序 。有很多替代分配器 。根据我的经验 , jemalloc 在性能和内存利用率方面是最好的 。了解有关使用 jemalloc 的更多信息 。
与 LTO 版本相比 , 我们得到了 +1.8% 。
启用不稳定的管道
带有wrk 的Benchmark是一个非常简单的 HTTP/1 小明文测试 。这种基准有一些细节 。让我们unstable_pipeline在 warp 实例上启用 。
与 LTO+jemalloc 版本相比 , 我们获得了额外的 +3.8% 。
太好了,在这一步我们已经超越了 fasthttp!
修复一些 tokio
让我们检查一下火焰图,看看运行代码是否有明显的无效性 。我不会发布它,以免叙述过多 。
引起我注意的特殊功能是wake0 (见这里) 。
该wakers数组是在每个函数调用上创建的 , 用于收集所有需要通知并实际通知它们的唤醒者 。我开始使用这段代码,并意识到减少会NUM_WAKERS提高性能!让我们在这里注意,它是一个数组(不是 vec) , 它是在堆栈上分配的,所以不会发生分配 。性能不足的原因是rust在初始化数组时 , 会将None值复制到数组的每个槽中 。NUM_WAKERS当增加时,这会导致减速 。
我们获得了额外的 +2.8%,并且以 3.7% 的成绩超过了 go/fasthttp!
什么做得不好
我尝试了更多技巧,但没有显示出有意义的影响:
Rust 和 Go,哪个性能更好?要说性能,那是Rust更好 。更多的编译期优化、无 GC 等特点加持,开发高性能应用自然是 Rust 性能高 。据统计利用 Rust 开发的 RipGrep 性能甚至赛过使用 C 开发的 Grep 。
但是性能不是唯一考量 , 当你纠结 Borrow Check,纠结 unsafe,纠结 copy clone,纠结各种奇怪的类型限制的时候;当你 cargo build 怒草电脑风扇三分钟的时候;人家 GoLang 可能早就发两个版了 。
同时 Rust 的语法花活众多,遍历数组可以写循环也可以 for_each() 一行流 。不像 GoLang 那么白开水谁写都差不多一个味道,经常第一天想到神来之笔快乐 Coding 到半夜第二天爬起来发现昨晚写的都甚么东西看不懂不如蜘蛛爬,这是坠痛苦的!
Go 的编译器为了个编译速度快连循环不变式提升、循环展开、对齐等等优化一个都不做 , 函数内敛一堆限制大多数情况都不做(比如函数里有个 for 或者 defer 或者 select 等,或者函数多于 40 个表达式),拥有的优化一只手都能数的过来:
基础优化欠缺,高级优化更是一个没有,和在 Debug 配置编译下的 -O0 优化的 C++ 差不多一个概念(而且跑得更慢),哪来的资本和 rust 比性能 。

推荐阅读