From 3aab230e43179eaae988580fd6423fac590cec05 Mon Sep 17 00:00:00 2001 From: Shubham Chaturvedi Date: Fri, 5 Sep 2025 00:04:44 -0700 Subject: [PATCH 1/3] PerfTests: java --- .../benchmarks/java/README.md | 216 +++++++++ .../benchmarks/java/pom.xml | 254 +++++++++++ .../amazon/esdk/benchmark/ESDKBenchmark.java | 243 ++++++++++ .../com/amazon/esdk/benchmark/Program.java | 122 +++++ .../java/com/amazon/esdk/benchmark/Tests.java | 422 ++++++++++++++++++ .../benchmark/model/BenchmarkMetadata.java | 24 + .../amazon/esdk/benchmark/model/Config.java | 93 ++++ .../amazon/esdk/benchmark/model/Report.java | 57 +++ .../esdk/benchmark/model/TestResult.java | 199 +++++++++ 9 files changed, 1630 insertions(+) create mode 100644 esdk-performance-testing/benchmarks/java/README.md create mode 100644 esdk-performance-testing/benchmarks/java/pom.xml create mode 100644 esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/ESDKBenchmark.java create mode 100644 esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Program.java create mode 100644 esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Tests.java create mode 100644 esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/BenchmarkMetadata.java create mode 100644 esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/Config.java create mode 100644 esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/Report.java create mode 100644 esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/TestResult.java diff --git a/esdk-performance-testing/benchmarks/java/README.md b/esdk-performance-testing/benchmarks/java/README.md new file mode 100644 index 000000000..9180682c5 --- /dev/null +++ b/esdk-performance-testing/benchmarks/java/README.md @@ -0,0 +1,216 @@ +# ESDK Performance Benchmark - Java + +This directory contains the Java implementation of the AWS Encryption SDK (ESDK) performance benchmark suite. + +## Overview + +The Java benchmark provides comprehensive performance testing for the ESDK Java runtime, measuring: + +- **Throughput**: Operations per second and bytes per second +- **Latency**: Encrypt, decrypt, and end-to-end timing +- **Memory Usage**: Peak memory consumption and efficiency +- **Concurrency**: Multi-threaded performance scaling +- **Statistical Analysis**: P50, P95, P99 latency percentiles + +## Prerequisites + +- Java 11 or higher +- Maven 3.6 or higher +- Access to AWS Encryption SDK Java libraries + +## Building + +```bash +# Build the project +mvn clean compile + +# Create executable JAR +mvn clean package + +# Run tests +mvn test +``` + +## Running Benchmarks + +### Quick Test + +```bash +# Using Maven +mvn exec:java -Dexec.mainClass="com.amazon.esdk.benchmark.ESDKBenchmark" -Dexec.args="--quick" + +# Using JAR +java -jar target/esdk-benchmark.jar --quick +``` + +### Full Benchmark Suite + +```bash +# Using Maven +mvn exec:java -Dexec.mainClass="com.amazon.esdk.benchmark.ESDKBenchmark" + +# Using JAR +java -jar target/esdk-benchmark.jar +``` + +### Custom Configuration + +```bash +# Specify custom config and output paths +java -jar target/esdk-benchmark.jar \ + --config /path/to/config.yaml \ + --output /path/to/results.json +``` + +## Command Line Options + +- `--config, -c`: Path to test configuration file (default: `../../config/test-scenarios.yaml`) +- `--output, -o`: Path to output results file (default: `../../results/raw-data/java_results.json`) +- `--quick, -q`: Run quick test with reduced iterations +- `--help, -h`: Show help message + +## Configuration + +The benchmark uses a YAML configuration file to define test parameters: + +```yaml +data_sizes: + small: [1024, 5120, 10240] + medium: [102400, 512000, 1048576] + large: [10485760, 52428800, 104857600] + +iterations: + warmup: 5 + measurement: 10 + +concurrency_levels: [1, 2, 4, 8] +algorithm_suites: ["ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256"] +frame_lengths: [4096, 65536, 1048576] +``` + +## Output Format + +Results are saved in JSON format with the following structure: + +```json +{ + "metadata": { + "language": "java", + "timestamp": "2025-08-27T15:30:00Z", + "javaVersion": "11.0.20", + "cpuCount": 8, + "totalMemoryGB": 16.0, + "totalTests": 45 + }, + "results": [ + { + "testName": "throughput", + "language": "java", + "dataSize": 1024, + "algorithmSuite": "ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256", + "frameLength": 4096, + "concurrency": 1, + "encryptLatencyMs": 0.85, + "decryptLatencyMs": 0.72, + "endToEndLatencyMs": 1.57, + "opsPerSecond": 636.94, + "bytesPerSecond": 652224.0, + "peakMemoryMB": 0.0, + "memoryEfficiencyRatio": 0.0, + "p50Latency": 1.55, + "p95Latency": 1.89, + "p99Latency": 2.12, + "timestamp": "2025-08-27T15:30:15Z", + "javaVersion": "11.0.20", + "cpuCount": 8, + "totalMemoryGB": 16.0 + } + ] +} +``` + +## Performance Tuning + +### JVM Options + +For optimal performance, consider these JVM options: + +```bash +java -Xmx4g -Xms2g \ + -XX:+UseG1GC \ + -XX:MaxGCPauseMillis=200 \ + -XX:+UnlockExperimentalVMOptions \ + -XX:+UseJVMCICompiler \ + -jar target/esdk-benchmark.jar +``` + +### System Configuration + +- Ensure adequate heap memory (recommended: 4GB+) +- Use SSD storage for temporary files +- Disable CPU frequency scaling for consistent results +- Close unnecessary applications during benchmarking + +## Troubleshooting + +### Common Issues + +1. **OutOfMemoryError**: Increase heap size with `-Xmx` option +2. **Dependency conflicts**: Run `mvn dependency:tree` to check for conflicts +3. **Slow performance**: Ensure JVM warmup and disable background processes + +### Debug Mode + +Enable debug logging: + +```bash +java -Dorg.slf4j.simpleLogger.defaultLogLevel=debug \ + -jar target/esdk-benchmark.jar +``` + +## Integration + +### CI/CD Pipeline + +Example GitHub Actions workflow: + +```yaml +- name: Run Java Benchmarks + run: | + cd aws-encryption-sdk/esdk-performance-testing/benchmarks/java + mvn clean package + java -jar target/esdk-benchmark.jar --quick +``` + +### Automated Analysis + +The benchmark integrates with the overall performance testing suite. Results can be: + +- Compared across language implementations +- Tracked over time for regression detection +- Analyzed for performance optimization opportunities + +## Contributing + +When modifying the Java benchmark: + +1. Follow Java coding standards +2. Add appropriate unit tests +3. Update documentation for new features +4. Ensure compatibility with existing configuration format +5. Test with both quick and full benchmark modes + +## Dependencies + +Key dependencies used in this benchmark: + +- **AWS Encryption SDK**: Core encryption/decryption functionality +- **Jackson**: JSON/YAML processing +- **Commons CLI**: Command line argument parsing +- **ProgressBar**: Visual progress indication +- **SLF4J**: Logging framework +- **JUnit**: Unit testing (test scope) + +## License + +This benchmark suite is part of the AWS Encryption SDK project and follows the same licensing terms. diff --git a/esdk-performance-testing/benchmarks/java/pom.xml b/esdk-performance-testing/benchmarks/java/pom.xml new file mode 100644 index 000000000..2cdf71224 --- /dev/null +++ b/esdk-performance-testing/benchmarks/java/pom.xml @@ -0,0 +1,254 @@ + + + 4.0.0 + + com.amazon.esdk + esdk-performance-benchmark + 1.0.0 + jar + + ESDK Performance Benchmark - Java + Performance benchmarking suite for AWS Encryption SDK Java runtime + + + 17 + 17 + UTF-8 + + + 3.0.2 + 2.15.2 + 0.9.5 + 1.5.0 + 2.0.7 + 1.4.8 + 5.10.0 + + + + + + + software.amazon.awssdk + bom + 2.25.1 + pom + import + + + + + + + + com.amazonaws + aws-encryption-sdk-java + 3.0.2 + + + + + software.amazon.cryptography + aws-cryptographic-material-providers + 1.0.2 + + + + + + software.amazon.awssdk + kms + + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + ${jackson.version} + + + + + me.tongfei + progressbar + ${progressbar.version} + + + + + commons-cli + commons-cli + ${commons.cli.version} + + + + + org.slf4j + slf4j-api + ${slf4j.version} + + + + + ch.qos.logback + logback-classic + ${logback.version} + + + + + org.junit.jupiter + junit-jupiter-engine + ${junit.version} + test + + + org.junit.jupiter + junit-jupiter-api + ${junit.version} + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + 17 + 17 + UTF-8 + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.1.2 + + + **/*Test.java + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.0 + + + package + + shade + + + + + com.amazon.esdk.benchmark.Program + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + com.amazon.esdk.benchmark.Program + + + + + + + + + + org.apache.maven.plugins + maven-clean-plugin + 3.3.1 + + + + + org.apache.maven.plugins + maven-resources-plugin + 3.3.1 + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + + + org.apache.maven.plugins + maven-install-plugin + 3.1.1 + + + + + org.apache.maven.plugins + maven-deploy-plugin + 3.1.1 + + + + + com.diffplug.spotless + spotless-maven-plugin + 2.40.0 + + + + 1.17.0 + + + + + + + + + + + + + + central + Maven Central Repository + https://repo1.maven.org/maven2 + + + diff --git a/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/ESDKBenchmark.java b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/ESDKBenchmark.java new file mode 100644 index 000000000..b2951290f --- /dev/null +++ b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/ESDKBenchmark.java @@ -0,0 +1,243 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.amazon.esdk.benchmark; + +import com.amazon.esdk.benchmark.model.Config; +import com.amazon.esdk.benchmark.model.TestResult; +import com.amazonaws.encryptionsdk.AwsCrypto; +import com.amazonaws.encryptionsdk.CryptoResult; +import java.nio.ByteBuffer; +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import me.tongfei.progressbar.ProgressBar; +import software.amazon.cryptography.materialproviders.IKeyring; +import software.amazon.cryptography.materialproviders.MaterialProviders; +import software.amazon.cryptography.materialproviders.model.AesWrappingAlg; +import software.amazon.cryptography.materialproviders.model.CreateRawAesKeyringInput; +import software.amazon.cryptography.materialproviders.model.MaterialProvidersConfig; + +/** + * ESDK Performance Benchmark Suite - Java Implementation + * + *

