性能比拼: Actix (Rust) vs Zap (Zig) vs Zig

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

介绍

在这期内容中,我想分享关于 Rust 和 Zig 之前的基准测试的最新结果。我收到了很多关于如何优化 Zig 应用程序的建议,还有几个 PR(Pull Request),这些优化带来了巨大的改进。 feat: Fix improper build command Lesson 207 - add pure Zig implementation

我会快速介绍这些优化技术,然后使用优化后的代码重新运行基准测试。此次测试的设置和参数与之前相同,以确保负载生成的一致性。

所以,在本视频中,我们将比较 Rust 和 Zig 这两种编程语言。具体来说,我会使用 Actix 作为 Rust 的 HTTP 框架,而 Zap 则作为 Zig 的 HTTP 框架。此外,我还收到了一位 Zig 专家的 PR,其中包含了一个纯 Zig 编写的 HTTP 服务器实现。

和往常一样,我会施加足够的负载,以找出每个应用程序的极限性能。


Actix(Rust)概览

我选择 Actix 作为测试框架,是基于我之前对最流行的 Rust HTTP 框架(Actix、Axum 和 Rocket)进行的基准测试。在那次测试中,Actix 在这三者中表现出了 最低的延迟最低的 CPU 使用率


Zap(Zig)概览

接下来是 Zap ,一个用 Zig 编写的 HTTP 框架。它本质上是对一个 C 库的封装,并且根据官方提供的基准测试结果,它的性能应该优于 Rust。

在我上次运行基准测试时,我并没有使用所有优化编译选项来编译应用程序。而就在我发布基准测试的几分钟后,我就收到了一个 PR,其中包含了正确的优化方法。

Zig 具有四种构建模式:

  1. Debug 模式 (默认模式):当你直接运行 zig build 命令时,它会使用此模式。这正是我在上次基准测试中使用的模式,导致 Zap 应用程序运行 非常慢
  2. ReleaseFast:优先考虑性能,并禁用所有安全检查。
  3. ReleaseSafe:优先考虑安全性,并保留所有安全检查。
  4. ReleaseSmall :用于生成 较小 的可执行文件。

你可以在 Zig 的官方文档中阅读更多关于构建模式和其他设置的信息。


纯 Zig 实现概览

除了 Zap,我还收到了一位 Zig 专家的 PR,其中包含了一个 纯 Zig 编写 的 Web 服务器实现,并且使用了相同的 API 端点。根据本地测试,该服务器的吞吐量比 Rust 还要高,能够处理 接近 200,000 次请求/秒

该测试是在一台 M2 ARM 架构的 Mac 上进行的。

唯一的不同之处在于,我在编译时选择了 ReleaseFast 模式 ,以 优先考虑性能 而非文件大小。如果你对 Zig 感兴趣,我建议你阅读该 PR 的代码。


测试方法

为了运行此次测试,我使用了 生产级的 AWS EKS(托管 Kubernetes)集群 。我创建了两个 节点组(Node Groups):

  • 一个由 xlarge 实例组成,用于运行应用程序。
  • 另一个由 4xlarge 实例组成,用于运行生成负载的客户端。

所有源代码都托管在我的 GitHub 公开仓库

接下来,我们将所有三个应用程序部署到 AWS Kubernetes ,并让它们在 空闲状态 下运行 10 到 15 分钟


CPU 和内存使用情况

让我们先看看 CPU 使用率

  • Rust(Actix) 具有最高的 CPU 使用率。
  • 纯 Zig 实现 的 CPU 使用率 低得离谱 ,甚至 Prometheus 和 cAdvisor 都无法检测到它正在运行,显示为 0%

接下来是 内存使用情况

  • 如预期的那样,Zap内存使用量最高
  • 具体来看:
    • Actix 使用 760 KB
    • Zap 使用 22 MB
    • 纯 Zig 实现使用约 1,000 KB(1 MB)

虽然这些数据本身并不能说明太多问题,但它们仍然是评估应用程序性能的一个有用基准。


负载测试

现在,我开始部署 测试任务 到 Kubernetes,以生成负载。

  • 每个应用程序都有 20 个 Pod 运行。
  • 30 秒 ,虚拟客户端的数量会增加 1 个。
  • 负载从 20 个客户端 开始,最终大约会达到 4,000 个并发客户端

在测试的前几分钟,我们可以 忽略延迟波动,直到它趋于稳定。


测试结果

初始阶段

  • Rust(Actix) 具有 最低的延迟
  • Zap 和纯 Zig 实现 的延迟相近。
  • 纯 Zig 服务器的 CPU 使用率在测试初期要高得多
  • 每个应用实例运行在 独立的 Kubernetes 节点 上,配置为 2 个 CPU 核心256 MB 内存

50,000 QPS(请求/秒)时的表现

  • 延迟排名

    1. 纯 Zig 服务器
    2. Zap
    3. Rust(Actix)
  • CPU 使用率 也呈现出类似的模式。

  • 偶尔会有客户端超时 ,但 99.999% 的可用性 仍然确保绝大多数请求不会失败。

75,000 QPS 时的表现

  • 纯 Zig 服务器的性能开始下降,延迟上升。
  • 这个吞吐量几乎是 纯 Zig 服务器的极限

81,000 QPS 时的表现

  • 纯 Zig 服务器 开始落后,因此我将其从图表中移除,稍后再进行回顾。

100,000 QPS 时的表现

  • Zap 和 Actix 的延迟和可用性均出现波动
  • CPU 使用率达到 60% 以上 ,这时应该 水平扩展(扩容),而不是继续增加负载。

125,000 QPS 时的表现

  • Zap 达到最大极限,无法处理更多请求。

最终结果

  • Rust(Actix) 最高处理 160,000 QPS
  • Zap 最高处理 127,000 QPS ,CPU 使用率接近 90%

完整测试数据

  1. 请求处理速率(QPS)趋势图
  1. 客户端延迟趋势图
  1. 各应用程序 CPU 使用率
  1. 内存使用情况
  1. 可用性(成功请求率)趋势图
  1. Kubernetes CPU 限流情况

(图略)

相关推荐
桦说编程18 分钟前
爆赞!完全认同!《软件设计的哲学》这本书深得我心
后端
thinktik29 分钟前
还在手把手教AI写代码么? 让你的AWS Kiro AI IDE直接读飞书需求文档给你打工吧!
后端·serverless·aws
老青蛙3 小时前
权限系统设计-用户设计
后端
echoyu.3 小时前
消息队列-初识kafka
java·分布式·后端·spring cloud·中间件·架构·kafka
yuluo_YX3 小时前
Go Style 代码风格规范
开发语言·后端·golang
David爱编程3 小时前
从 JVM 到内核:synchronized 与操作系统互斥量的深度联系
java·后端
彭于晏Yan4 小时前
SpringBoot优化树形结构数据查询
java·spring boot·后端
章丸丸4 小时前
Tube - Studio Videos
前端·后端
练习时长一年4 小时前
Spring事件监听机制(三)
java·后端·spring