Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 18 additions & 16 deletions esdk-performance-testing/benchmarks/rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,60 +1,62 @@
[package]
name = "esdk-benchmark"
version = "0.1.0"
edition = "2021"
edition = "2024"

[[bin]]
name = "esdk_benchmark"
path = "src/main.rs"

[dependencies]
# AWS Encryption SDK
# aws-esdk = { path = "/Users/ajewell/esdk_rust/esdk" }
aws-esdk = { path = "../../../AwsEncryptionSDK/runtimes/rust" }

# Async runtime
tokio = { version = "1.0", features = ["full"] }
tokio = { version = "1.47", features = ["full"] }

# Serialization
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_yaml = "0.9"

# CLI and progress
clap = { version = "4.0", features = ["derive"] }
indicatif = "0.17"
clap = { version = "4.5", features = ["derive"] }
indicatif = "0.18"

# Statistics and benchmarking
hdrhistogram = "7.5"
rand = "0.8"
rand = "0.9"

# System info
sysinfo = "0.30"
sysinfo = "0.37"

# Error handling
anyhow = "1.0"
thiserror = "1.0"
thiserror = "2.0"

# Logging
log = "0.4"
env_logger = "0.10"
env_logger = "0.11"

# Time
chrono = { version = "0.4", features = ["serde"] }

# Memory profiling
memory-stats = "1.0"
memory-stats = "1.2"
stats_alloc = "0.1"

# Async utilities
futures = "0.3"

aws-config = "1.8.6"
aws-sdk-dynamodb = "1.73.0"
aws-sdk-kms = "1.67.0"
aws-sdk-sso = "1.69.0"
aws-sdk-ssooidc = "1.69.0"
aws-sdk-sts = "1.69.0"
aws-smithy-types = "1.2"
aws-sdk-dynamodb = "1.92.0"
aws-sdk-kms = "1.86.0"
aws-sdk-sso = "1.83.0"
aws-sdk-ssooidc = "1.84.0"
aws-sdk-sts = "1.85.0"
aws-smithy-types = "1.3"
cpu-time = "1.0.0"

[dev-dependencies]
criterion = { version = "0.5", features = ["html_reports"] }
criterion = { version = "0.7", features = ["html_reports"] }
12 changes: 8 additions & 4 deletions esdk-performance-testing/benchmarks/rust/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,22 @@ Rust implementation of the AWS Encryption SDK performance benchmark suite.

## Prerequisites

