Please refer to Optimizing AWS Lambda extensions in C# and Rust blog for more details.
To follow the solution walkthrough, you will need to:
- An AWS Account.
- Set up the AWS CLI to deploy resources to your account.
- Have the appropriate AWS Credentials configured.
- Rust, Cargo Lambda, dotnet sdk, and curl (version 7.75.0 or higher) installed.
- Install Docker on your machine.
- Bootstrap your environment with AWS CDK.
You can use your preferred IDE to deploy the solution. Refer to the cleanup section of this post for instructions to delete the resources to stop incurring any further charges.
- Clone the project repository to your local machine.
git clone https://github.com/aws-samples/lambda-extesion-optimization.git
- Navigate to the solution folder.
cd lambda-extension-optimization/app/
- Install the packages required.
npm install
- Store the AWS profile name in a variable.
AWS_PROFILE="<AWS profile to be used>"
- Store the stack name in a variable.
STACK_NAME="demo-blank-ext-stack"
- Inspect the code.
HeaderCounter
Lambda function has a500 ms
delay baked into it.Blank
extension written in .NET 6 has acorp-demo-extensions-blank
shell script that is responsible for running the extension. The extension is leveraging a common library that is responsible for the extension registration and continuous operation.Blank
extension written in Rust is leveraginglambda-extension
crate that is taking care of the extension registration and continuous operation.
- Build the source files.
../scripts/publish-src.sh
- Deploy the solution stack.
cdk deploy $STACK_NAME --context lambda-memory=128 --profile $AWS_PROFILE
- Store the endpoints into corresponding variables.
API_URL_NO_EXT=$(aws cloudformation describe-stacks \
--stack-name $STACK_NAME \
--query "Stacks[0].Outputs[?OutputKey=='NoExtensionLambdaUrl'].OutputValue" \
--output text \
--profile $AWS_PROFILE)
echo $API_URL_NO_EXT
API_URL_DOTNET_EXT=$(aws cloudformation describe-stacks \
--stack-name $STACK_NAME \
--query "Stacks[0].Outputs[?OutputKey=='DotnetExtensionLambdaUrl'].OutputValue" \
--output text \
--profile $AWS_PROFILE)
echo $API_URL_DOTNET_EXT
API_URL_RUST_EXT=$(aws cloudformation describe-stacks \
--stack-name $STACK_NAME \
--query "Stacks[0].Outputs[?OutputKey=='RustExtensionLambdaUrl'].OutputValue" \
--output text \
--profile $AWS_PROFILE)
echo $API_URL_RUST_EXT
- Load test the solution by running the
load-test.sh
script against the endpoints.
ac=$(aws configure get aws_access_key_id --profile $AWS_PROFILE)
sc=$(aws configure get aws_secret_access_key --profile $AWS_PROFILE)
rg=$(aws configure get region --profile $AWS_PROFILE)
../scripts/load-test.sh $API_URL_NO_EXT $ac $sc $rg
../scripts/load-test.sh $API_URL_DOTNET_EXT $ac $sc $rg
../scripts/load-test.sh $API_URL_RUST_EXT $ac $sc $rg
- Navigate to Amazon CloudWatch (make sure you select the region where you stack is deployed).
- Select
Dashboards
in the left-hand side menu. - Click on
lambda-performance-dashboard
to open the dashboard. - Inspect the results.
- Clean up by deleting the CDK stack.
cdk destroy $STACK_NAME --profile $AWS_PROFILE
- Store the stack name in a variable.
STACK_NAME="demo-ec-ext-stack"
- Inspect the code.
HeaderCounter
Lambda function has a500 ms
delay baked into it.EventCollector
extension written in .NET 6 has acorp-demo-extensions-event-collector
shell script that is responsible for running the extension. The extension is leveraging a common library that is responsible for the extension registration and continuous operation.EventCollector
extension written in Rust is leveraginglambda-extension
crate that is taking care of the extension registration and continuous operation.
- Build the source files.
../scripts/publish-src.sh
- Deploy the solution stack.
cdk deploy $STACK_NAME --context lambda-memory=128 --profile $AWS_PROFILE
- Store the endpoints into corresponding variables.
API_URL_NO_EXT=$(aws cloudformation describe-stacks \
--stack-name $STACK_NAME \
--query "Stacks[0].Outputs[?OutputKey=='NoExtensionLambdaUrl'].OutputValue" \
--output text \
--profile $AWS_PROFILE)
echo $API_URL_NO_EXT
API_URL_DOTNET_EXT=$(aws cloudformation describe-stacks \
--stack-name $STACK_NAME \
--query "Stacks[0].Outputs[?OutputKey=='DotnetExtensionLambdaUrl'].OutputValue" \
--output text \
--profile $AWS_PROFILE)
echo $API_URL_DOTNET_EXT
API_URL_RUST_EXT=$(aws cloudformation describe-stacks \
--stack-name $STACK_NAME \
--query "Stacks[0].Outputs[?OutputKey=='RustExtensionLambdaUrl'].OutputValue" \
--output text \
--profile $AWS_PROFILE)
echo $API_URL_RUST_EXT
- Load test the solution by running the
load-test.sh
script against the endpoints.
ac=$(aws configure get aws_access_key_id --profile $AWS_PROFILE)
sc=$(aws configure get aws_secret_access_key --profile $AWS_PROFILE)
rg=$(aws configure get region --profile $AWS_PROFILE)
../scripts/load-test.sh $API_URL_NO_EXT $ac $sc $rg
../scripts/load-test.sh $API_URL_DOTNET_EXT $ac $sc $rg
../scripts/load-test.sh $API_URL_RUST_EXT $ac $sc $rg
- Navigate to Amazon CloudWatch (make sure you select the region where you stack is deployed).
- Select
Dashboards
in the left-hand side menu. - Click on
lambda-performance-dashboard
to open the dashboard. - Inspect the results.
- Clean up by deleting the CDK stack.
cdk destroy $STACK_NAME --profile $AWS_PROFILE
- Store the stack name in a variable.
STACK_NAME="demo-ec-aot-ext-stack"
- Inspect the code.
HeaderCounter
Lambda function has a500 ms
delay baked into it.EventCollector
extension written in .NET 7 is compiled into an executable using thepublish-src-aot.sh
shell script. The extension is leveraging a common library that is responsible for the extension registration and continuous operation. The extension is using a custom serializer required for the Native AOT compilation.EventCollector
extension written in Rust is leveraginglambda-extension
crate that is taking care of the extension registration and continuous operation.
- Make sure you have public.ecr.aws/sam/build-dotnet7 image.
# search for public.ecr.aws/sam/build-dotnet7
docker images -a
- If the public.ecr.aws/sam/build-dotnet7 is not present, pull the image.
# make sure to select the right architecture
docker pull public.ecr.aws/sam/build-dotnet7:latest-x86_64
- Build the source files.
../scripts/publish-src-aot.sh
- Deploy the solution stack.
cdk deploy $STACK_NAME --context lambda-memory=128 --profile $AWS_PROFILE
Warning
Make sure you do not see this message:
[WARNING]: Cannot find EventCollector extension built using Native AOT. Falling back to the DLL
. You will need to fix the Native AOT build in case the message above appears.
- Store the endpoints into corresponding variables.
API_URL_NO_EXT=$(aws cloudformation describe-stacks \
--stack-name $STACK_NAME \
--query "Stacks[0].Outputs[?OutputKey=='NoExtensionLambdaUrl'].OutputValue" \
--output text \
--profile $AWS_PROFILE)
echo $API_URL_NO_EXT
API_URL_DOTNET_EXT=$(aws cloudformation describe-stacks \
--stack-name $STACK_NAME \
--query "Stacks[0].Outputs[?OutputKey=='DotnetExtensionLambdaUrl'].OutputValue" \
--output text \
--profile $AWS_PROFILE)
echo $API_URL_DOTNET_EXT
API_URL_RUST_EXT=$(aws cloudformation describe-stacks \
--stack-name $STACK_NAME \
--query "Stacks[0].Outputs[?OutputKey=='RustExtensionLambdaUrl'].OutputValue" \
--output text \
--profile $AWS_PROFILE)
echo $API_URL_RUST_EXT
- Load test the solution by running the
load-test.sh
script against the endpoints.
ac=$(aws configure get aws_access_key_id --profile $AWS_PROFILE)
sc=$(aws configure get aws_secret_access_key --profile $AWS_PROFILE)
rg=$(aws configure get region --profile $AWS_PROFILE)
../scripts/load-test.sh $API_URL_NO_EXT $ac $sc $rg
../scripts/load-test.sh $API_URL_DOTNET_EXT $ac $sc $rg
../scripts/load-test.sh $API_URL_RUST_EXT $ac $sc $rg
- Navigate to Amazon CloudWatch (make sure you select the region where you stack is deployed).
- Select
Dashboards
in the left-hand side menu. - Click on
lambda-performance-dashboard
to open the dashboard. - Inspect the results.
- Clean up by deleting the CDK stack.
cdk destroy $STACK_NAME --profile $AWS_PROFILE
Make sure you follow the cleanup process to avoid any unexpected charges.
See CONTRIBUTING for more information.
This library is licensed under the MIT-0 License. See the LICENSE file.
Warning
You should not use this AWS Content in your production accounts, or on production or other critical data. You are responsible for testing, securing, and optimizing the AWS Content, such as sample code, as appropriate for production grade use based on your specific quality control practices and standards.