性能比拼: Rust vs Zig vs Go

本内容是对知名性能评测博主 Anton Putra Rust vs Zig vs Go: Performance (Latency - Throughput - Saturation - Availability) 内容的翻译与整理, 有适当删减, 相关指标和结论以原作为准

在本视频中,我们将对 Rust、Zig 和 Golang 进行比较。我使用 Actix HTTP 框架 运行 Rust,标准库 运行 Golang,并使用 较新的 Zek 框架 运行 Zig。

我之所以更新这个基准测试,是因为我收到了一位 熟悉 Zig 的开发者 提交的 Pull Request,因此我决定重新进行一次测试。

在本次测试中,我们将重点关注 四个关键指标

  1. 延迟(Latency) :使用 P99 百分位 进行测量。
  2. 吞吐量(Throughput) :即 每秒可以处理的请求数,用于衡量不同 HTTP 框架的性能。
  3. 资源使用情况(Saturation) :包括 CPU 使用率(相对于 Kubernetes 定义的限额)内存使用情况 。在本测试中,我们直接使用 实际的内存使用值 。此外,由于测试是在 Kubernetes 中运行的,我们还需要测量 CPU 限制(Throttling)
  4. 错误率或可用性(Errors/Availability) :对于 HTTP 服务来说,这指的是 成功请求数与总请求数的比率

我使用了 生产级 Kubernetes 集群AWS 上运行大部分基准测试,以确保测试环境尽可能接近 真实的生产环境 。应用程序部署在 大型 EC2 实例 上,客户端运行在 四核 Graviton 实例(基于 ARM 架构,成本略低于 AMD)


测试方法

在本次测试中,我创建了一个 API 端点/api/api/devices),客户端会向该端点发送请求,并获取一个 硬编码的设备信息 。这个测试虽然非常简单,但可以很好地反映 每个应用程序的基准性能

测试开始

首先,我运行 三个应用程序 5 分钟 ,并 不施加任何负载

  • 这次测试中,我决定 直接显示实际的内存使用量(单位:字节)
  • Rust 在空闲状态下仅占用不到 1MB 内存 ,而 Zig 约占 25MB

接下来,我 部署客户端 并施加负载。整个测试持续 大约 2 小时 ,但我已将其 压缩为几分钟 展示结果。


测试结果

CPU 和延迟

  • Golang 从一开始 CPU 使用率就较高 ,并且其 延迟比 Rust 和 Zig 略高
  • Rust 和 Zig 在几乎所有指标上都非常接近 ,除了 内存使用量。但这种情况很快会发生变化。

吞吐量

  • 当请求数达到 20,000 QPS(每秒请求数)时 ,Golang 开始 性能下降,延迟上升
  • 我已应用了所有推荐的优化技术,相关 源代码可在我的仓库中查看
  • 当 QPS 达到 33,000 时,Golang 的延迟问题变得更加明显,已经无法与 Rust 和 Zig 竞争 ,因此从这里开始,我的重点将放在 Rust 和 Zig 的对比 上。

可用性(Availability)

  • 当 QPS 达到 40,000 时,Rust 的 可用性曲线出现小幅下降
  • 由于 平均请求处理时间低于 1ms ,我将 超时时间设定为 100ms
  • 当客户端 请求超时 ,它会收到 HTTP 408 错误码 ,导致 可用性下降

资源使用情况

  • 当 QPS 达到 51,000 时,Golang 开始 丢失部分请求,无法继续保持较高的吞吐量。
  • Golang 的缓存使用量不断增加 ,最终超出 Kubernetes 设定的 256MB 内存限制 ,导致 进程被 OOM(内存溢出)终止

Rust vs Zig

  • Rust 的内存使用量最终达到了 Zig 的水平,并在高负载下超过了 Zig

  • 当 QPS 达到 98,000 时,Rust 开始 性能下降

    • RPS(每秒请求数)下降,无法维持原有吞吐量。
    • 延迟上升
    • Rust 开始返回错误,导致可用性下降(由于大量超时请求)。
  • 在 RPS 计算时,我仅统计成功请求 ,因此 Rust 的请求总数出现了 略微下降

总体吞吐量

  • 最终,Kubernetes 开始限制 Golang 的 CPU 资源 ,但此时它的性能 已经无法与 Rust 和 Zig 竞争
  • Zig 的最大吞吐量约为 118,000 QPS ,Rust 为 113,000 QPS ,而 Golang 仅能达到 70,000 QPS

数据可视化

接下来,我展示了完整测试时长内的各项数据指标的变化情况:

  1. 每秒请求数(RPS)
  • Golang 远低于 Rust 和 Zig ,处理能力约 70,000 QPS
  • Rust 和 Zig 均可达到 100,000 QPS 以上
  1. 延迟(Latency)
  • Rust 和 Zig 之间的延迟差距很小
  • Golang 的延迟明显更高
  1. CPU 使用率(CPU Usage)
  • Golang 从一开始就消耗更多 CPU 资源
  • Rust 和 Zig 的 CPU 使用率更稳定
  1. 内存使用量(Memory Usage)
  • Golang 多次被 OOM 终止 ,导致 多个进程被杀死并重启
  • Rust 和 Zig 的内存使用量相对稳定
  1. 可用性(Availability)
  • Rust 在高负载下出现了部分超时错误,导致可用性下降
  • Zig 的可用性相对较高
  1. CPU 限制(CPU Throttling)

(图略)

  • Golang 在测试后期受到了 Kubernetes 的 CPU 限制,但此时它的性能已经下降,影响不大。
相关推荐
字节跳跃者15 分钟前
Java 中的 Stream 可以替代 for 循环吗?
java·后端
北执南念34 分钟前
如何在 Spring Boot 中设计和返回树形结构的组织和部门信息
java·spring boot·后端
修仙的人42 分钟前
【开发环境】 VSCode 快速搭建 Python 项目开发环境
前端·后端·python
FinalLi44 分钟前
SpringBoot3.5.0项目使用ALLATORI JAVA混淆器
后端
bobz9651 小时前
用于服务器测试的 MCP 开发工具
后端
SimonKing1 小时前
流式数据服务端怎么传给前端,前端怎么接收?
java·后端·程序员
Laplaces Demon2 小时前
Spring 源码学习(十)—— DispatcherServlet
java·后端·学习·spring
BigYe程普2 小时前
出海技术栈集成教程(一):域名解析与配置
前端·后端·全栈
这里有鱼汤2 小时前
如何用‘资金视角’理解短线交易?这篇讲透了!
后端
扶风呀2 小时前
负载均衡详解
运维·后端·微服务·面试·负载均衡