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表中。

主要流程

冷启动测试

我尽了一切努力来减少冷启动。

  • 删除了无用的依赖性。

  • 尽可能多地移到初始化阶段(例如,在Java中把所有东西移到静态),以便在启动时使用CPU的爆发。

  • 指定了区域。

  • 摆脱了任何DI框架

结果。

冷启动结果

冷启动结果

  • 所有语言(除了Java和.Net)都有一个相当小的冷启动。

  • Java甚至不能用128Mb启动。它需要更多的内存。但GraalVM在这种情况下可以提供帮助。请随意阅读关于GraalVM和AWS Lambda的详细页面

  • 在所有的设置中,Rust击败了所有的其它语言,唯一的例外是128MB的Python是最好的。

  • 庞大的设置只对Java和.Net有帮助。

热启动测试

测试是向每个lambda逐一发送15,000个请求。

对于负载测试,我使用JMeter。它看起来像。

我们将检查哪些指标?

  • 每种语言的平均(每分钟)持续时间(256MB设置,(128MB的简短结果你可以在最后找到)。

  • 每种语言的最长(每分钟)时间(256MB设置)。

NodeJS

NodeJS有一个预期的行为。

开始的时候很慢,但经过JIT优化后会变得更好。

NodeJS 256MB的平均持续时间

NodeJS 256MB的最大持续时间

Python

具有稳定的性能:第100次和第15000次调用是一样的。

Python 256MB的平均持续时间

Python 最大持续时间为256MB

Ruby

我观察到Ruby非常奇怪的行为:平均持续时间在增长(看起来像是内存泄漏或代码中的错误)。

红宝石256MB的平均时间

红宝石 256MB 最大持续时间

.NET

最初的~1千次调用很慢,但随后它的性能非常好。

.Net 256MB的平均持续时间

.Net的最大持续时间为256MB

Golang

稳定的弹性性能。

Golang 256MB的平均持续时间

Golang 256MB的最大持续时间

Java

最初的~1千次迭代很慢,然后变得更快(JIT C1有帮助)。

Java 256MB的平均时间

Java最大持续时间为256MB

对于Java,我期望C2 JIT优化在1万次迭代后进行,但即使在2万次调用后也没有优化,而且持续时间是一样的。请看下面的屏幕。

Java 256 MB,没有C2优化。

GraalVM

正如预期的那样,GraalVM从一开始就具有稳定的良好性能。

GraalVM 256MB的平均时间

GraalVM 256MB的最大持续时间

Rust

Rust有一个持续的令人敬畏的表现。

Rust 256MB的平均持续时间

Rust 256MB的最大持续时间

全部在一起

衡量平均性能是非常棘手的,因为每一个新的lambda都有一些不同的结果(我相信这是因为lambdas在不同的硬件上分配)。我运行了3次测试,两次测试之间有30分钟的延迟,以便有3个不同的lambdas分配。

3个时间段的5K迭代(256MB Lambda)。

256 MB Lambda

此外,我还测试了128MB lambda的相同流量。在这里我们可以看到一个很大的区别。

128MB的平均温度状态

128MB的平均温度状态

最大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。它们总是比其他运行时更快,并表现出非常稳定的结果。

(0)

相关推荐