本內容是對知名性能評測博主 Anton Putra Elixir vs Go (Golang) Performance Benchmark (Round 2) 內容的翻譯與整理, 有適當刪減, 相關指標和結論以原作為準
這是第二輪關于 Elixir 和 Go 的對比測試。我收到了一份來自 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 集群,其中:
- 計算優化型節點 用于 Prometheus、Grafana 和 客戶端 生成負載。
- 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)
- Elixir 的 CPU 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!
- 我總是愿意承認自己的錯誤,并在合理的情況下重新運行測試。