Rust vs. Go: 在使用最快框架时的性能测试[译]
本内容是对知名性能评测博主 Anton Putra 1个月前 Rust vs. Go (Golang): Performance (Fastest Frameworks + PostgreSQL) 内容的翻译与整理, 有适当删减, 原作地址
引言
根据我收到的反馈和建议,此次选择 Rust 和 Go 语言中最快的框架进行测试。
-
Rust 方面,使用的是 Axum,它基于 Hyper(一个低级 HTTP 库)和 Tokio,这两者基本上由同一个团队开发。
-
Go 方面,使用的是 gnet,这是之前测试过的最快的 Go 框架。此外,还收到了 gnet 作者提交的 Pull Request ,优化了之前的基准测试,其中包括 Postgres 连接池 的实现。
这次,将进行 两项测试:
-
第一项测试 仅仅比较框架本身的性能,测量 吞吐量(每秒请求数)、延迟(P90 百分位,从客户端测量)、CPU 使用率 和 内存使用率。
-
第二项测试 更加贴近实际场景,我有一个 Postgres 数据库,每次应用收到 POST 请求 时,会将数据存入 关系型数据库 并将结果返回给客户端。
在测试过程中,发现了一些奇怪的行为,希望能得到帮助,进一步优化 Go 应用。
我在 AWS 上运行了所有的基准测试,每个应用都部署在 m7a.large 实例 上(2 核 CPU,8GB 内存)。此外,还有一台 Graviton 存储优化的 EC2 实例(3.4TB 磁盘空间),以及一些 EKS 节点 来运行客户端、监控代理和仪表盘。
第一项测试
我们开始第一项测试。
测试持续了 大约 2.5 小时,但我在(视频)剪辑时将其压缩到了几分钟。
在这次测试中,主要测量以下指标:
- 吞吐量(每秒请求数);
- 延迟(P90 百分位,从客户端测量);
- 应用程序的 CPU 和内存使用情况。
现在,将再运行 1 分钟,然后来逐个分析相关图表,并在测试结束后查看完整数据。
测试结果
1. 吞吐量(Requests per Second)
我没想到 Go 会有如此出色的表现。
-
Axum 由于基于 Hyper 进行抽象封装,相较于之前的测试稍微慢了一些;
-
Go(gnet) 则达到了 近 170,000 QPS(每秒请求数)。 这创造了 2 核 CPU 机器上的新纪录!
Gnet 是我过去一年测试过的最快框架,它的 API 设计非常底层,构建 Web 应用时会有一定的难度,但性能确实强悍。
2. 延迟(Latency)
在延迟方面,Go(gnet) 同样优于 Rust,这真的让我感到惊讶。
3. CPU 使用率
CPU 使用率几乎与之前的测试一致,Rust 和 Go 之间的差别不大。
4. 内存使用率
这一点有些出乎意料,Go 在这个静态测试中的表现明显更胜一筹。
如果你觉得可以进一步优化这两个应用,请提交 Pull Request,我会重新运行测试。
第二项测试
在这项测试中,我添加了 Postgres 数据库,并额外测量了:
- 连接池大小(每个应用维护的连接池);
- Postgres 自身的 CPU 使用率(确保数据库不会成为瓶颈)。
我将连接池大小设置为 500,并确保 Postgres 不会成为性能瓶颈。
现在,我再运行 1 分钟,然后我们会逐个分析图表。
测试结果
1. 吞吐量(Requests per Second)
在这一测试中,Go 依然表现更优,但我注意到了一些 奇怪的行为,可能是 Go 应用 和 Postgres 交互时存在问题。
如果有人能调查并修复这个问题,那就太好了。
-
Rust 最高达到了 39,000 QPS,相较于其他框架来说,这已经是一个 极其优秀 的结果。
-
Go 的吞吐量甚至比 Rust 还高,这很不寻常。
这完全归功于 Gnet,因为其他 Go 框架(比如 Fiber、Gin)在这方面完全比不上。
2. 延迟(Latency)
延迟表现有些不稳定。
- Go 的延迟一开始很高,随后下降,但过程中出现了一些 延迟峰值;
- Rust 在 稳定性 方面表现得更好。
3. CPU 使用率
Go 的 CPU 使用率出现了下降的峰值,这表明可能存在某些问题。
- 我以相同的负载增加速率测试了两个应用,而 Go 这种波动的 CPU 使用情况在 Web 框架中并不常见。
4. 连接池大小(Connection Pool Size)
- 连接池的使用情况正常,没有明显的瓶颈。
5. 内存使用率(Memory Usage)
- Go 表现依然很强劲,没有出现异常情况。
6. Postgres 的 CPU 使用率(Postgres CPU Usage)
- Postgres 本身的 CPU 使用率保持稳定,说明数据库端没有成为瓶颈。
此外,如果你感兴趣,可以看看 每个应用在数据库中插入的记录数:
- Go 插入的记录比 Rust 多了大约 500 万条!
这表明,在使用 最优框架 的情况下,Go 可能比 Rust 还要更具性能优势。