Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 5 additions & 0 deletions esdk-performance-testing/benchmarks/javascript/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules/
browser/dist/bundle.js
browser/dist/index.html
*.log
*.tgz
142 changes: 142 additions & 0 deletions esdk-performance-testing/benchmarks/javascript/benchmark.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

"use strict";

const os = require("os");
const crypto = require("crypto");
const { getDataSizes, shouldRunTestType } = require("./config");
const { log_msg } = require("./log");
const {
runThroughputTest,
runMemoryTest,
runConcurrentTest,
} = require("./tests");

const DEFAULT_ITERATIONS_PER_WORKER = 5;

/** Node.js platform adapter for the shared test harness. */
const nodePlatform = {
generateTestData(size) {
return new Uint8Array(crypto.randomBytes(size));
},
nowMs() {
return Number(process.hrtime.bigint()) / 1e6;
},
log: log_msg,
getMemoryUsage() {
const m = process.memoryUsage();
return { heapUsed: m.heapUsed, heapTotal: m.heapTotal };
},
triggerGC() {
if (global.gc) global.gc();
},
};

/**
* Orchestrate all benchmark tests based on config.
*/
async function runAllBenchmarks(config, isQuickMode, esdk, resultFactories) {
const keyring = await esdk.createKeyring();
log_msg("ESDK client initialized successfully");
log_msg(
`Initialized ESDK Benchmark - CPU cores: ${os.cpus().length}, Memory: ${(os.totalmem() / 1024 ** 3).toFixed(1)}GB`,
);
log_msg("Starting comprehensive ESDK benchmark suite");

const dataSizes = getDataSizes(config);
const iterations = (config.iterations && config.iterations.measurement) || 10;
const warmup = (config.iterations && config.iterations.warmup) || 5;
const concurrencyLevels = config.concurrency_levels || [1, 2, 4];
const iterationsPerWorker = DEFAULT_ITERATIONS_PER_WORKER;
const results = [];

const { createThroughputResult, createMemoryResult, createConcurrentResult } =
resultFactories;

// Throughput tests
if (shouldRunTestType(config, "throughput", isQuickMode)) {
log_msg("Running throughput tests...");
for (const dataSize of dataSizes) {
try {
const result = await runThroughputTest(
keyring,
dataSize,
iterations,
warmup,
esdk.runEncryptDecryptCycle,
createThroughputResult,
nodePlatform,
);
results.push(result);
log_msg(
`Throughput test completed: ${result.ops_per_second.toFixed(2)} ops/sec`,
);
} catch (err) {
log_msg(`Throughput test failed: ${err.message}`);
}
}
} else {
log_msg("Skipping throughput tests (not in test_types)");
}

// Memory tests
if (shouldRunTestType(config, "memory", isQuickMode)) {
log_msg("Running memory tests...");
for (const dataSize of dataSizes) {
try {
const result = await runMemoryTest(
keyring,
dataSize,
esdk.runEncryptDecryptCycle,
createMemoryResult,
nodePlatform,
);
results.push(result);
log_msg(
`Memory test completed: ${result.peak_memory_mb.toFixed(2)} MB peak`,
);
} catch (err) {
log_msg(`Memory test failed: ${err.message}`);
}
}
} else {
log_msg("Skipping memory tests (not in test_types)");
}

// Concurrency tests
if (shouldRunTestType(config, "concurrency", isQuickMode)) {
log_msg("Running concurrency tests...");
for (const dataSize of dataSizes) {
for (const concurrency of concurrencyLevels) {
if (concurrency <= 1) continue;
try {
const result = await runConcurrentTest(
keyring,
dataSize,
concurrency,
iterationsPerWorker,
esdk.runEncryptDecryptCycle,
createConcurrentResult,
nodePlatform,
);
results.push(result);
log_msg(
`Concurrent test completed: ${result.ops_per_second.toFixed(2)} ops/sec @ ${concurrency} workers`,
);
} catch (err) {
log_msg(`Concurrent test failed: ${err.message}`);
}
}
}
} else {
log_msg("Skipping concurrency tests (not in test_types)");
}

log_msg(`Benchmark suite completed. Total results: ${results.length}`);
return results;
}

module.exports = {
runAllBenchmarks,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# AWS Encryption SDK Browser JavaScript Benchmark

Performance testing suite for the AWS Encryption SDK Browser JavaScript implementation (`@aws-crypto/client-browser`).

## Overview

This benchmark uses the browser variant of the AWS Encryption SDK, which relies on WebCrypto APIs (`RawAesKeyringWebCrypto`). The launcher bundles the benchmark with esbuild, serves it locally, and runs it in headless Chrome via Puppeteer to collect results.

## Quick Start

```bash
# Install dependencies
npm install

# Run benchmark (bundles with esbuild, launches headless Chrome via Puppeteer)
node src/launcher.js

# Quick test (reduced iterations)
node src/launcher.js --quick
```

## Options

- `--config <path>` - Path to test configuration file (default: `../../../config/test-scenarios.yaml`)
- `--output <path>` - Path to output results file (default: `../../../results/raw-data/browser_js_results.json`)
- `--quick` - Run with reduced iterations for faster testing

## Configuration

Edit `../../config/test-scenarios.yaml` for test parameters:

- Data sizes (small/medium/large)
- Iterations and concurrency levels

## Test Types

- **Throughput** - Measures encryption/decryption operations per second with latency percentiles
- **Memory** - Tracks heap memory usage during operations via Chrome's `performance.memory` API
- **Concurrency** - Tests performance under concurrent load using async workers via `Promise.all`

## Key Differences from Node.js Benchmark

- Uses `@aws-crypto/client-browser` instead of `@aws-crypto/client-node`
- Uses `RawAesKeyringWebCrypto` instead of `RawAesKeyringNode`
- Keyring creation is async (`importCryptoKey` returns a Promise)
- Encrypt/decrypt operates on `Uint8Array` instead of `Buffer`
- Reuses the shared test harness (`tests.js`, `result-base.js`, `utils.js`) via a browser-specific platform adapter

## Output

Results saved as JSON to `../../results/raw-data/browser_js_results.json` with:

- Performance metrics (ops/sec, latency percentiles)
- Memory usage (peak heap, efficiency ratio)
- System information (CPU, memory, Node.js version)
Loading
Loading