Moving AWS Lambda functions with Golang to Graviton chips

allows you to configure new and existing functions to run on Arm-based AWS Graviton2 processors in addition to x86-based functions.

On top, with this choice you can save money in two ways. First, your functions run more efficiently due to the Graviton2 architecture. Second, you pay less for the time that they run. In fact, Lambda functions powered by Graviton2 are designed to deliver up to 19 percent better performance at 20 percent lower cost.

But what is the high-level architecture exactly?

Every vCPU is a physical core and this offers better scalability. It offers more cache on per CPU-basis, and as depicted above, it means that there’s no (SMT) with more isolation between vCPUs. By contrast, every vCPU on a 5th generation instance type with Intel chips, is a hyper-thread. Having large L1 and L2 caches for every vCPU means that most of the times, a large portion of your workload will fit in cache, without the extra roundtrip in memory.

Gravitons are also implemented using a single socket with a flat memory hierarchy and with a single Non-uniform memory access domain. Under , a processor can access its own local memory faster than non-local memory. This accommodates for the same latency and bandwidth to memory for every vCPU.

How to run an AWS Lambda function with Golang on Graviton

For Golang to run on Graviton, you need to specify the Architecture to arm64 and the Runtime to provided.al2 (Provide your own bootstrap on Amazon Linux 2).

Then, for your handler code to run in a custom runtime, you need to package it with code that handles the Lambda Runtime API into a binary called bootstrap. The library provides a custom runtime mode out of the box and it has the logic to determine whether it is running in a native or custom runtime.

This means that all you need to do, is change your build process to rename the produced binary to bootstrap and it will work in a custom runtime without any changes to the handler code.

Action!

Using the test function below, we need to compile the code to the bootstrap binary, zip it and upload it through the console. You can find more details on custom runtimes for AWS Lambda .

package main

import (
"fmt"
"github.com/aws/aws-lambda-go/lambda"
)

func main() {
lambda.Start(Handler)
}

func Handler() {
fmt.Println("Hello AWS Lambda from Graviton!")
}
$ GOOS=linux GOARCH=arm64 go build -o boostrap .
$ zip function.zip bootstrap

Final thoughts:

What if you want to maintain the same Lambda function for both x86 and Arm and how do you roll them out in production?

Since you have the ability to , you can create one or more aliases for your Lambda function. An alias is like a pointer to a specific function version. You can then send traffic to the function via an alias using weights to distribute traffic between the two versions. You can also use function versions and weighted aliases to control the rollout to production. For example you can deploy the Arm version to a small amount of invocations (such as 5%) and then increase up to 100% for a complete deployment. During rollout, you can lower the weight or set it to zero if your metrics show something suspicious (such as an increase in errors).

How do you monitor the functions to determine which version is performing better?

In , performance metrics are collected by function and you can look at key indicators (such as duration) using . You can then compare, for example, average and duration between the two architectures.

--

--

AWS Senior Solutions Architect by profession, Software Engineer by heart. https://www.linkedin.com/in/spei

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store