性能比拼: 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 限流情况

(图略)

相关推荐
noravinsc1 小时前
InforSuite RDS 与django结合
后端·python·django
Brookty2 小时前
【MySQL】基础知识
后端·学习·mysql
一只码代码的章鱼2 小时前
Spring 的 异常管理的相关注解@ControllerAdvice 和@ExceptionHandler
java·后端·spring
老友@3 小时前
Spring Data Elasticsearch 中 ElasticsearchOperations 构建查询条件的详解
java·后端·spring·elasticsearch·operations
熬夜苦读学习3 小时前
Linux线程控制
linux·运维·服务器·开发语言·后端
bing_1584 小时前
Spring Boot 项目中什么时候会抛出 FeignException?
java·spring boot·后端
Java&Develop4 小时前
springboot + mysql8降低版本到 mysql5.7
java·spring boot·后端
傻小胖5 小时前
json-server的用法-基于 RESTful API 的本地 mock 服务
后端·json·restful
秋野酱6 小时前
基于SpringBoot的家政服务系统设计与实现(源码+文档+部署讲解)
java·spring boot·后端
不再幻想,脚踏实地6 小时前
Spring Boot 日志
java·spring boot·后端