本内容是对知名性能评测博主 Anton Putra Elixir vs Go (Golang) Performance Benchmark (Round 2) Performance Benchmark (Round 2)") 内容的翻译与整理, 有适当删减, 相关指标和结论以原作为准

这是第二轮关于 ElixirGo 的对比测试。我收到了一份来自 Elixir 创作者的 Pull Request ,并且我认为有必要分享他所做的一些改进。他还表示,在 Kubernetes 环境下比较这两种语言是没问题的,我只需要为应用程序分配整个 VM(虚拟机)。因此,我使用了 Tolerations(容忍度)和 Affinity(亲和性)来实现这一点。


第一轮测试

在第一轮测试中,我们的目标是返回硬编码的对象给客户端,并测量 P90(90% 分位数)的延迟。同时,我们还会通过每秒请求数(Requests per Second,简称 RPS)的指标来衡量吞吐量,并记录以下关键数据:

  • CPU 使用率
  • 内存使用率
  • 可用性(错误率)
  • CPU 限流(Throttling)

由于我们会将这两个应用程序部署到 AWS 上的生产级 Kubernetes 集群,因此这些指标至关重要。这次 Pull Request 带来了一些改进,我建议你也可以与之前的基准测试进行对比。


第二轮测试

第二轮测试模拟了一个更接近实际应用场景的案例:

  • 当应用程序接收到 POST 请求时,它会解析请求体,并将记录插入到关系型数据库中,然后返回数据库生成的 ID 给客户端。
  • 除了前述的性能指标,我们还会额外测量:

    • 数据库操作的延迟(通过内部监测每个应用程序)
    • 数据库的 CPU 使用率(使用 Node Exporter 进行监测)
    • 应用程序创建的数据库连接池大小(使用 Postgres Prometheus Exporter 监测)

所有的基准测试都在 AWS 上运行。在本次测试中,我使用了一台 存储优化型 Graviton2 xlarge 实例 作为数据库服务器。不过,我认为未来可能需要升级它。此外,我还创建了一个 EKS 集群,其中:

  • 计算优化型节点 用于 PrometheusGrafana客户端 生成负载。
  • M7A Large 实例 用于运行应用程序,每个应用程序都部署在自己的 EC2 实例上。

AWS 并不便宜,为了支持我的频道,我提供 一对一咨询服务。如果你感兴趣,可以在视频描述中找到更多信息。


开始执行第一轮测试

整个测试持续 1.5 小时,但我会将其压缩到 1.5 分钟 的展示时间。此外,你可以在此处找到 完整的源代码


第一轮测试结果

1. 每秒请求数(Requests per Second, RPS)

  • Elixir 处理了 20,000 RPS,比之前的基准测试提升了 2,000 RPS,可以看到一定的性能提升。
  • Go 预期达到了 60,000 RPS,依然领先。

2. 客户端延迟

  • Elixir 的延迟相比之前的基准测试略有降低,延迟越低越好
  • 但它仍然远远落后于 Go 的性能。

3. CPU 使用率

  • CPU 使用率越高,吞吐量越低,延迟越高,这并不意外。
  • Elixir 在这个测试中表现不如 Go,至少在这个特定的工作负载下。

4. 可用性(错误率)

  • 可用性 通过每秒错误数来衡量,错误数越低,代表系统越稳定。
  • 这个图表展示的是每秒错误数,错误数越高,代表可用性下降。

5. 内存使用情况

  • 之前已经预料到,在 Go 崩溃之前,它的内存使用率会不断上升

6. CPU 限流(CPU Throttling)

  • ElixirCPU Throttling 现象更严重,因为它更早达到 CPU 使用率的上限,相比之下 Go 应用程序的 CPU 资源管理更高效。

这一轮静态测试的结果可以作为后续测试的基准。


开始执行第二轮测试

这轮测试的展示时间同样压缩到了 1.5 分钟


第二轮测试结果

1. 每秒请求数(Requests per Second, RPS)

  • 这次测试中,相较于之前的基准测试,并没有明显的提升,甚至可以说有轻微的下降
  • Go 在两次测试中都稳定在 22,000 RPS

2. POST 请求延迟

  • Elixir 的延迟相比之前的测试有所降低,表现略有提升,但仍然不及 Go

3. 数据库插入延迟

  • 大部分请求的延迟都来自数据库操作,这在预期之内。
  • 我按照建议创建了 4 个数据库连接池,每个池有 125 个连接

4. CPU 使用率

  • 这里没有太多意外的发现。
  • 未来我可能需要增加数据库连接池的大小,以便让 CPU 资源利用率达到更高水平。
  • 数据库连接池大小网络 I/O 通常是瓶颈,连接数越多,吞吐量越大。但同时,也需要监控数据库本身的健康状况,确保它不会成为新的瓶颈。

5. 可用性

  • 这次测试中,我将超时时间增加到 5 秒,因此没有看到错误

6. PostgreSQL 数据库的 CPU 使用

  • 上一次测试 使用的是 AMD 处理器,这次测试采用的是 Graviton4 第四代处理器

7. 数据库连接池大小

  • Elixir 应用在启动时会立即创建 500 个数据库连接
  • Go 则会根据负载逐步增加连接数
  • 我认为未来可能需要将连接数增加至 1,000,以进一步优化性能。
  • 值得一提的是,Amazon RDS 默认的最大连接数是 5,000,所以应该不会有太大问题。

8. 内存使用情况

  • 如果你有更好的优化方案,欢迎提交 Pull Request
  • 我总是愿意承认自己的错误,并在合理的情况下重新运行测试


好文收藏
38 声望6 粉丝

好文收集