Skip to content

Commit e5a53ad

Browse files
authored
feat: lambda-power-tuning (#249)
* feat: added powertuning with config ready to test the lambda performence and optimize for cost. * feat: lamnda arn updated on both examples. * fix: stack name updated. * feat: invoked and updated lambda config. * fix: copilot suggestions and typos, some minor improvments.
1 parent 7c2346e commit e5a53ad

File tree

9 files changed

+334
-3
lines changed

9 files changed

+334
-3
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
name: AWS Lambda Power Tuning Script Runner
2+
description: Runs a bash script with a JSON config (from path or inline), with optional overrides.
3+
branding:
4+
icon: terminal
5+
color: blue
6+
7+
inputs:
8+
config_json_directory:
9+
description: Directory where the config JSON file is located.
10+
required: true
11+
config_json_name:
12+
description: Name of the config JSON file.
13+
required: true
14+
15+
runs:
16+
using: composite
17+
steps:
18+
- name: Check if config JSON exists
19+
shell: bash
20+
id: check_config
21+
working-directory: ${{ github.action_path }}
22+
env:
23+
CONFIG_JSON_PATH: ${{ inputs.config_json_directory }}/${{ inputs.config_json_name }}
24+
run: |
25+
if [ ! -f "${CONFIG_JSON_PATH}" ]; then
26+
echo "Config JSON file not found at $CONFIG_JSON_PATH"
27+
exit 1
28+
fi
29+
30+
- name: AWS Lambda Power Tuning Script Execution
31+
id: analysis
32+
shell: bash
33+
working-directory: ${{ github.action_path }}
34+
env:
35+
CONFIG_JSON_PATH: ${{ inputs.config_json_directory }}/${{ inputs.config_json_name }}
36+
run: |
37+
./execute.sh $CONFIG_JSON_PATH | tee output.log
38+
39+
- name: Write Summary to GitHub Step Summary
40+
if: steps.analysis.outcome == 'success'
41+
shell: bash
42+
working-directory: ${{ github.action_path }}
43+
run: |
44+
# Extract the visualization URL from the output
45+
VISUALIZATION_URL=$(grep -o 'https://lambda-power-tuning.show/[^"]*' output.log)
46+
47+
# Write formatted summary
48+
{
49+
echo '### ✅ AWS Lambda Power Tuning Summary'
50+
echo ''
51+
echo '**Execution Status:** `SUCCEEDED`'
52+
echo ''
53+
echo '**🔍 Output Details:**'
54+
echo '```json'
55+
cat output.log
56+
echo '```'
57+
echo ''
58+
echo '**📊 Visualization:** [🔗 Click here to view the visualization]('$VISUALIZATION_URL')'
59+
echo ''
60+
echo '---'
61+
} >> $GITHUB_STEP_SUMMARY
62+
63+
- name: Write Error to GitHub Step Summary
64+
if: steps.analysis.outcome != 'success'
65+
shell: bash
66+
working-directory: ${{ github.action_path }}
67+
run: |
68+
# Write error message to step summary
69+
{
70+
echo '### ❌ AWS Lambda Power Tuning Failed'
71+
echo ''
72+
echo 'An error occurred while running the AWS Lambda Power Tuning script.'
73+
echo ''
74+
echo 'Please check the logs for more details.'
75+
echo ''
76+
echo '---'
77+
} >> $GITHUB_STEP_SUMMARY
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#!/usr/bin/env bash
2+
# config
3+
4+
set -euox pipefail
5+
6+
if [[ $# -gt 1 ]]; then
7+
echo "Incorrect Usage: $0 [input json file path]"
8+
exit 1
9+
fi
10+
11+
STACK_NAME=powerTuning
12+
INPUT=$(cat "${1:-sample-execution-input.json}") # or use a static string
13+
14+
PROFILE="default"
15+
REGION="us-east-1"
16+
17+
# retrieve state machine ARN
18+
STATE_MACHINE_ARN=$(aws stepfunctions list-state-machines \
19+
--query "stateMachines[?contains(name,\`${STACK_NAME}\`)]|[0].stateMachineArn" \
20+
--output text \
21+
--profile $PROFILE \
22+
--region $REGION |
23+
cat)
24+
25+
# start execution
26+
EXECUTION_ARN=$(aws stepfunctions start-execution \
27+
--state-machine-arn $STATE_MACHINE_ARN \
28+
--input "$INPUT" \
29+
--query 'executionArn' \
30+
--output text --profile $PROFILE \
31+
--region $REGION)
32+
33+
echo -n "Execution started..."
34+
35+
# poll execution status until completed
36+
while true; do
37+
# retrieve execution status
38+
STATUS=$(aws stepfunctions describe-execution \
39+
--execution-arn $EXECUTION_ARN \
40+
--query 'status' \
41+
--output text \
42+
--profile $PROFILE \
43+
--region $REGION)
44+
45+
if test "$STATUS" == "RUNNING"; then
46+
# keep looping and wait if still running
47+
echo -n "."
48+
sleep 1
49+
elif test "$STATUS" == "FAILED"; then
50+
# exit if failed
51+
echo -e "\nThe execution failed, you can check the execution logs with the following script:\naws stepfunctions get-execution-history --execution-arn $EXECUTION_ARN"
52+
break
53+
else
54+
# print execution output if succeeded
55+
echo $STATUS
56+
echo "Execution output: "
57+
# retrieve output
58+
aws stepfunctions describe-execution \
59+
--execution-arn $EXECUTION_ARN \
60+
--query 'output' \
61+
--output text \
62+
--profile $PROFILE \
63+
--region $REGION |
64+
cat
65+
break
66+
fi
67+
done
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# .github/workflows/lambda-analysis.yaml
2+
---
3+
name: Lambda Analysis
4+
on:
5+
workflow_dispatch:
6+
inputs:
7+
config_json_directory:
8+
description: Directory where the config JSON file is located.
9+
required: true
10+
config_json_name:
11+
description: Name of the config JSON file.
12+
required: true
13+
14+
jobs:
15+
run:
16+
runs-on: ubuntu-latest
17+
permissions:
18+
contents: read
19+
id-token: write
20+
defaults:
21+
run:
22+
shell: bash
23+
steps:
24+
- name: Checkout
25+
uses: actions/checkout@v4
26+
27+
- name: Configure AWS Credentials
28+
uses: aws-actions/configure-aws-credentials@v4
29+
with:
30+
aws-region: us-east-1
31+
role-session-name: GitHubActions-LambdaAnalysis
32+
role-duration-seconds: 1800
33+
34+
- name: Run Lambda Power Tuning Script
35+
uses: ./.github/actions/aws-lambda-power-tuning
36+
env:
37+
CONFIG_JSON_DIRECTORY: ${{ github.workspace }}/${{ github.event.inputs.config_json_directory }}
38+
with:
39+
config_json_directory: ${{ env.CONFIG_JSON_DIRECTORY }}
40+
config_json_name: ${{ github.event.inputs.config_json_name }}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"lambdaARN": "arn:aws:lambda:us-east-1:747477446688:function:prod-AwsLambdaCalculatorS-AwsLambdaCalculatorLambd-1k47ZCQqMsV3",
3+
"num": 50,
4+
"powerValues": [128, 256, 512, 1024, 2048, 3008, 4096, 5120, 6144, 7168, 8192],
5+
"payload": [
6+
{ "payload": {"region":"us-east-1","architecture":"x86_64","number_of_requests":1000000,"request_unit":"per month","duration_of_each_request_in_ms":1500,"memory":128,"memory_unit":"MB","ephemeral_storage":512,"storage_unit":"MB","include_free_tier":true,"verbose":true}, "weight": 10 },
7+
{ "payload": {"region":"us-east-1","architecture":"arm64","number_of_requests":1000000,"request_unit":"per month","duration_of_each_request_in_ms":1500,"memory":128,"memory_unit":"MB","ephemeral_storage":512,"storage_unit":"MB","include_free_tier":true,"verbose":true}, "weight": 10 },
8+
{ "payload": {"region":"us-west-2","architecture":"x86_64","number_of_requests":100000,"request_unit":"per day","duration_of_each_request_in_ms":3000,"memory":1024,"memory_unit":"MB","ephemeral_storage":2,"storage_unit":"GB","include_free_tier":false,"verbose":true}, "weight": 10 },
9+
{ "payload": {"region":"us-west-2","architecture":"arm64","number_of_requests":100000,"request_unit":"per day","duration_of_each_request_in_ms":3000,"memory":1024,"memory_unit":"MB","ephemeral_storage":2,"storage_unit":"GB","include_free_tier":false,"verbose":true}, "weight": 10 },
10+
{ "payload": {"region":"eu-central-1","architecture":"x86_64","number_of_requests":10000,"request_unit":"per minute","duration_of_each_request_in_ms":400,"memory":2,"memory_unit":"GB","ephemeral_storage":1,"storage_unit":"GB","include_free_tier":true,"verbose":true}, "weight": 10 },
11+
],
12+
"payloadS3": "",
13+
"parallelInvocation": true,
14+
"strategy": "cost",
15+
"balancedWeight": 1.0,
16+
"autoOptimize": true,
17+
"autoOptimizeAlias": "optimized",
18+
"dryRun": false,
19+
"preProcessorARN": "",
20+
"postProcessorARN": "",
21+
"discardTopBottom": 0.2,
22+
"sleepBetweenRunsMs": 0,
23+
"disablePayloadLogs": false,
24+
"includeOutputResults": true,
25+
"onlyColdStarts": false,
26+
"allowedExceptions": []
27+
}

power-tuning/execute.sh

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#!/usr/bin/env bash
2+
# config
3+
4+
set -euox pipefail
5+
6+
if [[ $# -gt 1 ]]; then
7+
echo "Incorrect Usage: $0 [input json file path]"
8+
exit 1
9+
fi
10+
11+
STACK_NAME=powerTuning
12+
INPUT=$(cat "${1:-simple-execution-input.json}") # or use a static string
13+
14+
PROFILE="zMynx"
15+
REGION="us-east-1"
16+
17+
# retrieve state machine ARN
18+
STATE_MACHINE_ARN=$(aws stepfunctions list-state-machines \
19+
--query "stateMachines[?contains(name,\`${STACK_NAME}\`)]|[0].stateMachineArn" \
20+
--output text \
21+
--profile $PROFILE \
22+
--region $REGION |
23+
cat)
24+
25+
# start execution
26+
EXECUTION_ARN=$(aws stepfunctions start-execution \
27+
--state-machine-arn $STATE_MACHINE_ARN \
28+
--input "$INPUT" \
29+
--query 'executionArn' \
30+
--output text --profile $PROFILE \
31+
--region $REGION)
32+
33+
echo -n "Execution started..."
34+
35+
# poll execution status until completed
36+
while true; do
37+
# retrieve execution status
38+
STATUS=$(aws stepfunctions describe-execution \
39+
--execution-arn $EXECUTION_ARN \
40+
--query 'status' \
41+
--output text \
42+
--profile $PROFILE \
43+
--region $REGION)
44+
45+
if test "$STATUS" == "RUNNING"; then
46+
# keep looping and wait if still running
47+
echo -n "."
48+
sleep 1
49+
elif test "$STATUS" == "FAILED"; then
50+
# exit if failed
51+
echo -e "\nThe execution failed, you can check the execution logs with the following script:\naws stepfunctions get-execution-history --execution-arn $EXECUTION_ARN"
52+
break
53+
else
54+
# print execution output if succeeded
55+
echo $STATUS
56+
echo "Execution output: "
57+
# retrieve output
58+
aws stepfunctions describe-execution \
59+
--execution-arn $EXECUTION_ARN \
60+
--query 'output' \
61+
--output text \
62+
--profile $PROFILE \
63+
--region $REGION |
64+
cat
65+
break
66+
fi
67+
done

power-tuning/run.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/usr/bin/env bash
2+
3+
PROFILE="zMynx"
4+
REGION="us-east-1"
5+
6+
zip function.zip lambda_function.py
7+
8+
aws iam create-role \
9+
--role-name lambda-basic-execution \
10+
--assume-role-policy-document file://trust-policy.json \
11+
--profile $PROFILE \
12+
--region $REGION
13+
14+
aws iam attach-role-policy \
15+
--role-name lambda-basic-execution \
16+
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole \
17+
--profile $PROFILE \
18+
--region $REGION
19+
20+
aws lambda create-function \
21+
--function-name FibonacciBenchmark \
22+
--runtime python3.13 \
23+
--role arn:aws:iam::1234567890:role/lambda-basic-execution \
24+
--handler lambda_function.lambda_handler \
25+
--zip-file fileb://function.zip \
26+
--timeout 120 \
27+
--profile $PROFILE \
28+
--region $REGION
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"lambdaARN": "arn:aws:lambda:us-east-1:747477446688:function:prod-AwsLambdaCalculatorS-AwsLambdaCalculatorLambd-1k47ZCQqMsV3",
3+
"num": 3,
4+
"powerValues": [128, 256, 512, 1024, 2048],
5+
"payload": [
6+
{ "payload": {"region":"us-east-1","architecture":"x86_64","number_of_requests":1000000,"request_unit":"per month","duration_of_each_request_in_ms":1500,"memory":128,"memory_unit":"MB","ephemeral_storage":512,"storage_unit":"MB","include_free_tier":true,"verbose":true}, "weight": 3 }
7+
],
8+
"parallelInvocation": true,
9+
"strategy": "balanced",
10+
"balancedWeight": 0.5,
11+
"dryRun": false,
12+
"onlyColdStarts": false,
13+
"allowedExceptions": []
14+
}

power-tuning/trust-policy.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"Version": "2012-10-17",
3+
"Statement": [
4+
{
5+
"Effect": "Allow",
6+
"Principal": {
7+
"Service": "lambda.amazonaws.com"
8+
},
9+
"Action": "sts:AssumeRole"
10+
}
11+
]
12+
}

serverless/cdk-app/lib/cdk-app-stack.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,8 @@ export class AwsLambdaCalculatorStack extends cdk.Stack {
3232
code: lambda.DockerImageCode.fromEcr(dockerAsset.repository, {
3333
tagOrDigest: dockerAsset.assetHash,
3434
}),
35-
// Set memory and timeout limits for cost control
36-
memorySize: 512, // Adjust based on your needs
37-
timeout: cdk.Duration.seconds(30), // Prevent long-running requests
35+
memorySize: 1024,
36+
timeout: cdk.Duration.seconds(45), // Prevent long-running requests
3837
});
3938

4039
const logGroup = new logs.LogGroup(this, "AwsLambdaCalculatorApiGatewayAccessLogs", {

0 commit comments

Comments
 (0)