Skip to content

Commit e9edf98

Browse files
committed
tests: add benchmark on AWS Lambda
1 parent 1131541 commit e9edf98

File tree

7 files changed

+149
-0
lines changed

7 files changed

+149
-0
lines changed

benchmark/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.aws-sam

benchmark/benchmark.sh

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#!/bin/bash
2+
3+
set -e
4+
trap cleanup EXIT
5+
6+
export BENCHMARK_STACK_NAME=${BENCHMARK_STACK_NAME:-"powertools-benchmark"}
7+
8+
function cleanup {
9+
echo "Cleaning up stack..."
10+
aws cloudformation delete-stack --stack-name $BENCHMARK_STACK_NAME
11+
}
12+
13+
function run_function {
14+
# Update function to force a cold start
15+
aws lambda update-function-configuration --function-name $1 --memory-size 256 >/dev/null
16+
aws lambda update-function-configuration --function-name $1 --memory-size 128 >/dev/null
17+
# Cold-start invoke
18+
aws lambda invoke --function-name $1 --payload '{}' /dev/null >/dev/null && echo -n . || echo -n e
19+
}
20+
21+
# Retrieve statistics
22+
function get_stats {
23+
# Gather results from CloudWatch Logs Insights
24+
query_id=$(aws logs start-query --log-group-name $1 --query-string 'filter @type = "REPORT" | stats avg(@initDuration) as init_duration, avg(@duration) as duration' --start-time $(expr $(date +%s) - 86400) --end-time $(expr $(date +%s) + 0) --query 'queryId' --output text)
25+
while true; do
26+
result=$(aws logs get-query-results --query-id $query_id --query 'status' --output text)
27+
if [ $result == "Complete" ]; then
28+
break
29+
fi
30+
sleep 1
31+
done
32+
33+
# Check if greater than threshold and print result
34+
init_duration=$(aws logs get-query-results --query-id $query_id --query 'results[0][?field==`init_duration`].value' --output text)
35+
duration=$(aws logs get-query-results --query-id $query_id --query 'results[0][?field==`duration`].value' --output text)
36+
echo "$init_duration,$duration"
37+
}
38+
39+
# Build and deploy the benchmark stack
40+
echo "Building and deploying..."
41+
sam build
42+
sam deploy --stack-name $BENCHMARK_STACK_NAME --guided
43+
44+
# Retrieve output values
45+
echo "Retrieve values..."
46+
export INSTRUMENTED_FUNCTION=$(aws cloudformation describe-stacks --stack-name $BENCHMARK_STACK_NAME --query 'Stacks[0].Outputs[?OutputKey==`InstrumentedFunction`].OutputValue' --output text)
47+
export REFERENCE_FUNCTION=$(aws cloudformation describe-stacks --stack-name $BENCHMARK_STACK_NAME --query 'Stacks[0].Outputs[?OutputKey==`ReferenceFunction`].OutputValue' --output text)
48+
export INSTRUMENTED_LOG_GROUP=$(aws cloudformation describe-stacks --stack-name $BENCHMARK_STACK_NAME --query 'Stacks[0].Outputs[?OutputKey==`InstrumentedLogGroup`].OutputValue' --output text)
49+
export REFERENCE_LOG_GROUP=$(aws cloudformation describe-stacks --stack-name $BENCHMARK_STACK_NAME --query 'Stacks[0].Outputs[?OutputKey==`ReferenceLogGroup`].OutputValue' --output text)
50+
51+
echo INSTRUMENTED_FUNCTION=$INSTRUMENTED_FUNCTION
52+
echo REFERENCE_FUNCTION=$REFERENCE_FUNCTION
53+
echo INSTRUMENTED_LOG_GROUP=$INSTRUMENTED_LOG_GROUP
54+
echo REFERENCE_LOG_GROUP=$REFERENCE_LOG_GROUP
55+
56+
# Running cold starts
57+
echo "Running functions..."
58+
for i in {0..20}; do
59+
run_function $INSTRUMENTED_FUNCTION
60+
done &
61+
process_id=$!
62+
for i in {0..20}; do
63+
run_function $REFERENCE_FUNCTION
64+
done &
65+
wait $process_id
66+
wait $!
67+
echo
68+
69+
# Gather statistics
70+
sleep 150
71+
return_code=0
72+
echo -n "INSTRUMENTED="
73+
get_stats $INSTRUMENTED_LOG_GROUP
74+
echo -n "REFERENCE="
75+
get_stats $REFERENCE_LOG_GROUP
76+
77+
exit $return_code

benchmark/src/instrumented/main.py

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from aws_lambda_powertools import (Logger, Metrics, Tracer)
2+
3+
4+
# Initialize core utilities
5+
logger = Logger()
6+
metrics = Metrics()
7+
tracer = Tracer()
8+
9+
10+
# Instrument Lambda function
11+
@logger.inject_lambda_context
12+
@metrics.log_metrics
13+
@tracer.capture_lambda_handler
14+
def handler(event, context):
15+
return {
16+
"message": "success"
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
aws-lambda-powertools

benchmark/src/reference/main.py

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
def handler(event, context):
2+
return {
3+
"message": "success"
4+
}
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
aws-lambda-powertools

benchmark/template.yaml

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
AWSTemplateFormatVersion: '2010-09-09'
2+
Transform: AWS::Serverless-2016-10-31
3+
4+
Globals:
5+
Function:
6+
Handler: main.handler
7+
Runtime: python3.8
8+
MemorySize: 128
9+
Tracing: Active
10+
Environment:
11+
Variables:
12+
POWERTOOLS_SERVICE_NAME: benchmark
13+
POWERTOOLS_METRICS_NAMESPACE: LambdaPowertools
14+
POWERTOOLS_LOGGER_LOG_EVENT: "true"
15+
LOG_LEVEL: INFO
16+
17+
Resources:
18+
InstrumentedFunction:
19+
Type: AWS::Serverless::Function
20+
Properties:
21+
CodeUri: ./src/instrumented/
22+
23+
ReferenceFunction:
24+
Type: AWS::Serverless::Function
25+
Properties:
26+
CodeUri: ./src/reference/
27+
28+
InstrumentedLogGroup:
29+
Type: AWS::Logs::LogGroup
30+
Properties:
31+
LogGroupName: !Sub "/aws/lambda/${InstrumentedFunction}"
32+
RetentionInDays: 7
33+
34+
ReferenceLogGroup:
35+
Type: AWS::Logs::LogGroup
36+
Properties:
37+
LogGroupName: !Sub "/aws/lambda/${ReferenceFunction}"
38+
RetentionInDays: 7
39+
40+
Outputs:
41+
InstrumentedFunction:
42+
Value: !Ref InstrumentedFunction
43+
ReferenceFunction:
44+
Value: !Ref ReferenceFunction
45+
InstrumentedLogGroup:
46+
Value: !Ref InstrumentedLogGroup
47+
ReferenceLogGroup:
48+
Value: !Ref ReferenceLogGroup

0 commit comments

Comments
 (0)