Files
2025-11-29 18:25:52 +08:00

268 lines
6.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
description: Deep dive into Lambda cost optimization strategies for Rust functions
---
You are helping the user optimize the cost of their Rust Lambda functions.
## Your Task
Guide the user through advanced cost optimization techniques using AWS Lambda Power Tuning, memory configuration, and Rust-specific optimizations.
## Lambda Pricing Model
**Cost = (Requests × $0.20 per 1M) + (GB-seconds × $0.0000166667)**
- **Requests**: $0.20 per 1 million requests
- **Duration**: Charged per GB-second
- 1 GB-second = 1 GB memory × 1 second execution
- ARM64 (Graviton2): 20% cheaper than x86_64
**Example**:
- 512 MB, 100ms execution, 1M requests/month
- Duration: 0.5 GB × 0.1s × 1M = 50,000 GB-seconds
- Cost: $0.20 + (50,000 × $0.0000166667) = $0.20 + $0.83 = $1.03
## Memory vs CPU Allocation
Lambda allocates CPU proportional to memory:
- **128 MB**: 0.08 vCPU
- **512 MB**: 0.33 vCPU
- **1024 MB**: 0.58 vCPU
- **1769 MB**: 1.00 vCPU (full core)
- **3008 MB**: 1.77 vCPU
- **10240 MB**: 6.00 vCPU
**Key insight**: More memory = more CPU = faster execution = potentially lower cost
## AWS Lambda Power Tuning Tool
Automatically finds optimal memory configuration.
### Setup
```bash
# Deploy Power Tuning (one-time)
git clone https://github.com/alexcasalboni/aws-lambda-power-tuning
cd aws-lambda-power-tuning
sam deploy --guided
# Run power tuning
aws stepfunctions start-execution \
--state-machine-arn arn:aws:states:REGION:ACCOUNT:stateMachine:powerTuningStateMachine \
--input '{
"lambdaARN": "arn:aws:lambda:REGION:ACCOUNT:function:my-rust-function",
"powerValues": [128, 256, 512, 1024, 1536, 2048, 3008],
"num": 10,
"payload": "{\"test\": \"data\"}",
"parallelInvocation": true,
"strategy": "cost"
}'
```
**Strategies**:
- `cost`: Minimize cost
- `speed`: Minimize duration
- `balanced`: Balance cost and speed
## Rust-Specific Optimizations
### 1. Binary Size Reduction
**Cargo.toml**:
```toml
[profile.release]
opt-level = 'z' # Optimize for size
lto = true # Link-time optimization
codegen-units = 1 # Single codegen unit
strip = true # Strip symbols
panic = 'abort' # Smaller panic handler
[profile.release.package."*"]
opt-level = 'z' # Optimize dependencies too
```
**Result**: 3-5x smaller binary = faster cold starts = lower duration
### 2. Use ARM64 (Graviton2)
```bash
cargo lambda build --release --arm64
cargo lambda deploy --arch arm64
```
**Savings**: 20% lower cost for same performance
### 3. Dependency Optimization
```bash
# Analyze binary size
cargo install cargo-bloat
cargo bloat --release -n 20
# Find unused features
cargo install cargo-unused-features
cargo unused-features
# Remove unused dependencies
cargo install cargo-udeps
cargo +nightly udeps
```
**Example**:
```toml
# ❌ Full tokio (heavy)
tokio = { version = "1", features = ["full"] }
# ✅ Only needed features (light)
tokio = { version = "1", features = ["macros", "rt"] }
```
### 4. Use Lightweight Alternatives
- `ureq` instead of `reqwest` for simple HTTP
- `rustls` instead of `native-tls`
- `simdjson` instead of `serde_json` for large JSON
- Avoid `regex` for simple string operations
## Memory Configuration Strategies
### Strategy 1: Start Low, Test Up
```bash
# Test different memory sizes
for mem in 128 256 512 1024 2048; do
echo "Testing ${mem}MB"
cargo lambda deploy --memory $mem
# Run load test
# Measure duration and cost
done
```
### Strategy 2: Monitor CloudWatch Metrics
```bash
# Get duration statistics
aws cloudwatch get-metric-statistics \
--namespace AWS/Lambda \
--metric-name Duration \
--dimensions Name=FunctionName,Value=my-function \
--start-time 2025-01-01T00:00:00Z \
--end-time 2025-01-02T00:00:00Z \
--period 3600 \
--statistics Average,Maximum
# Get memory usage
aws cloudwatch get-metric-statistics \
--namespace AWS/Lambda \
--metric-name MemoryUtilization \
--dimensions Name=FunctionName,Value=my-function \
--start-time 2025-01-01T00:00:00Z \
--end-time 2025-01-02T00:00:00Z \
--period 3600 \
--statistics Maximum
```
### Strategy 3: Right-size Based on Workload
**IO-intensive** (API calls, DB queries):
- Start: 512 MB
- Sweet spot: Usually 512-1024 MB
- Reason: Limited by network, not CPU
**Compute-intensive** (data processing):
- Start: 1024 MB
- Sweet spot: Usually 1769-3008 MB
- Reason: More CPU = faster = lower total cost
**Mixed workload**:
- Start: 1024 MB
- Test: 1024, 1769, 2048 MB
- Use Power Tuning tool
## Cost Optimization Checklist
- [ ] Use ARM64 architecture (20% savings)
- [ ] Optimize binary size (faster cold starts)
- [ ] Remove unused dependencies
- [ ] Use lightweight alternatives
- [ ] Run AWS Lambda Power Tuning
- [ ] Right-size memory based on workload
- [ ] Set appropriate timeout (not too high)
- [ ] Reduce cold starts (keep functions warm if needed)
- [ ] Use reserved concurrency for predictable workloads
- [ ] Batch requests when possible
- [ ] Cache results (DynamoDB, ElastiCache)
- [ ] Monitor and alert on cost anomalies
## Advanced: Provisioned Concurrency
For latency-sensitive functions, pre-warm instances.
**Cost**: $0.015 per GB-hour (expensive!)
```bash
aws lambda put-provisioned-concurrency-config \
--function-name my-function \
--provisioned-concurrent-executions 5
```
**Use when**:
- Cold starts are unacceptable
- Predictable traffic patterns
- Cost justifies latency improvement
## Cost Monitoring
### CloudWatch Billing Alerts
```bash
aws cloudwatch put-metric-alarm \
--alarm-name lambda-cost-alert \
--alarm-description "Alert when Lambda costs exceed threshold" \
--metric-name EstimatedCharges \
--namespace AWS/Billing \
--statistic Maximum \
--period 21600 \
--evaluation-periods 1 \
--threshold 100 \
--comparison-operator GreaterThanThreshold
```
### Cost Explorer Tags
```bash
cargo lambda deploy \
--tags Environment=production,Team=backend,CostCenter=engineering
```
## Real-World Optimization Example
**Before**:
- Memory: 128 MB
- Duration: 2000ms
- Requests: 10M/month
- Cost: $0.20 + (0.128 GB × 2s × 10M × $0.0000166667) = $42.87/month
**After Optimization**:
- Binary size: 8MB → 2MB (cold start: 800ms → 300ms)
- Architecture: x86_64 → ARM64 (20% cheaper)
- Memory: 128 MB → 512 MB (duration: 2000ms → 600ms)
- Duration improvement: More CPU = faster execution
**Cost calculation**:
- Compute: 0.512 GB × 0.6s × 10M × $0.0000166667 × 0.8 (ARM discount) = $40.96
- Requests: $0.20
- **Total**: $41.16/month (4% savings with better performance!)
**Key lesson**: Sometimes more memory = lower total cost due to faster execution.
## Rust Performance Advantage
Rust vs Python/Node.js:
- **3-4x cheaper** on average
- **3-10x faster execution**
- **2-3x faster cold starts**
- **Lower memory usage**
Guide the user through cost optimization based on their workload and budget constraints.