- Rust 1.85.0+ ([rustup.rs](https://rustup.rs/))
- Rust 1.86.0+ ([rustup.rs](https://rustup.rs/))
- Build tools (Xcode CLI Tools on macOS, build-essential on Linux)

## Quick Start

```bash
# If necessary, build the ESDK and return here
cd ../../../AwsEncryptionSDK/
make polymorph_rust transpile_rust
cd ../esdk-performance-testing/benchmarks/rust/

# Build and run
cargo build --release
./target/release/esdk_benchmark --config ../../config/test-scenarios.yaml
cargo run --release -- --config ../../config/test-scenarios.yaml

# Quick test (requires quick_config in YAML)
./target/release/esdk_benchmark --quick
cargo run --release -- --quick
```

## Configuration
Expand Down
112 changes: 112 additions & 0 deletions esdk-performance-testing/benchmarks/rust/src/alloc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#![allow(dead_code)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand this correctly, should we clean up the dead code and remove this?

use serde::Serialize;
use std::sync::atomic::AtomicIsize;
use std::sync::atomic::Ordering;

pub struct ResourceTracker {
pub count: isize,
pub total: isize,
pub net_total: isize,
pub net_count: isize,
}

#[derive(Debug, Default, Clone, Serialize)]
pub struct ResourceResults {
pub count_k: isize,
pub total_m: isize,
pub max_bytes_m: isize,
pub net_count: isize,
pub net_total: isize,
}

impl ResourceTracker {
pub fn new() -> Self {
Self {
count: get_counter(),
total: get_total(),
net_total: get_net_total(),
net_count: get_net_counter(),
}
}
pub fn report_leak(&self) {
println!(
"{} outstanding allocations totalling {} bytes.",
get_net_counter(),
get_net_total()
);
}
pub fn get_results(&self) -> ResourceResults {
ResourceResults {
count_k: (get_counter() - self.count) / 1000,
total_m: (get_total() - self.total) / 1_000_000,
max_bytes_m: (get_max_total() - self.net_total) / 1_000_000,
net_count: get_net_counter() - self.net_count,
net_total: (get_net_total() - self.net_total) / 1_000_000,
}
}
}

static COUNTER: AtomicIsize = AtomicIsize::new(0);
static TOTAL: AtomicIsize = AtomicIsize::new(0);

static NET_COUNTER: AtomicIsize = AtomicIsize::new(0);
static NET_TOTAL: AtomicIsize = AtomicIsize::new(0);
static MAX_NET_TOTAL: AtomicIsize = AtomicIsize::new(0);
Comment on lines 51 to 60
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we document these fields?


fn add_to_counter(inc: isize) {
COUNTER.fetch_add(1, Ordering::SeqCst);
TOTAL.fetch_add(inc, Ordering::SeqCst);
NET_COUNTER.fetch_add(1, Ordering::SeqCst);
NET_TOTAL.fetch_add(inc, Ordering::SeqCst);
MAX_NET_TOTAL.fetch_max(NET_TOTAL.load(Ordering::SeqCst), Ordering::SeqCst);
}

fn subtract_from_counter(inc: isize) {
NET_COUNTER.fetch_sub(1, Ordering::SeqCst);
NET_TOTAL.fetch_sub(inc, Ordering::SeqCst);
}

fn get_counter() -> isize {
COUNTER.load(Ordering::SeqCst)
}

fn get_total() -> isize {
TOTAL.load(Ordering::SeqCst)
}

fn get_net_counter() -> isize {
NET_COUNTER.load(Ordering::SeqCst)
}

fn get_net_total() -> isize {
NET_TOTAL.load(Ordering::SeqCst)
}

fn clear_max() {
MAX_NET_TOTAL.store(0, Ordering::SeqCst)
}

fn get_max_total() -> isize {
MAX_NET_TOTAL.load(Ordering::SeqCst)
}

use std::alloc::{GlobalAlloc, Layout, System};

struct MyAllocator;

unsafe impl GlobalAlloc for MyAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
add_to_counter(layout.size() as isize);
unsafe { System.alloc(layout) }
}

unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
subtract_from_counter(layout.size() as isize);
unsafe { System.dealloc(ptr, layout) }
}
}

#[global_allocator]
static GLOBAL: MyAllocator = MyAllocator;
6 changes: 3 additions & 3 deletions esdk-performance-testing/benchmarks/rust/src/benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
use anyhow::{Context, Result};
use aws_esdk::client as esdk_client;
use aws_esdk::material_providers::client as mpl_client;
use aws_esdk::material_providers::types::material_providers_config::MaterialProvidersConfig;
use aws_esdk::material_providers::types::AesWrappingAlg;
use aws_esdk::material_providers::types::EsdkCommitmentPolicy;
use aws_esdk::material_providers::types::material_providers_config::MaterialProvidersConfig;
use aws_esdk::types::aws_encryption_sdk_config::AwsEncryptionSdkConfig;
use log::info;
use rand::Rng;
use sysinfo::System;

use crate::config::{load_config, TestConfig};
use crate::config::{TestConfig, load_config};
use crate::results::BenchmarkResult;

// Constants for memory testing
Expand Down Expand Up @@ -72,7 +72,7 @@ impl EsdkBenchmark {

// Create default AES-256 keyring
let mut key = [0u8; 32]; // 256-bit key
rand::thread_rng().fill(&mut key);
rand::rng().fill(&mut key);

let raw_keyring = mpl_client
.create_raw_aes_keyring()
Expand Down
16 changes: 9 additions & 7 deletions esdk-performance-testing/benchmarks/rust/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

#![allow(clippy::collapsible_if)]

mod alloc;
mod benchmark;
mod config;
mod results;
Expand All @@ -18,10 +21,8 @@ fn main() -> Result<()> {
.thread_stack_size(8 * 1024 * 1024) // 8MB stack size
.enable_all()
.build()?;

rt.block_on(async {
run_benchmark().await
})

rt.block_on(async { run_benchmark().await })
}

async fn run_benchmark() -> Result<()> {
Expand Down Expand Up @@ -63,9 +64,10 @@ async fn run_benchmark() -> Result<()> {

// Adjust config for quick test
if quick {
let quick_config = bench.config.quick_config.as_ref()
.ok_or_else(|| anyhow::anyhow!("Quick mode requested but no quick_config found in config file"))?;

let quick_config = bench.config.quick_config.as_ref().ok_or_else(|| {
anyhow::anyhow!("Quick mode requested but no quick_config found in config file")
})?;

bench.config.iterations.measurement = quick_config.iterations.measurement;
bench.config.iterations.warmup = quick_config.iterations.warmup;
bench.config.data_sizes.small = quick_config.data_sizes.small.clone();
Expand Down
2 changes: 2 additions & 0 deletions esdk-performance-testing/benchmarks/rust/src/results.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::alloc;
use anyhow::Result;
use chrono::Utc;
use serde::Serialize;
Expand Down Expand Up @@ -28,6 +29,7 @@ pub struct BenchmarkResult {
pub rust_version: String,
pub cpu_count: usize,
pub total_memory_gb: f64,
pub alloc: alloc::ResourceResults,
}

#[derive(Debug, Serialize)]
Expand Down
Loading
Loading