Improving AWS Lambda performance and cost with ARM at PostNL
When running applications at scale, it is always important to keep an eye out on performance and cost. But what if I would tell you there is a simple configuration change that will save at least 20% on cost and improve the performance of most of your lambdas: Using arm architecture instead of the old x86.
You may recognize x86 from your PC with an Intel chip. Arm has it's origin in the mobile market but is now under heavy demand in other markets as well. For example, laptops (Apple's M1 chip) and cloud (AWS Graviton2 processor). In September 2021 AWS introduced arm-based lambda functions. They use the AWS Graviton2 processor for their workloads. Lambda functions using arm are 20% cheaper than functions with the same memory/CPU but using x86.
Currently the following runtimes are supported:
- Node.js 12, Node.js 14
- Python 3.8, Python 3.9
- Java 8 (AL2), Java 11
- .NET Core 3.1
- Ruby 2.7
- Custom Runtime on Amazon Linux 2
Migrating
Migrating from x86 to arm architecture can be smooth, but varies a lot depending on the runtime you use and which dependencies you have. Many lambda functions may only need a configuration change to take advantage of the price/performance of Graviton2. Other functions may require repackaging the lambda function using arm-specific dependencies, or rebuilding the function binary or container image.
If your functions don't use architecture-specific binaries or dependencies, you can switch from one architecture to the other. This is often the case for many functions using interpreted languages such as Node.js and Python or functions compiled to Java bytecode.
Known issues and considerations
AWS maintains a GitHub repository where they report current developments, known (language specific) issues and workarounds. Here are some direct links to guides and considerations:
And here are some highlights of what you can encounter:
- For Python, you need to make sure that you not using an out of date version of pip (<19.3). Also, in the case pip could not find a pre-compiled package, it automatically downloads, compiles, and builds the packages from source code. Most notorious is pandas, which now can take up to 20 minutes to install.
- While Java 8 is fully supported on arm processors, some customers haven't been able to obtain Graviton's full performance benefit until they switched to Java 11.
- With .NET 5 Microsoft has made specific arm architecture optimizations resulting in significant increase in performance.
- Lastly, when compiling Rust, you need to set target-cpu to neoverse-n1.
Testing performance and cost
To benchmark your lambda in performance and cost can be easily done by the lambda power tuning tool. A PoC has been run at PostNL Data Solutions for two simple Python lambda functions. There was an improvement in costs of ~20%, unfortunately there was no significant change in performance.
Results of the AWS Lambda Power Tuning tool for the Address Check National API lambda
Results of the AWS Lambda Power Tuning tool for the Address Check International API lambda
Conclusion
In general, use the new arm architecture if you can. Often it is just a configuration change in you configuration/CDK code. If having to deal with x86 specific binaries/dependencies, check the known issues and workarounds to tackle them.
Have you already tried the new architecture? I'm curious about your experiences.
Thanks to Selcuk Sasoglu for proof-reading this post.
References
- [1] - x86-64 Wikipedia
- [2] - AArch64 Wikipedia
- [3] - AWS Lambda Pricing
- [4] - AWS Lambda Architecture Documentation
- [5] - AWS Graviton Getting Started - Lambda
- [6] - AWS Blog - Graviton2 Lambda Functions
- [7] - AWS Graviton Getting Started Repository
- [8] - .NET ARM64 Performance
- [9] - AWS Lambda Power Tuning Tool
Originally published on Medium - PostNL Engineering