This class provides comprehensive performance testing for the AWS Encryption SDK (ESDK) Java + * runtime, measuring throughput, latency, memory usage, and scalability. + */ +public final class ESDKBenchmark { + + final Config config; + final AwsCrypto crypto; + final IKeyring keyring; + // System information + final int cpuCount; + final long totalMemoryMB; + + public ESDKBenchmark(final String configPath) throws Exception { + this.config = Config.loadConfig(configPath); + + // System info + this.cpuCount = Runtime.getRuntime().availableProcessors(); + this.totalMemoryMB = Runtime.getRuntime().maxMemory() / (1024 * 1024); + + // Initialize AWS Crypto + this.crypto = AwsCrypto.standard(); + + // Generate a 256-bit AES key for testing + final KeyGenerator aesGen = KeyGenerator.getInstance("AES"); + aesGen.init(256, new SecureRandom()); + final SecretKey encryptionKey = aesGen.generateKey(); + final ByteBuffer keyBytes = ByteBuffer.wrap(encryptionKey.getEncoded()); + + // Create Raw AES keyring using Material Providers + final String keyNamespace = "esdk-performance-test"; + final String keyName = "test-aes-256-key"; + + final CreateRawAesKeyringInput keyringInput = CreateRawAesKeyringInput + .builder() + .keyName(keyName) + .keyNamespace(keyNamespace) + .wrappingKey(keyBytes) + .wrappingAlg(AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16) + .build(); + + final MaterialProviders matProv = MaterialProviders + .builder() + .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) + .build(); + + this.keyring = matProv.CreateRawAesKeyring(keyringInput); + + System.out.println( + "Initialized ESDK Benchmark - CPU cores: " + + cpuCount + + ", Memory: " + + (totalMemoryMB / 1024.0) + + "GB" + ); + } + + /** + * Run a single encrypt-decrypt cycle and measure performance + */ + public EncryptDecryptResult runEncryptDecryptCycle(final byte[] data) { + final var encryptionContext = Collections.singletonMap( + "purpose", + "performance-test" + ); + + // Measure encryption + final long encryptStart = System.nanoTime(); + final CryptoResult encryptResult = crypto.encryptData( + keyring, + data, + encryptionContext + ); + final long encryptTime = System.nanoTime() - encryptStart; + + final byte[] ciphertext = encryptResult.getResult(); + + // Measure decryption + final long decryptStart = System.nanoTime(); + final CryptoResult decryptResult = crypto.decryptData( + keyring, + ciphertext + ); + final long decryptTime = System.nanoTime() - decryptStart; + + final byte[] decryptedData = decryptResult.getResult(); + + // Verify data integrity + if (!Arrays.equals(data, decryptedData)) { + throw new RuntimeException("Decrypted data does not match original data"); + } + + return new EncryptDecryptResult( + encryptTime / 1_000_000.0, // Convert to milliseconds + decryptTime / 1_000_000.0, + ciphertext.length + ); + } + + public List runAllBenchmarks() { + System.out.println("Starting comprehensive ESDK benchmark suite"); + final List allResults = new ArrayList<>(); + + // Get test parameters from config + final List dataSizes = new ArrayList<>(); + if (config.dataSizes.small != null) dataSizes.addAll( + config.dataSizes.small + ); + if (config.dataSizes.medium != null) dataSizes.addAll( + config.dataSizes.medium + ); + if (config.dataSizes.large != null) dataSizes.addAll( + config.dataSizes.large + ); + + // Calculate actual total tests + final int throughputTests = dataSizes.size(); + final int memoryTests = dataSizes.size(); + final int concurrentTests = + dataSizes.size() * + (int) config.concurrencyLevels.stream().filter(c -> c > 1).count(); + final int totalTests = throughputTests + memoryTests + concurrentTests; + + System.out.println("Running " + totalTests + " total tests"); + + try ( + final ProgressBar pb = new ProgressBar("Running benchmarks", totalTests) + ) { + // Throughput tests + for (final int dataSize : dataSizes) { + try { + final TestResult result = Tests.runThroughputTest( + this, + dataSize, + config.iterations.measurement + ); + if (result != null) { + allResults.add(result); + System.out.println( + "Throughput test completed: " + + String.format("%.2f", result.opsPerSecond) + + " ops/sec" + ); + System.out.flush(); + System.out.println( + "Throughput test completed - Ops/sec: " + + String.format("%.2f", result.opsPerSecond) + + ", MB/sec: " + + String.format("%.2f", result.bytesPerSecond / (1024 * 1024)) + ); + } + } catch (final Exception e) { + System.err.println("Throughput test failed: " + e.getMessage()); + } + pb.step(); + System.out.flush(); + } + + // Memory tests + for (final int dataSize : dataSizes) { + try { + final TestResult result = Tests.runMemoryTest(this, dataSize); + allResults.add(result); + System.out.println( + "Memory test completed: " + + String.format("%.2f", result.peakMemoryMb) + + " MB peak" + ); + System.out.flush(); + } catch (final Exception e) { + System.err.println("Memory test failed: " + e.getMessage()); + } + pb.step(); + System.out.flush(); + } + + // Concurrent tests + for (final int dataSize : dataSizes) { + for (final int concurrency : config.concurrencyLevels) { + if (concurrency > 1) { // Skip single-threaded for concurrent tests + try { + final TestResult result = Tests.runConcurrentTest( + this, + dataSize, + concurrency, + 5 + ); + allResults.add(result); + System.out.println( + "Concurrent test completed: " + + String.format("%.2f", result.opsPerSecond) + + " ops/sec @ " + + concurrency + + " threads" + ); + } catch (final Exception e) { + System.err.println("Concurrent test failed: " + e.getMessage()); + } + pb.step(); + System.out.flush(); + } + } + } + } + + System.out.println( + "Benchmark suite completed. Total results: " + allResults.size() + ); + return allResults; + } + + public record EncryptDecryptResult( + double encryptTimeMs, + double decryptTimeMs, + int ciphertextSize + ) {} +} diff --git a/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Program.java b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Program.java new file mode 100644 index 000000000..6213cbd0a --- /dev/null +++ b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Program.java @@ -0,0 +1,122 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.amazon.esdk.benchmark; + +import com.amazon.esdk.benchmark.model.Report; +import com.amazon.esdk.benchmark.model.TestResult; +import java.util.List; +import java.util.OptionalDouble; + +public final class Program { + + public static void main(final String[] args) { + final CommandLineOptions options = parseArgs(args); + if (options == null) return; + + try { + final ESDKBenchmark benchmark = new ESDKBenchmark(options.configPath); + + if (options.quickTest) { + benchmark.config.adjustForQuickTest(); + } + + final List results = benchmark.runAllBenchmarks(); + Report.saveResults( + results, + options.outputPath, + benchmark.cpuCount, + benchmark.totalMemoryMB + ); + printSummary(results, options.outputPath); + } catch (final Exception ex) { + System.out.println("Benchmark failed: " + ex.getMessage()); + } + } + + private static CommandLineOptions parseArgs(final String[] args) { + // Default options + final CommandLineOptions options = new CommandLineOptions(); + options.configPath = "../../config/test-scenarios.yaml"; + options.outputPath = "../../results/raw-data/java_results.json"; + options.quickTest = false; + + // Simple argument parsing + for (int i = 0; i < args.length; i++) { + switch (args[i]) { + case "--config": + case "-c": + if (i + 1 < args.length) options.configPath = args[++i]; + break; + case "--output": + case "-o": + if (i + 1 < args.length) options.outputPath = args[++i]; + break; + case "--quick": + case "-q": + options.quickTest = true; + break; + case "--help": + case "-h": + printUsage(); + return null; + } + } + + return options; + } + + private static void printUsage() { + System.out.println("ESDK Java Performance Benchmark"); + System.out.println("Usage: java -jar esdk-benchmark.jar [options]"); + System.out.println("Options:"); + System.out.println( + " --config, -c Path to test configuration file (default: ../../config/test-scenarios.yaml)" + ); + System.out.println( + " --output, -o Path to output results file (default: ../../results/raw-data/java_results.json)" + ); + System.out.println( + " --quick, -q Run quick test with reduced iterations" + ); + System.out.println(" --help, -h Show this help message"); + } + + private static void printSummary( + final List results, + final String outputPath + ) { + System.out.println("\n=== ESDK Java Benchmark Summary ==="); + System.out.println("Total tests completed: " + results.size()); + System.out.println("Results saved to: " + outputPath); + + // Print some basic statistics + if (!results.isEmpty()) { + final OptionalDouble avgOps = results + .stream() + .filter(r -> "throughput".equals(r.testName)) + .mapToDouble(r -> r.opsPerSecond) + .average(); + final OptionalDouble maxOps = results + .stream() + .filter(r -> "throughput".equals(r.testName)) + .mapToDouble(r -> r.opsPerSecond) + .max(); + + if (avgOps.isPresent() && maxOps.isPresent()) { + System.out.printf( + "Throughput - Avg: %.2f ops/sec, Max: %.2f ops/sec%n", + avgOps.getAsDouble(), + maxOps.getAsDouble() + ); + } + } + } + + public static final class CommandLineOptions { + + public String configPath; + public String outputPath; + public boolean quickTest; + } +} diff --git a/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Tests.java b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Tests.java new file mode 100644 index 000000000..d84b86583 --- /dev/null +++ b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Tests.java @@ -0,0 +1,422 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.amazon.esdk.benchmark; + +import com.amazon.esdk.benchmark.model.TestResult; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import me.tongfei.progressbar.ProgressBar; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class Tests { + + private static final Logger logger = LoggerFactory.getLogger(Tests.class); + + // Constants for memory testing + private static final int MemoryTestIterations = 5; + private static final int SamplingIntervalMs = 1; + private static final int GcSettleTimeMs = 5; + private static final int FinalSampleWaitMs = 2; + + /** + * Run throughput benchmark test + */ + public static TestResult runThroughputTest( + final ESDKBenchmark benchmark, + final int dataSize, + final int iterations + ) { + System.out.println( + "Running throughput test - Size: " + + dataSize + + " bytes, Iterations: " + + iterations + ); + System.out.flush(); + + final byte[] data = new byte[dataSize]; + new java.security.SecureRandom().nextBytes(data); + + // Warmup + runWarmupIterations(benchmark, data, benchmark.config.iterations.warmup); + + // Measurement runs + final var results = runMeasurementIterations(benchmark, data, iterations); + final var encryptLatencies = results.encryptLatencies; + final var decryptLatencies = results.decryptLatencies; + final var totalLatencies = results.totalLatencies; + + if (encryptLatencies.isEmpty()) { + System.out.println("All test iterations failed"); + return null; + } + + return TestResult.createThroughputResult( + encryptLatencies, + decryptLatencies, + totalLatencies, + dataSize, + benchmark.cpuCount, + benchmark.totalMemoryMB + ); + } + + private static long getTotalAllocatedBytes() { + try { + final var memoryBean = + java.lang.management.ManagementFactory.getMemoryMXBean(); + final var heapUsage = memoryBean.getHeapMemoryUsage(); + final var nonHeapUsage = memoryBean.getNonHeapMemoryUsage(); + return heapUsage.getUsed() + nonHeapUsage.getUsed(); + } catch (final Exception e) { + final Runtime runtime = Runtime.getRuntime(); + return runtime.totalMemory() - runtime.freeMemory(); + } + } + + private static void runWarmupIterations( + final ESDKBenchmark benchmark, + final byte[] data, + final int warmupCount + ) { + for (int i = 0; i < warmupCount; i++) { + try { + benchmark.runEncryptDecryptCycle(data); + } catch (final Exception e) { + System.out.println( + "Warmup iteration " + i + " failed: " + e.getMessage() + ); + } + } + } + + private static MeasurementResults runMeasurementIterations( + final ESDKBenchmark benchmark, + final byte[] data, + final int iterations + ) { + final var encryptLatencies = new ArrayList(); + final var decryptLatencies = new ArrayList(); + final var totalLatencies = new ArrayList(); + + for (int i = 0; i < iterations; i++) { + try { + final long iterationStart = System.nanoTime(); + final var result = benchmark.runEncryptDecryptCycle(data); + final double totalMs = + (System.nanoTime() - iterationStart) / 1_000_000.0; + + encryptLatencies.add(result.encryptTimeMs()); + decryptLatencies.add(result.decryptTimeMs()); + totalLatencies.add(totalMs); + } catch (final Exception e) { + System.out.println("Iteration " + i + " failed: " + e.getMessage()); + } + } + + return new MeasurementResults( + encryptLatencies, + decryptLatencies, + totalLatencies + ); + } + + /** + * Run memory usage benchmark test + */ + public static TestResult runMemoryTest( + final ESDKBenchmark benchmark, + final int dataSize + ) { + System.out.println( + "Running memory test - Size: " + + dataSize + + " bytes (" + + MemoryTestIterations + + " iterations, continuous sampling)" + ); + System.out.flush(); + + final byte[] data = new byte[dataSize]; + new java.security.SecureRandom().nextBytes(data); + final var memoryResults = sampleMemoryDuringOperations(benchmark, data); + + return TestResult.createMemoryResult( + memoryResults.peakMemoryMb, + memoryResults.avgMemoryMb, + dataSize, + benchmark.cpuCount, + benchmark.totalMemoryMB + ); + } + + private static MemoryResults sampleMemoryDuringOperations( + final ESDKBenchmark benchmark, + final byte[] data + ) { + double peakMemoryDelta = 0.0; + double peakAllocations = 0.0; + final var avgMemoryValues = new ArrayList(); + + for (int i = 0; i < MemoryTestIterations; i++) { + // Force GC and settle + System.gc(); + System.gc(); + try { + Thread.sleep(GcSettleTimeMs); + } catch (final InterruptedException e) {} + + final long baselineMemory = + Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); + final long baselineAllocations = getTotalAllocatedBytes(); + final var memorySamples = new ArrayList(); + + // Sample memory during operation + final long operationStart = System.nanoTime(); + + // Start background sampling + final var samplingTask = new Thread(() -> { + try { + while (System.nanoTime() - operationStart < 100_000_000) { // 100ms + final long currentMemory = + Runtime.getRuntime().totalMemory() - + Runtime.getRuntime().freeMemory(); + final long currentAllocations = getTotalAllocatedBytes(); + final double heapDelta = + (currentMemory - baselineMemory) / (1024.0 * 1024.0); + final double allocsDelta = + (currentAllocations - baselineAllocations) / (1024.0 * 1024.0); + + if (heapDelta > 0 || allocsDelta > 0) { + synchronized (memorySamples) { + memorySamples.add( + new MemorySample( + Math.max(0, heapDelta), + Math.max(0, allocsDelta) + ) + ); + } + } + Thread.sleep(SamplingIntervalMs); + } + } catch (final InterruptedException e) {} + }); + + samplingTask.start(); + + // Run the actual operation + try { + benchmark.runEncryptDecryptCycle(data); + } catch (final Exception e) { + System.out.println( + "Memory test iteration " + (i + 1) + " failed: " + e.getMessage() + ); + continue; + } + + final double operationDurationMs = + (System.nanoTime() - operationStart) / 1_000_000.0; + + // Wait for sampling to complete + try { + Thread.sleep(FinalSampleWaitMs); + samplingTask.join(100); + } catch (final InterruptedException e) {} + + // Get final measurements + final Runtime runtime = Runtime.getRuntime(); + final long finalMemory = runtime.totalMemory() - runtime.freeMemory(); + final long finalAllocations = getTotalAllocatedBytes(); + final double finalHeapDelta = + (finalMemory - baselineMemory) / (1024.0 * 1024.0); + final double finalAllocsDelta = + (finalAllocations - baselineAllocations) / (1024.0 * 1024.0); + + // Calculate iteration metrics + final double iterPeakMemory; + final double iterTotalAllocs; + final double iterAvgMemory; + + synchronized (memorySamples) { + if (memorySamples.isEmpty()) { + iterPeakMemory = Math.max(0, finalHeapDelta); + iterTotalAllocs = Math.max(0, finalAllocsDelta); + iterAvgMemory = Math.max(0, finalHeapDelta); + } else { + iterPeakMemory = + memorySamples.stream().mapToDouble(s -> s.heapMB).max().orElse(0.0); + iterTotalAllocs = + memorySamples + .stream() + .mapToDouble(s -> s.allocsMB) + .max() + .orElse(0.0); + iterAvgMemory = + memorySamples + .stream() + .mapToDouble(s -> s.heapMB) + .average() + .orElse(0.0); + } + } + + if (iterPeakMemory > peakMemoryDelta) { + peakMemoryDelta = iterPeakMemory; + } + if (iterTotalAllocs > peakAllocations) { + peakAllocations = iterTotalAllocs; + } + + avgMemoryValues.add(iterAvgMemory); + + System.out.println( + "=== Iteration " + + (i + 1) + + " === Peak Heap: " + + String.format("%.2f", iterPeakMemory) + + " MB, Total Allocs: " + + String.format("%.2f", iterTotalAllocs) + + " MB, Avg Heap: " + + String.format("%.2f", iterAvgMemory) + + " MB (" + + String.format("%.0f", operationDurationMs) + + "ms, " + + memorySamples.size() + + " samples)" + ); + System.out.flush(); + } + + final double overallAvgMemory = avgMemoryValues.isEmpty() + ? 0.0 + : avgMemoryValues + .stream() + .mapToDouble(Double::doubleValue) + .average() + .orElse(0.0); + + System.out.println("\nMemory Summary:"); + System.out.println( + "- Absolute Peak Heap: " + + String.format("%.2f", peakMemoryDelta) + + " MB (across all runs)" + ); + System.out.println( + "- Average Heap: " + + String.format("%.2f", overallAvgMemory) + + " MB (across all runs)" + ); + System.out.println( + "- Total Allocations: " + + String.format("%.2f", peakAllocations) + + " MB (max across all runs)" + ); + System.out.flush(); + + return new MemoryResults(peakMemoryDelta, overallAvgMemory); + } + + /** + * Run concurrent operations benchmark test + */ + public static TestResult runConcurrentTest( + final ESDKBenchmark benchmark, + final int dataSize, + final int concurrency, + final int iterationsPerThread + ) { + System.out.println( + "Running concurrent test - Size: " + + dataSize + + " bytes, Concurrency: " + + concurrency + ); + System.out.flush(); + + final byte[] data = new byte[dataSize]; + new java.security.SecureRandom().nextBytes(data); + final List allTimes = Collections.synchronizedList( + new ArrayList<>() + ); + + final ExecutorService executor = Executors.newFixedThreadPool(concurrency); + final List> futures = new ArrayList<>(); + + // Create progress bar for concurrent operations + final int expectedOperations = concurrency * iterationsPerThread; + try ( + final ProgressBar concurrentPb = new ProgressBar( + "Concurrent test", + expectedOperations + ) + ) { + // Submit concurrent tasks + for (int i = 0; i < concurrency; i++) { + final Future future = executor.submit(() -> { + for (int j = 0; j < iterationsPerThread; j++) { + try { + final long threadStartTime = System.nanoTime(); + benchmark.runEncryptDecryptCycle(data); + final double elapsed = + (System.nanoTime() - threadStartTime) / 1_000_000.0; + allTimes.add(elapsed); + + concurrentPb.step(); + System.out.flush(); + } catch (final Exception e) { + System.err.println( + "Concurrent test iteration failed: " + e.getMessage() + ); + } + } + return null; + }); + futures.add(future); + } + + // Wait for all tasks to complete + for (final Future future : futures) { + try { + future.get(); + } catch (final Exception e) { + System.err.println("Concurrent thread failed: " + e.getMessage()); + } + } + } + + executor.shutdown(); + + if (allTimes.isEmpty()) { + throw new RuntimeException("All concurrent operations failed"); + } + + // Calculate metrics + final int totalOperations = allTimes.size(); + + return TestResult.createConcurrentResult( + allTimes, + totalOperations, + dataSize, + concurrency, + benchmark.cpuCount, + benchmark.totalMemoryMB + ); + } + + // Helper classes + private record MeasurementResults( + List encryptLatencies, + List decryptLatencies, + List totalLatencies + ) {} + + private record MemoryResults(double peakMemoryMb, double avgMemoryMb) {} + + private record MemorySample(double heapMB, double allocsMB) {} +} diff --git a/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/BenchmarkMetadata.java b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/BenchmarkMetadata.java new file mode 100644 index 000000000..cd1af5ad1 --- /dev/null +++ b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/BenchmarkMetadata.java @@ -0,0 +1,24 @@ +package com.amazon.esdk.benchmark.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public final class BenchmarkMetadata { + + @JsonProperty("language") + public String language = "java"; + + @JsonProperty("timestamp") + public String timestamp = ""; + + @JsonProperty("java_version") + public String javaVersion = ""; + + @JsonProperty("cpu_count") + public int cpuCount; + + @JsonProperty("total_memory_gb") + public double totalMemoryGb; + + @JsonProperty("total_tests") + public int totalTests; +} diff --git a/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/Config.java b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/Config.java new file mode 100644 index 000000000..3f4564313 --- /dev/null +++ b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/Config.java @@ -0,0 +1,93 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.amazon.esdk.benchmark.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class Config { + + private static final Logger logger = LoggerFactory.getLogger(Config.class); + + @JsonProperty("data_sizes") + public DataSizes dataSizes; + + @JsonProperty("iterations") + public Iterations iterations; + + @JsonProperty("concurrency_levels") + public List concurrencyLevels; + + @JsonProperty("quick_config") + public QuickConfig quickConfig; + + /** + * Load test configuration from YAML file + */ + public static Config loadConfig(String configPath) throws IOException { + ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); + File configFile = new File(configPath); + + if (!configFile.exists()) { + System.err.println("Config file not found, using default configuration"); + throw new FileNotFoundException(configPath); + } + + return mapper.readValue(configFile, Config.class); + } + + /** + * Adjust configuration for quick test + */ + public void adjustForQuickTest() { + this.iterations = quickConfig.iterations; + + this.dataSizes = quickConfig.dataSizes; + + this.concurrencyLevels = quickConfig.concurrencyLevels; + } + + public static final class DataSizes { + + @JsonProperty("small") + public List small; + + @JsonProperty("medium") + public List medium; + + @JsonProperty("large") + public List large; + } + + public static final class Iterations { + + @JsonProperty("warmup") + public int warmup; + + @JsonProperty("measurement") + public int measurement; + } + + public static final class QuickConfig { + + @JsonProperty("data_sizes") + public DataSizes dataSizes; + + @JsonProperty("iterations") + public Iterations iterations; + + @JsonProperty("concurrency_levels") + public List concurrencyLevels; + + @JsonProperty("test_types") + public List testTypes; + } +} diff --git a/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/Report.java b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/Report.java new file mode 100644 index 000000000..8eeea4cc5 --- /dev/null +++ b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/Report.java @@ -0,0 +1,57 @@ +package com.amazon.esdk.benchmark.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class Report { + + private static final Logger logger = LoggerFactory.getLogger(Report.class); + + @JsonProperty("metadata") + public BenchmarkMetadata metadata; + + @JsonProperty("results") + public List results; + + public static void saveResults( + final List results, + final String outputPath, + final int cpuCount, + final double totalMemoryMB + ) throws IOException { + final Path outputFile = Paths.get(outputPath); + Files.createDirectories(outputFile.getParent()); + + final Report resultsData = new Report(); + + final BenchmarkMetadata metadata = new BenchmarkMetadata(); + metadata.language = "java"; + metadata.timestamp = + java.time.LocalDateTime + .now() + .format( + java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") + ); + metadata.javaVersion = System.getProperty("java.version"); + metadata.cpuCount = cpuCount; + metadata.totalMemoryGb = totalMemoryMB / 1024.0; + metadata.totalTests = results.size(); + + resultsData.metadata = metadata; + resultsData.results = results; + + final ObjectMapper mapper = new ObjectMapper(); + mapper + .writerWithDefaultPrettyPrinter() + .writeValue(outputFile.toFile(), resultsData); + + System.out.println("Results saved to " + outputFile); + } +} diff --git a/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/TestResult.java b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/TestResult.java new file mode 100644 index 000000000..9d30faf72 --- /dev/null +++ b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/TestResult.java @@ -0,0 +1,199 @@ +package com.amazon.esdk.benchmark.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Collections; +import java.util.List; + +public final class TestResult { + + @JsonProperty("language") + public final String language = "java"; + + @JsonProperty("test_name") + public String testName; + + @JsonProperty("data_size") + public int dataSize; + + @JsonProperty("concurrency") + public int concurrency = 1; + + @JsonProperty("operations_per_second") + public double opsPerSecond; + + @JsonProperty("bytes_per_second") + public double bytesPerSecond; + + @JsonProperty("peak_memory_mb") + public double peakMemoryMb; + + @JsonProperty("memory_efficiency_ratio") + public double memoryEfficiencyRatio; + + @JsonProperty("avg_latency_ms") + public double avgLatencyMs; + + @JsonProperty("p50_latency_ms") + public double p50LatencyMs; + + @JsonProperty("p95_latency_ms") + public double p95LatencyMs; + + @JsonProperty("p99_latency_ms") + public double p99LatencyMs; + + @JsonProperty("encrypt_latency_ms") + public double encryptLatencyMs; + + @JsonProperty("decrypt_latency_ms") + public double decryptLatencyMs; + + @JsonProperty("timestamp") + public String timestamp = ""; + + @JsonProperty("java_version") + public String javaVersion = ""; + + @JsonProperty("cpu_count") + public int cpuCount; + + @JsonProperty("total_memory_gb") + public double totalMemoryGb; + + @JsonProperty("iterations") + public int iterations; + + public static TestResult createThroughputResult( + final List encryptLatencies, + final List decryptLatencies, + final List totalLatencies, + final int dataSize, + final int cpuCount, + final double totalMemoryMB + ) { + final double avgTotalLatency = totalLatencies + .stream() + .mapToDouble(Double::doubleValue) + .average() + .orElse(0.0); + final double opsPerSecond = avgTotalLatency > 0 + ? 1000.0 / avgTotalLatency + : 0.0; + + Collections.sort(totalLatencies); + + final var result = new TestResult(); + result.testName = "throughput"; + result.dataSize = dataSize; + result.concurrency = 1; + result.opsPerSecond = opsPerSecond; + result.bytesPerSecond = opsPerSecond * dataSize; + result.avgLatencyMs = avgTotalLatency; + result.p50LatencyMs = calculatePercentile(totalLatencies, 50); + result.p95LatencyMs = calculatePercentile(totalLatencies, 95); + result.p99LatencyMs = calculatePercentile(totalLatencies, 99); + result.encryptLatencyMs = + encryptLatencies + .stream() + .mapToDouble(Double::doubleValue) + .average() + .orElse(0.0); + result.decryptLatencyMs = + decryptLatencies + .stream() + .mapToDouble(Double::doubleValue) + .average() + .orElse(0.0); + result.iterations = encryptLatencies.size(); + result.timestamp = + java.time.LocalDateTime + .now() + .format( + java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") + ); + result.javaVersion = System.getProperty("java.version"); + result.cpuCount = cpuCount; + result.totalMemoryGb = totalMemoryMB / 1024.0; + + return result; + } + + public static TestResult createMemoryResult( + final double peakMemoryMb, + final double avgMemoryMb, + final int dataSize, + final int cpuCount, + final double totalMemoryMB + ) { + final double memoryEfficiency = peakMemoryMb > 0 + ? dataSize / (peakMemoryMb * 1024 * 1024) + : 0.0; + + final var result = new TestResult(); + result.testName = "memory"; + result.dataSize = dataSize; + result.concurrency = 1; + result.peakMemoryMb = peakMemoryMb; + result.memoryEfficiencyRatio = memoryEfficiency; + result.timestamp = + java.time.LocalDateTime + .now() + .format( + java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") + ); + result.javaVersion = System.getProperty("java.version"); + result.cpuCount = cpuCount; + result.totalMemoryGb = totalMemoryMB / 1024.0; + + return result; + } + + public static TestResult createConcurrentResult( + final List allTimes, + final int totalOps, + final int dataSize, + final int concurrency, + final int cpuCount, + final double totalMemoryMB + ) { + final double avgLatency = allTimes + .stream() + .mapToDouble(Double::doubleValue) + .average() + .orElse(0.0); + final double opsPerSecond = + totalOps / + (allTimes.stream().mapToDouble(Double::doubleValue).sum() / 1000.0); + + final var result = new TestResult(); + result.testName = "concurrent"; + result.dataSize = dataSize; + result.concurrency = concurrency; + result.opsPerSecond = opsPerSecond; + result.bytesPerSecond = opsPerSecond * dataSize; + result.avgLatencyMs = avgLatency; + result.iterations = totalOps; + result.timestamp = + java.time.LocalDateTime + .now() + .format( + java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") + ); + result.javaVersion = System.getProperty("java.version"); + result.cpuCount = cpuCount; + result.totalMemoryGb = totalMemoryMB / 1024.0; + + return result; + } + + private static double calculatePercentile( + final List values, + final int percentile + ) { + if (values.isEmpty()) return 0.0; + + final int index = (int) Math.ceil((percentile / 100.0) * values.size()) - 1; + final int clampedIndex = Math.max(0, Math.min(index, values.size() - 1)); + return values.get(clampedIndex); + } +} From 44993c9b6e76e913798a9661a50e1a9b2f6b8347 Mon Sep 17 00:00:00 2001 From: Shubham Chaturvedi Date: Fri, 5 Sep 2025 15:07:13 -0700 Subject: [PATCH 2/3] fix: Check in results --- .../benchmarks/java/README.md | 219 +--- .../benchmarks/java/pom.xml | 152 +-- .../amazon/esdk/benchmark/ESDKBenchmark.java | 30 +- .../com/amazon/esdk/benchmark/Program.java | 34 +- .../java/com/amazon/esdk/benchmark/Tests.java | 364 +++--- .../amazon/esdk/benchmark/model/Config.java | 8 +- .../results/raw-data/java_results.json | 1146 +++++++++++++++++ 7 files changed, 1423 insertions(+), 530 deletions(-) create mode 100644 esdk-performance-testing/results/raw-data/java_results.json diff --git a/esdk-performance-testing/benchmarks/java/README.md b/esdk-performance-testing/benchmarks/java/README.md index 9180682c5..a88665ad7 100644 --- a/esdk-performance-testing/benchmarks/java/README.md +++ b/esdk-performance-testing/benchmarks/java/README.md @@ -1,216 +1,43 @@ -# ESDK Performance Benchmark - Java +# AWS Encryption SDK Java Benchmark -This directory contains the Java implementation of the AWS Encryption SDK (ESDK) performance benchmark suite. +Performance testing suite for the AWS Encryption SDK Java implementation. -## Overview - -The Java benchmark provides comprehensive performance testing for the ESDK Java runtime, measuring: - -- **Throughput**: Operations per second and bytes per second -- **Latency**: Encrypt, decrypt, and end-to-end timing -- **Memory Usage**: Peak memory consumption and efficiency -- **Concurrency**: Multi-threaded performance scaling -- **Statistical Analysis**: P50, P95, P99 latency percentiles - -## Prerequisites - -- Java 11 or higher -- Maven 3.6 or higher -- Access to AWS Encryption SDK Java libraries - -## Building +## Quick Start ```bash # Build the project mvn clean compile -# Create executable JAR -mvn clean package - -# Run tests -mvn test -``` - -## Running Benchmarks - -### Quick Test - -```bash -# Using Maven -mvn exec:java -Dexec.mainClass="com.amazon.esdk.benchmark.ESDKBenchmark" -Dexec.args="--quick" +# Run benchmark +mvn exec:java -Dexec.mainClass="com.amazon.esdk.benchmark.Program" -# Using JAR -java -jar target/esdk-benchmark.jar --quick +# Quick test (reduced iterations) +mvn exec:java -Dexec.mainClass="com.amazon.esdk.benchmark.Program" -Dexec.args="--quick" ``` -### Full Benchmark Suite +## Options -```bash -# Using Maven -mvn exec:java -Dexec.mainClass="com.amazon.esdk.benchmark.ESDKBenchmark" - -# Using JAR -java -jar target/esdk-benchmark.jar -``` - -### Custom Configuration - -```bash -# Specify custom config and output paths -java -jar target/esdk-benchmark.jar \ - --config /path/to/config.yaml \ - --output /path/to/results.json -``` - -## Command Line Options - -- `--config, -c`: Path to test configuration file (default: `../../config/test-scenarios.yaml`) -- `--output, -o`: Path to output results file (default: `../../results/raw-data/java_results.json`) -- `--quick, -q`: Run quick test with reduced iterations -- `--help, -h`: Show help message +- `--config` - Path to test configuration file (default: `../../config/test-scenarios.yaml`) +- `--output` - Path to output results file (default: `../../results/raw-data/java_results.json`) +- `--quick` - Run with reduced iterations for faster testing ## Configuration -The benchmark uses a YAML configuration file to define test parameters: - -```yaml -data_sizes: - small: [1024, 5120, 10240] - medium: [102400, 512000, 1048576] - large: [10485760, 52428800, 104857600] - -iterations: - warmup: 5 - measurement: 10 - -concurrency_levels: [1, 2, 4, 8] -algorithm_suites: ["ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256"] -frame_lengths: [4096, 65536, 1048576] -``` - -## Output Format - -Results are saved in JSON format with the following structure: - -```json -{ - "metadata": { - "language": "java", - "timestamp": "2025-08-27T15:30:00Z", - "javaVersion": "11.0.20", - "cpuCount": 8, - "totalMemoryGB": 16.0, - "totalTests": 45 - }, - "results": [ - { - "testName": "throughput", - "language": "java", - "dataSize": 1024, - "algorithmSuite": "ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256", - "frameLength": 4096, - "concurrency": 1, - "encryptLatencyMs": 0.85, - "decryptLatencyMs": 0.72, - "endToEndLatencyMs": 1.57, - "opsPerSecond": 636.94, - "bytesPerSecond": 652224.0, - "peakMemoryMB": 0.0, - "memoryEfficiencyRatio": 0.0, - "p50Latency": 1.55, - "p95Latency": 1.89, - "p99Latency": 2.12, - "timestamp": "2025-08-27T15:30:15Z", - "javaVersion": "11.0.20", - "cpuCount": 8, - "totalMemoryGB": 16.0 - } - ] -} -``` - -## Performance Tuning - -### JVM Options - -For optimal performance, consider these JVM options: - -```bash -java -Xmx4g -Xms2g \ - -XX:+UseG1GC \ - -XX:MaxGCPauseMillis=200 \ - -XX:+UnlockExperimentalVMOptions \ - -XX:+UseJVMCICompiler \ - -jar target/esdk-benchmark.jar -``` - -### System Configuration - -- Ensure adequate heap memory (recommended: 4GB+) -- Use SSD storage for temporary files -- Disable CPU frequency scaling for consistent results -- Close unnecessary applications during benchmarking - -## Troubleshooting - -### Common Issues - -1. **OutOfMemoryError**: Increase heap size with `-Xmx` option -2. **Dependency conflicts**: Run `mvn dependency:tree` to check for conflicts -3. **Slow performance**: Ensure JVM warmup and disable background processes - -### Debug Mode - -Enable debug logging: - -```bash -java -Dorg.slf4j.simpleLogger.defaultLogLevel=debug \ - -jar target/esdk-benchmark.jar -``` - -## Integration - -### CI/CD Pipeline - -Example GitHub Actions workflow: - -```yaml -- name: Run Java Benchmarks - run: | - cd aws-encryption-sdk/esdk-performance-testing/benchmarks/java - mvn clean package - java -jar target/esdk-benchmark.jar --quick -``` - -### Automated Analysis - -The benchmark integrates with the overall performance testing suite. Results can be: - -- Compared across language implementations -- Tracked over time for regression detection -- Analyzed for performance optimization opportunities - -## Contributing - -When modifying the Java benchmark: +Edit `../../config/test-scenarios.yaml` for test parameters: -1. Follow Java coding standards -2. Add appropriate unit tests -3. Update documentation for new features -4. Ensure compatibility with existing configuration format -5. Test with both quick and full benchmark modes +- Data sizes (small/medium/large) +- Iterations and concurrency levels -## Dependencies +## Test Types -Key dependencies used in this benchmark: +- **Throughput** - Measures encryption/decryption operations per second +- **Memory** - Tracks memory usage and allocations during operations +- **Concurrency** - Tests performance under concurrent load -- **AWS Encryption SDK**: Core encryption/decryption functionality -- **Jackson**: JSON/YAML processing -- **Commons CLI**: Command line argument parsing -- **ProgressBar**: Visual progress indication -- **SLF4J**: Logging framework -- **JUnit**: Unit testing (test scope) +## Output -## License +Results saved as JSON to `../../results/raw-data/java_results.json` with: -This benchmark suite is part of the AWS Encryption SDK project and follows the same licensing terms. +- Performance metrics (ops/sec, latency percentiles) +- Memory usage (peak, average, allocations, input data to memory ratio) +- System information (CPU, memory, Java version) diff --git a/esdk-performance-testing/benchmarks/java/pom.xml b/esdk-performance-testing/benchmarks/java/pom.xml index 2cdf71224..538a3f60e 100644 --- a/esdk-performance-testing/benchmarks/java/pom.xml +++ b/esdk-performance-testing/benchmarks/java/pom.xml @@ -9,37 +9,12 @@ 1.0.0 jar - ESDK Performance Benchmark - Java - Performance benchmarking suite for AWS Encryption SDK Java runtime - 17 17 UTF-8 - - - 3.0.2 - 2.15.2 - 0.9.5 - 1.5.0 - 2.0.7 - 1.4.8 - 5.10.0 - - - - - software.amazon.awssdk - bom - 2.25.1 - pom - import - - - - @@ -55,95 +30,41 @@ 1.0.2 - - - - software.amazon.awssdk - kms - - - + com.fasterxml.jackson.core jackson-databind - ${jackson.version} + 2.15.2 com.fasterxml.jackson.dataformat jackson-dataformat-yaml - ${jackson.version} + 2.15.2 - + me.tongfei progressbar - ${progressbar.version} - - - - - commons-cli - commons-cli - ${commons.cli.version} + 0.9.5 - + org.slf4j - slf4j-api - ${slf4j.version} - - - - - ch.qos.logback - logback-classic - ${logback.version} - - - - - org.junit.jupiter - junit-jupiter-engine - ${junit.version} - test - - - org.junit.jupiter - junit-jupiter-api - ${junit.version} - test + slf4j-simple + 2.0.7 - org.apache.maven.plugins maven-compiler-plugin 3.11.0 - - 17 - 17 - UTF-8 - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.1.2 - - - **/*Test.java - - - - - org.apache.maven.plugins maven-shade-plugin @@ -175,80 +96,25 @@ - org.codehaus.mojo exec-maven-plugin 3.1.0 com.amazon.esdk.benchmark.Program - - - - - - - org.apache.maven.plugins - maven-clean-plugin - 3.3.1 - - - - - org.apache.maven.plugins - maven-resources-plugin - 3.3.1 - - - - - org.apache.maven.plugins - maven-jar-plugin - 3.3.0 - - - - - org.apache.maven.plugins - maven-install-plugin - 3.1.1 - - - - - org.apache.maven.plugins - maven-deploy-plugin - 3.1.1 - - - com.diffplug.spotless spotless-maven-plugin 2.40.0 - - 1.17.0 - - - - - + - - - - central - Maven Central Repository - https://repo1.maven.org/maven2 - - diff --git a/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/ESDKBenchmark.java b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/ESDKBenchmark.java index b2951290f..8d0ea0e46 100644 --- a/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/ESDKBenchmark.java +++ b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/ESDKBenchmark.java @@ -81,9 +81,7 @@ public ESDKBenchmark(final String configPath) throws Exception { ); } - /** - * Run a single encrypt-decrypt cycle and measure performance - */ + /** Run a single encrypt-decrypt cycle and measure performance */ public EncryptDecryptResult runEncryptDecryptCycle(final byte[] data) { final var encryptionContext = Collections.singletonMap( "purpose", @@ -176,8 +174,14 @@ public List runAllBenchmarks() { ); } } catch (final Exception e) { - System.err.println("Throughput test failed: " + e.getMessage()); + System.err.println( + "Throughput test failed for data size " + + dataSize + + " bytes: " + + e.getMessage() + ); } + System.out.flush(); pb.step(); System.out.flush(); } @@ -194,8 +198,14 @@ public List runAllBenchmarks() { ); System.out.flush(); } catch (final Exception e) { - System.err.println("Memory test failed: " + e.getMessage()); + System.err.println( + "Memory test failed for data size " + + dataSize + + " bytes: " + + e.getMessage() + ); } + System.out.flush(); pb.step(); System.out.flush(); } @@ -220,8 +230,16 @@ public List runAllBenchmarks() { " threads" ); } catch (final Exception e) { - System.err.println("Concurrent test failed: " + e.getMessage()); + System.err.println( + "Concurrent test failed for data size " + + dataSize + + " bytes with " + + concurrency + + " threads: " + + e.getMessage() + ); } + System.out.flush(); pb.step(); System.out.flush(); } diff --git a/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Program.java b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Program.java index 6213cbd0a..844105c11 100644 --- a/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Program.java +++ b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Program.java @@ -15,20 +15,20 @@ public static void main(final String[] args) { if (options == null) return; try { - final ESDKBenchmark benchmark = new ESDKBenchmark(options.configPath); + final ESDKBenchmark benchmark = new ESDKBenchmark(options.configPath()); - if (options.quickTest) { + if (options.quickTest()) { benchmark.config.adjustForQuickTest(); } final List results = benchmark.runAllBenchmarks(); Report.saveResults( results, - options.outputPath, + options.outputPath(), benchmark.cpuCount, benchmark.totalMemoryMB ); - printSummary(results, options.outputPath); + printSummary(results, options.outputPath()); } catch (final Exception ex) { System.out.println("Benchmark failed: " + ex.getMessage()); } @@ -36,25 +36,24 @@ public static void main(final String[] args) { private static CommandLineOptions parseArgs(final String[] args) { // Default options - final CommandLineOptions options = new CommandLineOptions(); - options.configPath = "../../config/test-scenarios.yaml"; - options.outputPath = "../../results/raw-data/java_results.json"; - options.quickTest = false; + String configPath = "../../config/test-scenarios.yaml"; + String outputPath = "../../results/raw-data/java_results.json"; + boolean quickTest = false; // Simple argument parsing for (int i = 0; i < args.length; i++) { switch (args[i]) { case "--config": case "-c": - if (i + 1 < args.length) options.configPath = args[++i]; + if (i + 1 < args.length) configPath = args[++i]; break; case "--output": case "-o": - if (i + 1 < args.length) options.outputPath = args[++i]; + if (i + 1 < args.length) outputPath = args[++i]; break; case "--quick": case "-q": - options.quickTest = true; + quickTest = true; break; case "--help": case "-h": @@ -63,7 +62,7 @@ private static CommandLineOptions parseArgs(final String[] args) { } } - return options; + return new CommandLineOptions(configPath, outputPath, quickTest); } private static void printUsage() { @@ -113,10 +112,9 @@ private static void printSummary( } } - public static final class CommandLineOptions { - - public String configPath; - public String outputPath; - public boolean quickTest; - } + public record CommandLineOptions( + String configPath, + String outputPath, + boolean quickTest + ) {} } diff --git a/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Tests.java b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Tests.java index d84b86583..59542ced2 100644 --- a/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Tests.java +++ b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Tests.java @@ -24,9 +24,7 @@ public final class Tests { private static final int GcSettleTimeMs = 5; private static final int FinalSampleWaitMs = 2; - /** - * Run throughput benchmark test - */ + /** Run throughput benchmark test */ public static TestResult runThroughputTest( final ESDKBenchmark benchmark, final int dataSize, @@ -43,8 +41,12 @@ public static TestResult runThroughputTest( final byte[] data = new byte[dataSize]; new java.security.SecureRandom().nextBytes(data); - // Warmup - runWarmupIterations(benchmark, data, benchmark.config.iterations.warmup); + // Warmup - run measurement but drop results + runMeasurementIterations( + benchmark, + data, + benchmark.config.iterations.warmup + ); // Measurement runs final var results = runMeasurementIterations(benchmark, data, iterations); @@ -68,32 +70,15 @@ public static TestResult runThroughputTest( } private static long getTotalAllocatedBytes() { - try { - final var memoryBean = - java.lang.management.ManagementFactory.getMemoryMXBean(); - final var heapUsage = memoryBean.getHeapMemoryUsage(); - final var nonHeapUsage = memoryBean.getNonHeapMemoryUsage(); - return heapUsage.getUsed() + nonHeapUsage.getUsed(); - } catch (final Exception e) { - final Runtime runtime = Runtime.getRuntime(); - return runtime.totalMemory() - runtime.freeMemory(); - } - } + final var threadBean = + java.lang.management.ManagementFactory.getThreadMXBean(); + final var sunThreadBean = (com.sun.management.ThreadMXBean) threadBean; - private static void runWarmupIterations( - final ESDKBenchmark benchmark, - final byte[] data, - final int warmupCount - ) { - for (int i = 0; i < warmupCount; i++) { - try { - benchmark.runEncryptDecryptCycle(data); - } catch (final Exception e) { - System.out.println( - "Warmup iteration " + i + " failed: " + e.getMessage() - ); - } + if (!sunThreadBean.isThreadAllocatedMemoryEnabled()) { + sunThreadBean.setThreadAllocatedMemoryEnabled(true); } + + return sunThreadBean.getCurrentThreadAllocatedBytes(); } private static MeasurementResults runMeasurementIterations( @@ -127,9 +112,7 @@ private static MeasurementResults runMeasurementIterations( ); } - /** - * Run memory usage benchmark test - */ + /** Run memory usage benchmark test */ public static TestResult runMemoryTest( final ESDKBenchmark benchmark, final int dataSize @@ -147,6 +130,14 @@ public static TestResult runMemoryTest( new java.security.SecureRandom().nextBytes(data); final var memoryResults = sampleMemoryDuringOperations(benchmark, data); + if (memoryResults == null) { + throw new RuntimeException( + "Memory test failed: Unable to collect memory samples for data size " + + dataSize + + " bytes" + ); + } + return TestResult.createMemoryResult( memoryResults.peakMemoryMb, memoryResults.avgMemoryMb, @@ -165,132 +156,19 @@ private static MemoryResults sampleMemoryDuringOperations( final var avgMemoryValues = new ArrayList(); for (int i = 0; i < MemoryTestIterations; i++) { - // Force GC and settle - System.gc(); - System.gc(); - try { - Thread.sleep(GcSettleTimeMs); - } catch (final InterruptedException e) {} - - final long baselineMemory = - Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); - final long baselineAllocations = getTotalAllocatedBytes(); - final var memorySamples = new ArrayList(); - - // Sample memory during operation - final long operationStart = System.nanoTime(); - - // Start background sampling - final var samplingTask = new Thread(() -> { - try { - while (System.nanoTime() - operationStart < 100_000_000) { // 100ms - final long currentMemory = - Runtime.getRuntime().totalMemory() - - Runtime.getRuntime().freeMemory(); - final long currentAllocations = getTotalAllocatedBytes(); - final double heapDelta = - (currentMemory - baselineMemory) / (1024.0 * 1024.0); - final double allocsDelta = - (currentAllocations - baselineAllocations) / (1024.0 * 1024.0); - - if (heapDelta > 0 || allocsDelta > 0) { - synchronized (memorySamples) { - memorySamples.add( - new MemorySample( - Math.max(0, heapDelta), - Math.max(0, allocsDelta) - ) - ); - } - } - Thread.sleep(SamplingIntervalMs); - } - } catch (final InterruptedException e) {} - }); - - samplingTask.start(); - - // Run the actual operation - try { - benchmark.runEncryptDecryptCycle(data); - } catch (final Exception e) { - System.out.println( - "Memory test iteration " + (i + 1) + " failed: " + e.getMessage() - ); - continue; - } - - final double operationDurationMs = - (System.nanoTime() - operationStart) / 1_000_000.0; - - // Wait for sampling to complete - try { - Thread.sleep(FinalSampleWaitMs); - samplingTask.join(100); - } catch (final InterruptedException e) {} - - // Get final measurements - final Runtime runtime = Runtime.getRuntime(); - final long finalMemory = runtime.totalMemory() - runtime.freeMemory(); - final long finalAllocations = getTotalAllocatedBytes(); - final double finalHeapDelta = - (finalMemory - baselineMemory) / (1024.0 * 1024.0); - final double finalAllocsDelta = - (finalAllocations - baselineAllocations) / (1024.0 * 1024.0); - - // Calculate iteration metrics - final double iterPeakMemory; - final double iterTotalAllocs; - final double iterAvgMemory; - - synchronized (memorySamples) { - if (memorySamples.isEmpty()) { - iterPeakMemory = Math.max(0, finalHeapDelta); - iterTotalAllocs = Math.max(0, finalAllocsDelta); - iterAvgMemory = Math.max(0, finalHeapDelta); - } else { - iterPeakMemory = - memorySamples.stream().mapToDouble(s -> s.heapMB).max().orElse(0.0); - iterTotalAllocs = - memorySamples - .stream() - .mapToDouble(s -> s.allocsMB) - .max() - .orElse(0.0); - iterAvgMemory = - memorySamples - .stream() - .mapToDouble(s -> s.heapMB) - .average() - .orElse(0.0); - } - } + final var iterationResult = runSingleMemoryIteration( + benchmark, + data, + i + 1 + ); - if (iterPeakMemory > peakMemoryDelta) { - peakMemoryDelta = iterPeakMemory; + if (iterationResult.peakMemory > peakMemoryDelta) { + peakMemoryDelta = iterationResult.peakMemory; } - if (iterTotalAllocs > peakAllocations) { - peakAllocations = iterTotalAllocs; + if (iterationResult.totalAllocs > peakAllocations) { + peakAllocations = iterationResult.totalAllocs; } - - avgMemoryValues.add(iterAvgMemory); - - System.out.println( - "=== Iteration " + - (i + 1) + - " === Peak Heap: " + - String.format("%.2f", iterPeakMemory) + - " MB, Total Allocs: " + - String.format("%.2f", iterTotalAllocs) + - " MB, Avg Heap: " + - String.format("%.2f", iterAvgMemory) + - " MB (" + - String.format("%.0f", operationDurationMs) + - "ms, " + - memorySamples.size() + - " samples)" - ); - System.out.flush(); + avgMemoryValues.add(iterationResult.avgMemory); } final double overallAvgMemory = avgMemoryValues.isEmpty() @@ -322,9 +200,153 @@ private static MemoryResults sampleMemoryDuringOperations( return new MemoryResults(peakMemoryDelta, overallAvgMemory); } - /** - * Run concurrent operations benchmark test - */ + private static IterationResult runSingleMemoryIteration( + final ESDKBenchmark benchmark, + final byte[] data, + final int iteration + ) { + // Force GC and settle + System.gc(); + System.gc(); + try { + Thread.sleep(GcSettleTimeMs); + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException( + "Memory test interrupted during GC settle phase", + e + ); + } + + final long baselineMemory = + Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); + final long baselineAllocations = getTotalAllocatedBytes(); + final var memorySamples = new ArrayList(); + + final long operationStart = System.nanoTime(); + + // Start background sampling + final var samplingTask = new Thread(() -> { + try { + while (System.nanoTime() - operationStart < 100_000_000) { // 100ms + final long currentMemory = + Runtime.getRuntime().totalMemory() - + Runtime.getRuntime().freeMemory(); + final long currentAllocations = getTotalAllocatedBytes(); + final double heapDelta = + (currentMemory - baselineMemory) / (1024.0 * 1024.0); + final double cumulativeAllocs = + (currentAllocations - baselineAllocations) / (1024.0 * 1024.0); + + if (heapDelta > 0 || cumulativeAllocs > 0) { + synchronized (memorySamples) { + memorySamples.add( + new MemorySample( + Math.max(0, heapDelta), + Math.max(0, cumulativeAllocs) + ) + ); + } + } + Thread.sleep(SamplingIntervalMs); + } + } catch (final InterruptedException e) {} + }); + + samplingTask.start(); + + // Run the actual operation + try { + benchmark.runEncryptDecryptCycle(data); + } catch (final Exception e) { + System.out.println( + "Memory test iteration " + iteration + " failed: " + e.getMessage() + ); + return new IterationResult(0.0, 0.0, 0.0); + } + + final double operationDurationMs = + (System.nanoTime() - operationStart) / 1_000_000.0; + + // Wait for sampling to complete + try { + Thread.sleep(FinalSampleWaitMs); + samplingTask.join(100); + } catch (final InterruptedException e) {} + + return calculateIterationMetrics( + baselineMemory, + baselineAllocations, + memorySamples, + iteration, + operationDurationMs + ); + } + + private static IterationResult calculateIterationMetrics( + final long baselineMemory, + final long baselineAllocations, + final ArrayList memorySamples, + final int iteration, + final double operationDurationMs + ) { + final long finalMemory = + Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); + final long finalAllocations = getTotalAllocatedBytes(); + final double finalHeapDelta = + (finalMemory - baselineMemory) / (1024.0 * 1024.0); + final double finalCumulativeAllocs = + (finalAllocations - baselineAllocations) / (1024.0 * 1024.0); + + final double iterPeakMemory; + final double iterTotalAllocs; + final double iterAvgMemory; + + synchronized (memorySamples) { + if (memorySamples.isEmpty()) { + iterPeakMemory = Math.max(0, finalHeapDelta); + iterTotalAllocs = Math.max(0, finalCumulativeAllocs); + iterAvgMemory = Math.max(0, finalHeapDelta); + } else { + iterPeakMemory = + memorySamples.stream().mapToDouble(s -> s.heapMB).max().orElse(0.0); + iterTotalAllocs = Math.max(0, finalCumulativeAllocs); + iterAvgMemory = + memorySamples + .stream() + .mapToDouble(s -> s.heapMB) + .average() + .orElse(0.0); + } + } + + System.out.println( + "=== Iteration " + + iteration + + " === Peak Heap: " + + String.format("%.2f", iterPeakMemory) + + " MB, Total Allocs: " + + String.format("%.2f", iterTotalAllocs) + + " MB, Avg Heap: " + + String.format("%.2f", iterAvgMemory) + + " MB (" + + String.format("%.0f", operationDurationMs) + + "ms, " + + memorySamples.size() + + " samples)" + ); + System.out.flush(); + + return new IterationResult(iterPeakMemory, iterTotalAllocs, iterAvgMemory); + } + + private record IterationResult( + double peakMemory, + double totalAllocs, + double avgMemory + ) {} + + /** Run concurrent operations benchmark test */ public static TestResult runConcurrentTest( final ESDKBenchmark benchmark, final int dataSize, @@ -335,10 +357,23 @@ public static TestResult runConcurrentTest( "Running concurrent test - Size: " + dataSize + " bytes, Concurrency: " + - concurrency + concurrency + + ", Iterations per thread: " + + iterationsPerThread ); System.out.flush(); + if (concurrency <= 0) { + throw new IllegalArgumentException( + "Concurrency must be positive, got: " + concurrency + ); + } + if (iterationsPerThread <= 0) { + throw new IllegalArgumentException( + "Iterations per thread must be positive, got: " + iterationsPerThread + ); + } + final byte[] data = new byte[dataSize]; new java.security.SecureRandom().nextBytes(data); final List allTimes = Collections.synchronizedList( @@ -367,6 +402,7 @@ public static TestResult runConcurrentTest( (System.nanoTime() - threadStartTime) / 1_000_000.0; allTimes.add(elapsed); + System.out.flush(); concurrentPb.step(); System.out.flush(); } catch (final Exception e) { @@ -393,7 +429,13 @@ public static TestResult runConcurrentTest( executor.shutdown(); if (allTimes.isEmpty()) { - throw new RuntimeException("All concurrent operations failed"); + throw new RuntimeException( + "Concurrent test failed: No operations completed successfully. " + + "Concurrency: " + + concurrency + + ", Expected operations: " + + (concurrency * iterationsPerThread) + ); } // Calculate metrics @@ -409,7 +451,7 @@ public static TestResult runConcurrentTest( ); } - // Helper classes + // Helper records private record MeasurementResults( List encryptLatencies, List decryptLatencies, diff --git a/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/Config.java b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/Config.java index 3f4564313..d35a006ef 100644 --- a/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/Config.java +++ b/esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/Config.java @@ -29,9 +29,7 @@ public final class Config { @JsonProperty("quick_config") public QuickConfig quickConfig; - /** - * Load test configuration from YAML file - */ + /** Load test configuration from YAML file */ public static Config loadConfig(String configPath) throws IOException { ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); File configFile = new File(configPath); @@ -44,9 +42,7 @@ public static Config loadConfig(String configPath) throws IOException { return mapper.readValue(configFile, Config.class); } - /** - * Adjust configuration for quick test - */ + /** Adjust configuration for quick test */ public void adjustForQuickTest() { this.iterations = quickConfig.iterations; diff --git a/esdk-performance-testing/results/raw-data/java_results.json b/esdk-performance-testing/results/raw-data/java_results.json new file mode 100644 index 000000000..ed72e761a --- /dev/null +++ b/esdk-performance-testing/results/raw-data/java_results.json @@ -0,0 +1,1146 @@ +{ + "metadata": { + "language": "java", + "timestamp": "2025-09-05 16:14:17", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "total_tests": 54 + }, + "results": [ + { + "language": "java", + "test_name": "throughput", + "data_size": 1024, + "concurrency": 1, + "operations_per_second": 183.17715984509732, + "bytes_per_second": 187573.41168137966, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 5.4591959, + "p50_latency_ms": 5.086, + "p95_latency_ms": 6.922917, + "p99_latency_ms": 6.922917, + "encrypt_latency_ms": 2.6386793, + "decrypt_latency_ms": 2.8132666, + "timestamp": "2025-09-05 16:10:06", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 10 + }, + { + "language": "java", + "test_name": "throughput", + "data_size": 5120, + "concurrency": 1, + "operations_per_second": 226.79187180652949, + "bytes_per_second": 1161174.383649431, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 4.4093291, + "p50_latency_ms": 4.314958, + "p95_latency_ms": 4.7515, + "p99_latency_ms": 4.7515, + "encrypt_latency_ms": 2.2099084, + "decrypt_latency_ms": 2.195804, + "timestamp": "2025-09-05 16:10:06", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 10 + }, + { + "language": "java", + "test_name": "throughput", + "data_size": 10240, + "concurrency": 1, + "operations_per_second": 201.5947840817049, + "bytes_per_second": 2064330.588996658, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 4.9604458000000005, + "p50_latency_ms": 4.703417, + "p95_latency_ms": 7.27925, + "p99_latency_ms": 7.27925, + "encrypt_latency_ms": 2.598525, + "decrypt_latency_ms": 2.3575292, + "timestamp": "2025-09-05 16:10:06", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 10 + }, + { + "language": "java", + "test_name": "throughput", + "data_size": 102400, + "concurrency": 1, + "operations_per_second": 134.89413036519483, + "bytes_per_second": 1.381315894939595e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 7.413221, + "p50_latency_ms": 7.378292, + "p95_latency_ms": 7.969375, + "p99_latency_ms": 7.969375, + "encrypt_latency_ms": 3.73405, + "decrypt_latency_ms": 3.6726084, + "timestamp": "2025-09-05 16:10:07", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 10 + }, + { + "language": "java", + "test_name": "throughput", + "data_size": 512000, + "concurrency": 1, + "operations_per_second": 53.228673270687835, + "bytes_per_second": 2.725308071459217e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 18.7868669, + "p50_latency_ms": 18.439625, + "p95_latency_ms": 20.558584, + "p99_latency_ms": 20.558584, + "encrypt_latency_ms": 9.387974700000001, + "decrypt_latency_ms": 9.381625, + "timestamp": "2025-09-05 16:10:07", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 10 + }, + { + "language": "java", + "test_name": "throughput", + "data_size": 1048576, + "concurrency": 1, + "operations_per_second": 27.557597624980417, + "bytes_per_second": 2.8896235487211466e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 36.2876334, + "p50_latency_ms": 35.236, + "p95_latency_ms": 42.721458, + "p99_latency_ms": 42.721458, + "encrypt_latency_ms": 18.3452959, + "decrypt_latency_ms": 17.9032249, + "timestamp": "2025-09-05 16:10:07", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 10 + }, + { + "language": "java", + "test_name": "throughput", + "data_size": 10485760, + "concurrency": 1, + "operations_per_second": 3.1914328746983025, + "bytes_per_second": 3.346459918019647e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 313.33887919999995, + "p50_latency_ms": 307.094292, + "p95_latency_ms": 337.59475, + "p99_latency_ms": 337.59475, + "encrypt_latency_ms": 154.4814208, + "decrypt_latency_ms": 158.5211291, + "timestamp": "2025-09-05 16:10:12", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 10 + }, + { + "language": "java", + "test_name": "throughput", + "data_size": 52428800, + "concurrency": 1, + "operations_per_second": 0.6636039793724537, + "bytes_per_second": 3.4791960313722506e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 1506.9228502, + "p50_latency_ms": 1506.442542, + "p95_latency_ms": 1514.673209, + "p99_latency_ms": 1514.673209, + "encrypt_latency_ms": 748.5883541000001, + "decrypt_latency_ms": 756.5866625, + "timestamp": "2025-09-05 16:10:36", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 10 + }, + { + "language": "java", + "test_name": "throughput", + "data_size": 104857600, + "concurrency": 1, + "operations_per_second": 0.3298922071027812, + "bytes_per_second": 3.459170509550059e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 3031.2931875000004, + "p50_latency_ms": 3024.457209, + "p95_latency_ms": 3098.780959, + "p99_latency_ms": 3098.780959, + "encrypt_latency_ms": 1503.7712665, + "decrypt_latency_ms": 1524.4756584, + "timestamp": "2025-09-05 16:11:22", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 10 + }, + { + "language": "java", + "test_name": "memory", + "data_size": 1024, + "concurrency": 1, + "operations_per_second": 0.0, + "bytes_per_second": 0.0, + "peak_memory_mb": 1.7046585083007812, + "memory_efficiency_ratio": 5.728786705634352e-4, + "avg_latency_ms": 0.0, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:23", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 0 + }, + { + "language": "java", + "test_name": "memory", + "data_size": 5120, + "concurrency": 1, + "operations_per_second": 0.0, + "bytes_per_second": 0.0, + "peak_memory_mb": 1.5947799682617188, + "memory_efficiency_ratio": 0.0030617468222416773, + "avg_latency_ms": 0.0, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:24", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 0 + }, + { + "language": "java", + "test_name": "memory", + "data_size": 10240, + "concurrency": 1, + "operations_per_second": 0.0, + "bytes_per_second": 0.0, + "peak_memory_mb": 1.64971923828125, + "memory_efficiency_ratio": 0.005919567871545377, + "avg_latency_ms": 0.0, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:24", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 0 + }, + { + "language": "java", + "test_name": "memory", + "data_size": 102400, + "concurrency": 1, + "operations_per_second": 0.0, + "bytes_per_second": 0.0, + "peak_memory_mb": 2.5905838012695312, + "memory_efficiency_ratio": 0.03769661878999744, + "avg_latency_ms": 0.0, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:25", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 0 + }, + { + "language": "java", + "test_name": "memory", + "data_size": 512000, + "concurrency": 1, + "operations_per_second": 0.0, + "bytes_per_second": 0.0, + "peak_memory_mb": 6.12054443359375, + "memory_efficiency_ratio": 0.07977742099542277, + "avg_latency_ms": 0.0, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:26", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 0 + }, + { + "language": "java", + "test_name": "memory", + "data_size": 1048576, + "concurrency": 1, + "operations_per_second": 0.0, + "bytes_per_second": 0.0, + "peak_memory_mb": 10.597297668457031, + "memory_efficiency_ratio": 0.09436367942900298, + "avg_latency_ms": 0.0, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:26", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 0 + }, + { + "language": "java", + "test_name": "memory", + "data_size": 10485760, + "concurrency": 1, + "operations_per_second": 0.0, + "bytes_per_second": 0.0, + "peak_memory_mb": 29.238876342773438, + "memory_efficiency_ratio": 0.342010407061062, + "avg_latency_ms": 0.0, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:28", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 0 + }, + { + "language": "java", + "test_name": "memory", + "data_size": 52428800, + "concurrency": 1, + "operations_per_second": 0.0, + "bytes_per_second": 0.0, + "peak_memory_mb": 71.91471862792969, + "memory_efficiency_ratio": 0.6952679639711665, + "avg_latency_ms": 0.0, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:36", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 0 + }, + { + "language": "java", + "test_name": "memory", + "data_size": 104857600, + "concurrency": 1, + "operations_per_second": 0.0, + "bytes_per_second": 0.0, + "peak_memory_mb": 120.01608276367188, + "memory_efficiency_ratio": 0.8332216624409723, + "avg_latency_ms": 0.0, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:53", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 0 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 1024, + "concurrency": 2, + "operations_per_second": 297.7279664334345, + "bytes_per_second": 304873.43762783695, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 3.3587708, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:53", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 10 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 1024, + "concurrency": 4, + "operations_per_second": 285.4303762741594, + "bytes_per_second": 292280.70530473924, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 3.50348135, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:53", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 20 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 1024, + "concurrency": 8, + "operations_per_second": 235.1300480488841, + "bytes_per_second": 240773.16920205732, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 4.252965574999999, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:53", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 40 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 1024, + "concurrency": 16, + "operations_per_second": 189.06029899101685, + "bytes_per_second": 193597.74616680125, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 5.289317775, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:53", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 80 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 5120, + "concurrency": 2, + "operations_per_second": 291.3696371742903, + "bytes_per_second": 1491812.5423323663, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 3.4320666, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:53", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 10 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 5120, + "concurrency": 4, + "operations_per_second": 285.18177800229824, + "bytes_per_second": 1460130.703371767, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 3.5065353999999997, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:53", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 20 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 5120, + "concurrency": 8, + "operations_per_second": 231.7807119902492, + "bytes_per_second": 1186717.2453900757, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 4.31442285, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:54", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 40 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 5120, + "concurrency": 16, + "operations_per_second": 208.87805738957525, + "bytes_per_second": 1069455.6538346251, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 4.7874822875, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:54", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 80 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 10240, + "concurrency": 2, + "operations_per_second": 280.91631531058533, + "bytes_per_second": 2876583.068780394, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 3.559779, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:54", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 10 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 10240, + "concurrency": 4, + "operations_per_second": 280.90939867087434, + "bytes_per_second": 2876512.2423897535, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 3.55986665, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:54", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 20 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 10240, + "concurrency": 8, + "operations_per_second": 233.28631428228448, + "bytes_per_second": 2388851.858250593, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 4.2865780749999995, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:54", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 40 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 10240, + "concurrency": 16, + "operations_per_second": 168.66046278529342, + "bytes_per_second": 1727083.1389214047, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 5.9290718374999996, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:54", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 80 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 102400, + "concurrency": 2, + "operations_per_second": 156.8121126191976, + "bytes_per_second": 1.6057560332205834e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 6.3770584, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:54", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 10 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 102400, + "concurrency": 4, + "operations_per_second": 149.00104447497162, + "bytes_per_second": 1.5257706954237094e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 6.71136235, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:54", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 20 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 102400, + "concurrency": 8, + "operations_per_second": 125.09367405230768, + "bytes_per_second": 1.2809592222956305e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 7.994009350000001, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:54", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 40 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 102400, + "concurrency": 16, + "operations_per_second": 87.98955904453734, + "bytes_per_second": 9010130.846160624, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 11.364984787500001, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:54", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 80 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 512000, + "concurrency": 2, + "operations_per_second": 53.961771840390405, + "bytes_per_second": 2.762842718227989e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 18.5316376, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:55", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 10 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 512000, + "concurrency": 4, + "operations_per_second": 52.052827936186425, + "bytes_per_second": 2.665104790332745e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 19.2112521, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:55", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 20 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 512000, + "concurrency": 8, + "operations_per_second": 45.13952639457689, + "bytes_per_second": 2.3111437514023367e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 22.153533275, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:55", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 40 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 512000, + "concurrency": 16, + "operations_per_second": 27.493576089861286, + "bytes_per_second": 1.4076710958008979e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 36.372132775, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:55", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 80 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 1048576, + "concurrency": 2, + "operations_per_second": 28.600499017502788, + "bytes_per_second": 2.9989796857777003e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 34.9644249, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:56", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 10 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 1048576, + "concurrency": 4, + "operations_per_second": 28.135081868087223, + "bytes_per_second": 2.9501771604911428e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 35.542814650000004, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:56", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 20 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 1048576, + "concurrency": 8, + "operations_per_second": 23.179996013921528, + "bytes_per_second": 2.430598750029378e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 43.140645899999996, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:56", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 40 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 1048576, + "concurrency": 16, + "operations_per_second": 14.912942198172926, + "bytes_per_second": 1.5637353278391374e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 67.0558489875, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:57", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 80 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 10485760, + "concurrency": 2, + "operations_per_second": 3.2049668864071235, + "bytes_per_second": 3.360651357881236e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 312.01570419999996, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:11:58", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 10 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 10485760, + "concurrency": 4, + "operations_per_second": 3.100631918164334, + "bytes_per_second": 3.2512482142210845e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 322.51490225, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:12:00", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 20 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 10485760, + "concurrency": 8, + "operations_per_second": 2.732758266103669, + "bytes_per_second": 2.8655047316379208e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 365.93064685, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:12:02", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 40 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 10485760, + "concurrency": 16, + "operations_per_second": 1.6803365133496777, + "bytes_per_second": 1.7619605398221515e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 595.1188896125, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:12:05", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 80 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 52428800, + "concurrency": 2, + "operations_per_second": 0.6478731969061788, + "bytes_per_second": 3.3967214265954666e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 1543.5119167999999, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:12:14", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 10 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 52428800, + "concurrency": 4, + "operations_per_second": 0.6293871109548517, + "bytes_per_second": 3.2998010962829728e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 1588.8472811, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:12:22", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 20 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 52428800, + "concurrency": 8, + "operations_per_second": 0.5444256095482306, + "bytes_per_second": 2.854358139788227e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 1836.798237375, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:12:32", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 40 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 52428800, + "concurrency": 16, + "operations_per_second": 0.3311160081951964, + "bytes_per_second": 1.736001497046431e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 3020.0895615125, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:12:48", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 80 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 104857600, + "concurrency": 2, + "operations_per_second": 0.3261257796901731, + "bytes_per_second": 3.4196766556440294e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 3066.3015998, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:13:04", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 10 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 104857600, + "concurrency": 4, + "operations_per_second": 0.3186014187846871, + "bytes_per_second": 3.340778013035721e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 3138.717975, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:13:21", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 20 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 104857600, + "concurrency": 8, + "operations_per_second": 0.27171557574562805, + "bytes_per_second": 2.8491443155304767e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 3680.319014675, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:13:41", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 40 + }, + { + "language": "java", + "test_name": "concurrent", + "data_size": 104857600, + "concurrency": 16, + "operations_per_second": 0.14575851776637366, + "bytes_per_second": 1.5283888352539303e7, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "avg_latency_ms": 6860.662521300001, + "p50_latency_ms": 0.0, + "p95_latency_ms": 0.0, + "p99_latency_ms": 0.0, + "encrypt_latency_ms": 0.0, + "decrypt_latency_ms": 0.0, + "timestamp": "2025-09-05 16:14:17", + "java_version": "17.0.16", + "cpu_count": 12, + "total_memory_gb": 9.0, + "iterations": 80 + } + ] +} From e856cf1fbbb2b979c35d5999af1d1c49ec85281c Mon Sep 17 00:00:00 2001 From: Shubham Chaturvedi Date: Mon, 8 Sep 2025 16:29:12 -0700 Subject: [PATCH 3/3] Update esdk-performance-testing/benchmarks/java/pom.xml Co-authored-by: Tony Knapp <5892063+texastony@users.noreply.github.com> --- esdk-performance-testing/benchmarks/java/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esdk-performance-testing/benchmarks/java/pom.xml b/esdk-performance-testing/benchmarks/java/pom.xml index 538a3f60e..92374679a 100644 --- a/esdk-performance-testing/benchmarks/java/pom.xml +++ b/esdk-performance-testing/benchmarks/java/pom.xml @@ -27,7 +27,7 @@ software.amazon.cryptography aws-cryptographic-material-providers - 1.0.2 + 1.11.0