Skip to content

Commit a5bdeb7

Browse files
authored
chore(rust): add simple performance benchmarks (#2027)
1 parent 928e318 commit a5bdeb7

13 files changed

Lines changed: 1565 additions & 3 deletions

File tree

.github/workflows/performance-benchmarks-go.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# This workflow runs every day 09:00 UTC (1AM PST)
1+
# This workflow runs every day 16:00 UTC (8PM PST)
22
name: Performance Benchmarks
33

44
on:
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# This workflow runs every day 16:00 UTC (8PM PST)
2+
name: Performance Benchmarks
3+
4+
on:
5+
workflow_call:
6+
inputs:
7+
dafny:
8+
description: "The Dafny version to run"
9+
required: false
10+
default: "4.9.0"
11+
type: string
12+
regenerate-code:
13+
description: "Regenerate code using smithy-dafny"
14+
required: false
15+
default: false
16+
type: boolean
17+
mpl-version:
18+
description: "MPL version to use"
19+
required: false
20+
type: string
21+
mpl-head:
22+
description: "Running on MPL HEAD"
23+
required: false
24+
default: false
25+
type: boolean
26+
27+
jobs:
28+
testRust:
29+
strategy:
30+
fail-fast: false
31+
matrix:
32+
library: [DynamoDbEncryption]
33+
benchmark-dir: [db-esdk-performance-testing]
34+
# removed windows-latest because somehow it can't build aws-lc in CI
35+
os: [ubuntu-22.04, macos-15-intel]
36+
runs-on: ${{ matrix.os }}
37+
permissions:
38+
id-token: write
39+
contents: read
40+
env:
41+
RUST_MIN_STACK: 838860800
42+
steps:
43+
- name: Configure AWS Credentials
44+
uses: aws-actions/configure-aws-credentials@v5
45+
with:
46+
aws-region: us-west-2
47+
role-to-assume: arn:aws:iam::370957321024:role/GitHub-CI-DDBEC-Dafny-Role-us-west-2
48+
role-session-name: DDBEC-Dafny-Rust-Tests
49+
50+
- name: Setup Docker
51+
if: matrix.os == 'macos-15-intel' && matrix.library == 'TestVectors'
52+
uses: douglascamata/setup-docker-macos-action@v1.0.2
53+
54+
- name: Support longpaths on Git checkout
55+
run: |
56+
git config --global core.longpaths true
57+
- uses: actions/checkout@v5
58+
- name: Init Submodules
59+
shell: bash
60+
run: |
61+
git submodule update --init --recursive submodules/smithy-dafny
62+
git submodule update --init --recursive submodules/MaterialProviders
63+
64+
- name: Setup Rust Toolchain for GitHub CI
65+
uses: actions-rust-lang/setup-rust-toolchain@v1
66+
with:
67+
components: rustfmt
68+
69+
- name: Setup Dafny
70+
uses: ./submodules/MaterialProviders/.github/actions/setup_dafny/
71+
with:
72+
dafny-version: 4.10.0
73+
74+
- name: Update MPL submodule if using MPL HEAD
75+
if: ${{ inputs.mpl-head == true }}
76+
working-directory: submodules/MaterialProviders
77+
run: |
78+
git checkout main
79+
git pull
80+
git submodule update --init --recursive
81+
git rev-parse HEAD
82+
83+
- name: Setup Java 17 for codegen
84+
uses: actions/setup-java@v5
85+
with:
86+
distribution: "corretto"
87+
java-version: "17"
88+
89+
- name: Install Smithy-Dafny codegen dependencies
90+
uses: ./.github/actions/install_smithy_dafny_codegen_dependencies
91+
92+
- name: Run make polymorph_rust
93+
shell: bash
94+
working-directory: ./${{ matrix.library }}
95+
run: |
96+
make polymorph_rust
97+
98+
- name: Compile ${{ matrix.library }} implementation
99+
shell: bash
100+
working-directory: ./${{ matrix.library }}
101+
run: |
102+
# This works because `node` is installed by default on GHA runners
103+
CORES=$(node -e 'console.log(os.cpus().length)')
104+
make transpile_rust TRANSPILE_TESTS_IN_RUST=1 CORES=$CORES
105+
106+
- name: Run Performance Benchmarks - Quick Mode
107+
shell: bash
108+
working-directory: ./${{matrix.benchmark-dir}}/benchmarks/rust
109+
run: |
110+
cargo run --release -- --quick
111+
112+
- name: Parse and Format Logs
113+
working-directory: ./${{matrix.benchmark-dir}}/benchmarks/results/raw-data/
114+
run: |
115+
LOG_FILE="rust_results.json"
116+
UPLOAD_FILE="cloudwatch_logs.json"
117+
TIMESTAMP=$(date +%s%3N)
118+
jq -c --arg ts "$(date +%s)000" '[.results[] as $result | .metadata as $meta | {timestamp: ($ts | tonumber), message: ({metadata: $meta, result: $result} | tostring)}]' $LOG_FILE > $UPLOAD_FILE
119+
120+
- name: Upload logs to CloudWatch
121+
working-directory: ./${{matrix.benchmark-dir}}/benchmarks/results/raw-data/
122+
run: |
123+
LOG_FILE="cloudwatch_logs.json"
124+
LOG_GROUP="aws-dbesdk-performance-benchmarks"
125+
LOG_STREAM="rust/quick_benchmarks/${{ github.workflow }}"
126+
127+
# Create log stream (ignore if exists)
128+
aws logs create-log-stream \
129+
--log-group-name "$LOG_GROUP" \
130+
--log-stream-name "$LOG_STREAM" 2>/dev/null || true
131+
132+
aws logs put-log-events \
133+
--log-group-name "$LOG_GROUP" \
134+
--log-stream-name "$LOG_STREAM" \
135+
--log-events file://$LOG_FILE

.github/workflows/performance-benchmarks.yml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# This workflow runs every day 09:00 UTC (1AM PST)
1+
# This workflow runs every day 16:00 UTC (8PM PST)
22
name: Performance Benchmarks
33

44
permissions:
@@ -21,8 +21,13 @@ jobs:
2121
uses: ./.github/workflows/performance-benchmarks-go.yml
2222
with:
2323
dafny: ${{needs.getVersion.outputs.version}}
24+
performance-benchmarks-rust:
25+
needs: getVersion
26+
uses: ./.github/workflows/performance-benchmarks-rust.yml
27+
with:
28+
dafny: ${{needs.getVersion.outputs.version}}
2429
notify:
25-
needs: [getVersion, performance-benchmarks-go]
30+
needs: [getVersion, performance-benchmarks-go, performance-benchmarks-rust]
2631
if: ${{ failure() }}
2732
uses: aws/aws-cryptographic-material-providers-library/.github/workflows/slack-notification.yml@main
2833
with:
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
{
2+
"metadata": {
3+
"language": "rust",
4+
"timestamp": "2026-01-22 21:23:51",
5+
"rust_version": "unknown",
6+
"cpu_count": 14,
7+
"total_memory_gb": 48.0,
8+
"total_tests": 3
9+
},
10+
"results": [
11+
{
12+
"test_name": "throughput",
13+
"language": "rust",
14+
"data_size": 102400,
15+
"concurrency": 1,
16+
"encrypt_latency_ms": 2.0424586666666666,
17+
"decrypt_latency_ms": 1.1346386666666666,
18+
"end_to_end_latency_ms": 3.1774306666666665,
19+
"ops_per_second": 313.69134089559503,
20+
"bytes_per_second": 32121993.307708934,
21+
"peak_memory_mb": 0.0,
22+
"memory_efficiency_ratio": 0.0,
23+
"p50_latency": 3.1489589999999996,
24+
"p95_latency": 3.2460456000000004,
25+
"p99_latency": 3.2546755200000006,
26+
"timestamp": "2026-01-22 21:23:51",
27+
"rust_version": "unknown",
28+
"cpu_count": 14,
29+
"total_memory_gb": 48.0,
30+
"alloc": {
31+
"count_k": 45,
32+
"total_m": 8,
33+
"max_bytes_m": 0,
34+
"net_count": 8,
35+
"net_total": 0
36+
}
37+
},
38+
{
39+
"test_name": "memory",
40+
"language": "rust",
41+
"data_size": 102400,
42+
"concurrency": 1,
43+
"encrypt_latency_ms": 0.0,
44+
"decrypt_latency_ms": 0.0,
45+
"end_to_end_latency_ms": 0.0,
46+
"ops_per_second": 0.0,
47+
"bytes_per_second": 0.0,
48+
"peak_memory_mb": 0.4375,
49+
"memory_efficiency_ratio": 0.22321428571428573,
50+
"p50_latency": 0.0,
51+
"p95_latency": 0.0,
52+
"p99_latency": 0.0,
53+
"timestamp": "2026-01-22 21:23:51",
54+
"rust_version": "unknown",
55+
"cpu_count": 14,
56+
"total_memory_gb": 48.0,
57+
"alloc": {
58+
"count_k": 75,
59+
"total_m": 14,
60+
"max_bytes_m": 0,
61+
"net_count": 6,
62+
"net_total": 0
63+
}
64+
},
65+
{
66+
"test_name": "concurrent",
67+
"language": "rust",
68+
"data_size": 102400,
69+
"concurrency": 2,
70+
"encrypt_latency_ms": 0.0,
71+
"decrypt_latency_ms": 0.0,
72+
"end_to_end_latency_ms": 3.4039084,
73+
"ops_per_second": 575.1588876427113,
74+
"bytes_per_second": 58896270.09461364,
75+
"peak_memory_mb": 0.0,
76+
"memory_efficiency_ratio": 0.0,
77+
"p50_latency": 3.3777085,
78+
"p95_latency": 3.7358293500000004,
79+
"p99_latency": 3.7699994700000006,
80+
"timestamp": "2026-01-22 21:23:51",
81+
"rust_version": "unknown",
82+
"cpu_count": 14,
83+
"total_memory_gb": 48.0,
84+
"alloc": {
85+
"count_k": 150,
86+
"total_m": 29,
87+
"max_bytes_m": 1,
88+
"net_count": 5,
89+
"net_total": 0
90+
}
91+
}
92+
]
93+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Cargo.lock
2+
target
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
[package]
2+
name = "dbesdk-benchmark"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[[bin]]
7+
name = "dbesdk-benchmark"
8+
path = "src/main.rs"
9+
10+
[dependencies]
11+
# AWS SDK and DynamoDB Encryption SDK
12+
aws-db-esdk = { path = "../../../DynamoDbEncryption/runtimes/rust" }
13+
14+
# Async runtime
15+
tokio = { version = "1.47", features = ["full"] }
16+
17+
# Serialization
18+
serde = { version = "1.0", features = ["derive"] }
19+
serde_json = "1.0"
20+
serde_yaml = "0.9"
21+
22+
# CLI and progress
23+
clap = { version = "4.5", features = ["derive"] }
24+
indicatif = "0.18"
25+
26+
# Statistics and benchmarking
27+
hdrhistogram = "7.5"
28+
rand = "0.9"
29+
30+
# System info
31+
sysinfo = "0.37"
32+
33+
# Error handling
34+
anyhow = "1.0"
35+
thiserror = "2.0"
36+
37+
# Logging
38+
log = "0.4"
39+
env_logger = "0.11"
40+
41+
# Time
42+
chrono = { version = "0.4", features = ["serde"] }
43+
44+
# Memory profiling
45+
memory-stats = "1.2"
46+
stats_alloc = "0.1"
47+
48+
# Async utilities
49+
futures = "0.3"
50+
51+
aws-config = "1.8.6"
52+
aws-sdk-dynamodb = "1.92.0"
53+
aws-sdk-kms = "1.86.0"
54+
aws-sdk-sso = "1.83.0"
55+
aws-sdk-ssooidc = "1.84.0"
56+
aws-sdk-sts = "1.85.0"
57+
aws-smithy-types = "1.3"
58+
cpu-time = "1.0.0"
59+
60+
[dev-dependencies]
61+
criterion = { version = "0.7", features = ["html_reports"] }
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# AWS Database Encryption SDK for DynamoDB - Rust Performance Benchmarks
2+
3+
This directory contains comprehensive performance benchmarks for the AWS Database Encryption SDK for DynamoDB Rust implementation. The benchmarks measure throughput, memory usage, and concurrency performance across various data sizes and system configurations.
4+
5+
## Features
6+
7+
- **Throughput Benchmarks**: Measure encryption/decryption operations per second
8+
- **Memory Benchmarks**: Track peak memory usage and efficiency ratios
9+
- **Concurrency Benchmarks**: Test performance under different thread counts
10+
- **Raw AES Keyring**: Local 256-bit AES keys (no KMS dependency)
11+
12+
## Prerequisites
13+
14+
- Rust 1.70+ (recommended: latest stable)
15+
- Access to the AWS Database Encryption SDK for DynamoDB Rust runtime
16+
17+
## Quick Start
18+
19+
```bash
20+
# If necessary, build the ESDK and return here
21+
cd ../../../DynamoDbEncryption/
22+
make polymorph_rust transpile_rust
23+
cd ../db-esdk-performance-testing/benchmarks/rust/
24+
25+
# Build and run
26+
cargo run --release -- --config ../../config/test-scenarios.yaml
27+
28+
# Quick test (requires quick_config in YAML)
29+
cargo run --release -- --quick
30+
```
31+
32+
## Configuration
33+
34+
### Command Line
35+
36+
- `--config`: Path to YAML config file (required)
37+
- `--output`: Results output path (default: `../../results/raw-data/rust_results.json`)
38+
- `--quick`: Quick test mode (requires `quick_config` section in YAML)
39+
40+
## Logging
41+
42+
Default: info level. Override with `RUST_LOG`:
43+
44+
```bash
45+
RUST_LOG=debug ./target/release/db_esdk_benchmark --config config.yaml
46+
```
47+
48+
## Development
49+
50+
```bash
51+
# Format and lint
52+
cargo fmt
53+
cargo clippy -- -D warnings
54+
55+
# Test
56+
cargo test
57+
58+
# Debug build
59+
cargo build
60+
RUST_LOG=debug ./target/debug/esdk_benchmark --config config.yaml
61+
```
62+
63+
## Troubleshooting
64+
65+
- **Build issues**: `rustup update && cargo clean && cargo build --release`
66+
- **Config issues**: Validate YAML syntax and check file permissions
67+
- **Memory issues**: Monitor with `htop` or Activity Monitor
68+
69+
## License
70+
71+
Apache License 2.0

0 commit comments

Comments
 (0)