2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

Aleksandr Filichkin

-5分鐘閱讀

讓我們比較一下所有支援的執行時+2個自定義執行時(Rust和GraalVM)的效能。

將比較冷啟動和熱啟動。

原始碼在這裡:https://github。com/Aleksandr-Filichkin/aws-lambda-runtimes-performance。它需要最小的本地設定(幾乎所有的都是Docker化的)。

NodeJs (14。x)

Python (3。9)

Go(1。x)

Ruby(2。7)

。Net(3。1)

Java (11)

Rust(1。54。0)

GraalVM(21。2)

免責宣告。

所有的基準都是在2021年9月進行的

我不是所有這些語言的專家,我很高興看到GitHub repo中的MR有效能改進。我將支援這些 repo,並每三個月進行一次效能測試。我相信開放原始碼的合作 :)

測試場景

我們將測試API-Gateway->AWS Lambda->DynamoDb流程。

我們將只測試POST端點,它將把資料儲存到已知的AWS區域(us-east-2)的DynamoDb表中。

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

主要流程

冷啟動測試

我盡了一切努力來減少冷啟動。

刪除了無用的依賴性。

儘可能多地移到初始化階段(例如,在Java中把所有東西移到靜態),以便在啟動時使用CPU的爆發。

指定了區域。

擺脫了任何DI框架

結果。

冷啟動結果

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

冷啟動結果

所有語言(除了Java和.Net)都有一個相當小的冷啟動。

Java甚至不能用128Mb啟動。它需要更多的記憶體。但GraalVM在這種情況下可以提供幫助。請隨意閱讀關於GraalVM和AWS Lambda的詳細頁面

在所有的設定中,Rust擊敗了所有的其它語言,唯一的例外是128MB的Python是最好的。

龐大的設定只對Java和。Net有幫助。

熱啟動測試

測試是向每個lambda逐一發送15,000個請求。

對於負載測試,我使用JMeter。它看起來像。

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

我們將檢查哪些指標?

每種語言的平均(每分鐘)持續時間(256MB設定,(128MB的簡短結果你可以在最後找到)。

每種語言的最長(每分鐘)時間(256MB設定)。

NodeJS

NodeJS有一個預期的行為。

開始的時候很慢,但經過JIT最佳化後會變得更好。

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

NodeJS 256MB的平均持續時間

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

NodeJS 256MB的最大持續時間

Python

具有穩定的效能:第100次和第15000次呼叫是一樣的。

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

Python 256MB的平均持續時間

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

Python 最大持續時間為256MB

Ruby

我觀察到Ruby非常奇怪的行為:平均持續時間在增長(看起來像是記憶體洩漏或程式碼中的錯誤)。

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

紅寶石256MB的平均時間

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

紅寶石 256MB 最大持續時間

。NET

最初的~1千次呼叫很慢,但隨後它的效能非常好。

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

。Net 256MB的平均持續時間

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

。Net的最大持續時間為256MB

Golang

穩定的彈性效能。

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

Golang 256MB的平均持續時間

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

Golang 256MB的最大持續時間

Java

最初的~1千次迭代很慢,然後變得更快(JIT C1有幫助)。

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

Java 256MB的平均時間

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

Java最大持續時間為256MB

對於Java,我期望C2 JIT最佳化在1萬次迭代後進行,但即使在2萬次呼叫後也沒有最佳化,而且持續時間是一樣的。請看下面的螢幕。

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

Java 256 MB,沒有C2最佳化。

GraalVM

正如預期的那樣,GraalVM從一開始就具有穩定的良好效能。

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

GraalVM 256MB的平均時間

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

GraalVM 256MB的最大持續時間

Rust

Rust有一個持續的令人敬畏的表現。

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

Rust 256MB的平均持續時間

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

Rust 256MB的最大持續時間

全部在一起

衡量平均效能是非常棘手的,因為每一個新的lambda都有一些不同的結果(我相信這是因為lambdas在不同的硬體上分配)。我運行了3次測試,兩次測試之間有30分鐘的延遲,以便有3個不同的lambdas分配。

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

3個時間段的5K迭代(256MB Lambda)。

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

256 MB Lambda

此外,我還測試了128MB lambda的相同流量。在這裡我們可以看到一個很大的區別。

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

128MB的平均溫度狀態

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

128MB的平均溫度狀態

2021 AWS Lambda大戰:所有語言的效能比較(冷啟動和熱啟動)

最大128MB(每分鐘)溫熱狀態

我想對於CPU密集型的流程來說,

編譯語言

解釋語言

之間的差異

會更大。我想,GraalVM在128MB的情況下表現不佳,因為它裡面還有JVM,它需要太多的記憶體,而且Lambda經常執行GC。

結論

冷啟動

所有語言(除了Java和.Net)都有一個相當小的冷啟動。

Java甚至不能用128Mb啟動。它需要更多的記憶體。但GraalVM在這種情況下可以提供幫助。

在所有的設定中,Rust在冷啟動時都勝過所有的執行時間,唯一的例外是128MB,Python是最好的。

熱啟動

Golang和Rust是贏家。他們有同樣出色的表現。

。Net的效能幾乎與Golang和Rust相同,但只是在1千次迭代後(JIT後)。

GraalVM有一個穩定的偉大的效能,幾乎與。Net相同,比Rust和Golang差一點。但對於最小的設定來說, 它的效能並不理想。

與。Net一樣,Java也需要一些時間(1-3千次迭代)進行JIT(C1)。不幸的是,在這個特定的用例中,我無法在JIT C2編譯後達到預期的良好效能。也許AWS只是禁用了它。

Python具有穩定的良好效能,但對於128MB的計算機來說工作速度太慢。

Ruby的效能幾乎與Python相同,但我們看到在20分鐘的呼叫後(15000次迭代後),一些持續時間在增長。

NodeJs是最慢的執行時間,經過一段時間後,它變得更好了(JIT),但仍然不夠好。此外,我們看到NodeJS的最大持續時間最差。

冷+暖啟動

的贏家是Golang和Rust

。它們總是比其他執行時更快,並表現出非常穩定的結果。