diff --git a/db-esdk-performance-testing/benchmarks/config/test-scenarios.yaml b/db-esdk-performance-testing/benchmarks/config/test-scenarios.yaml new file mode 100644 index 000000000..c893a3587 --- /dev/null +++ b/db-esdk-performance-testing/benchmarks/config/test-scenarios.yaml @@ -0,0 +1,54 @@ +# DB-ESDK Performance Test Scenarios Configuration + +# Data sizes to test (in bytes) +# Categories are for organization only - code processes all sizes regardless of category +data_sizes: + small: + - 1024 # 1KB + - 5120 # 5KB + - 10240 # 10KB + medium: + - 102400 # 100KB + - 512000 # 500KB + - 1048576 # 1MB + - 10000000 # 10 MB + large: + - 10485760 # 10MB + - 52428800 # 50MB + - 100000000 + - 104857600 # 100MB + +# Quick test configuration (reduced test set for faster execution) +quick_config: + data_sizes: + small: + - 102400 # 100KB - within DynamoDB's 400KB limit + iterations: + warmup: 3 # Reduced warmup iterations + measurement: 3 # Reduced measurement iterations + concurrency_levels: + - 1 + - 2 + test_types: + - "throughput" + - "memory" + - "concurrency" + +# Test iterations for statistical significance +iterations: + warmup: 5 # Warmup iterations (not counted) + measurement: 10 # Measurement iterations + +# Concurrency levels to test +concurrency_levels: + - 1 + - 2 + - 4 + - 8 + - 16 + +# DynamoDB table name +table_name: "dbesdk-performance-testing" + +# Keyring +keyring: "raw-aes" \ No newline at end of file diff --git a/db-esdk-performance-testing/benchmarks/java/README.md b/db-esdk-performance-testing/benchmarks/java/README.md new file mode 100644 index 000000000..71201edd6 --- /dev/null +++ b/db-esdk-performance-testing/benchmarks/java/README.md @@ -0,0 +1,190 @@ +# DB-ESDK Performance Benchmark - Java + +This directory contains the Java implementation of the AWS Database Encryption SDK (DB-ESDK) performance benchmark suite. + +## Overview + +The Java benchmark provides comprehensive performance testing for the DB-ESDK Java runtime, measuring: + +- **Throughput**: Operations per second and bytes per second using DynamoDB batch operations +- **Latency**: Put, get, and end-to-end timing for encrypted DynamoDB operations +- **Memory Usage**: Peak memory consumption and efficiency +- **Concurrency**: Multi-threaded performance scaling +- **Statistical Analysis**: P50, P95, P99 latency percentiles + +## Prerequisites + +- Java 17 or higher +- Maven 3.6 or higher +- Local DynamoDB instance running on localhost:8000 +- Access to AWS Database Encryption SDK for DynamoDB Java libraries + +## Local DynamoDB Setup + +Start a local DynamoDB instance: + +```bash +# Using Docker +docker run -p 8000:8000 amazon/dynamodb-local + +# Or download and run DynamoDB Local +java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb -port 8000 +``` + +Create the test table: + +```bash +aws dynamodb create-table \ + --table-name db-esdk-performance-test \ + --attribute-definitions \ + AttributeName=partition_key,AttributeType=S \ + AttributeName=sort_key,AttributeType=N \ + --key-schema \ + AttributeName=partition_key,KeyType=HASH \ + AttributeName=sort_key,KeyType=RANGE \ + --billing-mode PAY_PER_REQUEST \ + --endpoint-url http://localhost:8000 +``` + +## 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.Program" -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.Program" + +# 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] +``` + +## Output Format + +Results are saved in JSON format with the following structure: + +```json +{ + "metadata": { + "language": "java", + "timestamp": "2025-09-05T15:30:00Z", + "javaVersion": "17.0.2", + "cpuCount": 8, + "totalMemoryGB": 16.0, + "totalTests": 45 + }, + "results": [ + { + "test_name": "throughput", + "language": "java", + "data_size": 1024, + "concurrency": 1, + "put_latency_ms": 0.85, + "get_latency_ms": 0.72, + "end_to_end_latency_ms": 1.57, + "ops_per_second": 636.94, + "bytes_per_second": 652224.0, + "peak_memory_mb": 0.0, + "memory_efficiency_ratio": 0.0, + "p50_latency": 1.55, + "p95_latency": 1.89, + "p99_latency": 2.12, + "timestamp": "2025-09-05T15:30:15Z", + "java_version": "17.0.2", + "cpu_count": 8, + "total_memory_gb": 16.0 + } + ] +} +``` + +## Key Features + +### DB-ESDK Integration +- Uses AWS Database Encryption SDK for DynamoDB with transparent encryption +- Configures attribute actions (ENCRYPT_AND_SIGN, SIGN_ONLY, DO_NOTHING) +- Tests actual DynamoDB operations with client-side encryption +- Uses Raw AES keyring for consistent performance testing + +### Batch Operations +- Performs BatchWriteItem operations with 25 items per batch +- Measures BatchGetItem operations with consistent reads +- Tests realistic DynamoDB workloads with encryption overhead + +### Performance Metrics +- **Throughput Tests**: Measures ops/sec and bytes/sec for batch operations +- **Memory Tests**: Tracks peak memory usage during encrypted operations +- **Concurrency Tests**: Evaluates multi-threaded performance scaling +- **Latency Analysis**: P50, P95, P99 percentiles for operation timing + +## Dependencies + +Key dependencies used in this benchmark: + +- **AWS Database Encryption SDK for DynamoDB**: Core encryption functionality for DynamoDB +- **AWS Cryptographic Material Providers**: Keyring and cryptographic material management +- **AWS SDK for Java v2 DynamoDB**: DynamoDB client operations +- **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/db-esdk-performance-testing/benchmarks/java/pom.xml b/db-esdk-performance-testing/benchmarks/java/pom.xml new file mode 100644 index 000000000..15634f36a --- /dev/null +++ b/db-esdk-performance-testing/benchmarks/java/pom.xml @@ -0,0 +1,255 @@ + + + 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 + + + 2.15.2 + 0.9.5 + 1.5.0 + 2.0.7 + 5.10.0 + + + + + + + software.amazon.awssdk + bom + 2.33.3 + pom + import + + + + + + + + software.amazon.cryptography + aws-database-encryption-sdk-dynamodb + 3.9.0 + + + + + software.amazon.cryptography + aws-cryptographic-material-providers + 1.11.0 + + + + + software.amazon.awssdk + dynamodb + + + + + 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} + + + + + org.junit.jupiter + junit-jupiter-engine + ${junit.version} + test + + + org.junit.jupiter + junit-jupiter-api + ${junit.version} + test + + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + com.example.Main + + -Xmx32g + + + + + + 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/db-esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/ESDKBenchmark.java b/db-esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/ESDKBenchmark.java new file mode 100644 index 000000000..c67c59150 --- /dev/null +++ b/db-esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/ESDKBenchmark.java @@ -0,0 +1,326 @@ +// 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 java.lang.management.ManagementFactory; +import java.net.URI; +import java.nio.ByteBuffer; +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import me.tongfei.progressbar.ProgressBar; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.BatchGetItemRequest; +import software.amazon.awssdk.services.dynamodb.model.BatchGetItemResponse; +import software.amazon.awssdk.services.dynamodb.model.BatchWriteItemRequest; +import software.amazon.awssdk.services.dynamodb.model.BatchWriteItemResponse; +import software.amazon.awssdk.services.dynamodb.model.BillingMode; +import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest; +import software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest; +import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement; +import software.amazon.awssdk.services.dynamodb.model.KeyType; +import software.amazon.awssdk.services.dynamodb.model.KeysAndAttributes; +import software.amazon.awssdk.services.dynamodb.model.PutRequest; +import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException; +import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; +import software.amazon.awssdk.services.dynamodb.model.WriteRequest; +import software.amazon.cryptography.dbencryptionsdk.dynamodb.DynamoDbEncryptionInterceptor; +import software.amazon.cryptography.dbencryptionsdk.dynamodb.itemencryptor.DynamoDbItemEncryptor; +import software.amazon.cryptography.dbencryptionsdk.dynamodb.itemencryptor.model.DecryptItemInput; +import software.amazon.cryptography.dbencryptionsdk.dynamodb.itemencryptor.model.DynamoDbItemEncryptorConfig; +import software.amazon.cryptography.dbencryptionsdk.dynamodb.itemencryptor.model.EncryptItemInput; +import software.amazon.cryptography.dbencryptionsdk.dynamodb.model.DynamoDbTableEncryptionConfig; +import software.amazon.cryptography.dbencryptionsdk.dynamodb.model.DynamoDbTablesEncryptionConfig; +import software.amazon.cryptography.dbencryptionsdk.structuredencryption.model.CryptoAction; +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.DBEAlgorithmSuiteId; +import software.amazon.cryptography.materialproviders.model.MaterialProvidersConfig; + +/** + * DB-ESDK Performance Benchmark Suite - Java Implementation + * + *

This class provides comprehensive performance testing for the AWS Database Encryption SDK (DB-ESDK) Java + * runtime, measuring throughput, latency, memory usage, and scalability using DynamoDB operations. + */ +public final class ESDKBenchmark { + + final Config config; + final DynamoDbItemEncryptor itemEncryptor; + final IKeyring keyring; + final String tableName; + // 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); + + // Table name for testing + this.tableName = "db-esdk-performance-test"; + + // Setup DB-ESDK with local DynamoDB + this.keyring = setupKeyring(); + this.itemEncryptor = setupItemEncryptorClient(); + + // Create table if it doesn't exist + // createTableIfNotExists(); + + System.out.println( + "Initialized DB-ESDK Benchmark - CPU cores: " + + cpuCount + + ", Memory: " + + (totalMemoryMB / 1024.0) + + "GB" + ); + } + + private IKeyring setupKeyring() throws Exception { + // 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 = "db-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(); + + return matProv.CreateRawAesKeyring(keyringInput); + } + + private DynamoDbItemEncryptor setupItemEncryptorClient() { + // Configure attribute actions for encryption + final Map attributeActionsOnEncrypt = new HashMap<>(); + attributeActionsOnEncrypt.put("partition_key", CryptoAction.SIGN_ONLY); + attributeActionsOnEncrypt.put("sort_key", CryptoAction.SIGN_ONLY); + attributeActionsOnEncrypt.put("attribute1", CryptoAction.ENCRYPT_AND_SIGN); + attributeActionsOnEncrypt.put("attribute2", CryptoAction.SIGN_ONLY); + attributeActionsOnEncrypt.put(":attribute3", CryptoAction.DO_NOTHING); + + // Configure table encryption + final DynamoDbItemEncryptorConfig tableConfig = DynamoDbItemEncryptorConfig + .builder() + .logicalTableName(tableName) + .partitionKeyName("partition_key") + .sortKeyName("sort_key") + .attributeActionsOnEncrypt(attributeActionsOnEncrypt) + .keyring(keyring) + .allowedUnsignedAttributePrefix(":") + .algorithmSuiteId(DBEAlgorithmSuiteId.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384_SYMSIG_HMAC_SHA384) + .build(); + + final DynamoDbItemEncryptor itemEncryptor = DynamoDbItemEncryptor + .builder() + .DynamoDbItemEncryptorConfig(tableConfig) + .build(); + + return itemEncryptor; + } + + /** + * Run a single batch put-get cycle and measure performance + */ + public Result runItemEncryptorCycle(final byte[] data) { + // Create 25 items with same data, different sort_key + final Map item = new HashMap<>(); + item.put("partition_key", AttributeValue.builder().s("benchmark-test").build()); + item.put("sort_key", AttributeValue.builder().n(String.valueOf(0)).build()); + item.put("attribute1", AttributeValue.builder() + .m(Map.of("data", AttributeValue.builder().b(SdkBytes.fromByteArray(data)).build())) + .build()); + item.put("attribute2", AttributeValue.builder().s("sign me!").build()); + item.put(":attribute3", AttributeValue.builder().s("ignore me!").build()); + + // Measure batch write + final long encryptStart = System.nanoTime(); + final Map encryptedItem = itemEncryptor + .EncryptItem( + EncryptItemInput.builder().plaintextItem(item).build() + ) + .encryptedItem(); + final long encryptTime = System.nanoTime() - encryptStart; + + // Measure batch get + final long decryptStart = System.nanoTime(); + final Map decryptedItem = itemEncryptor + .DecryptItem( + DecryptItemInput.builder().encryptedItem(encryptedItem).build() + ) + .plaintextItem(); + final long decryptTime = System.nanoTime() - decryptStart; + + return new Result( + encryptTime / 1_000_000.0, // Convert to milliseconds + decryptTime / 1_000_000.0 + ); + } + + 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 for data size " + + dataSize + + " bytes: " + + e.getMessage() + ); + } + System.out.flush(); + 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 for data size " + + dataSize + + " bytes: " + + e.getMessage() + ); + } + System.out.flush(); + 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 for data size " + + dataSize + + " bytes with " + + concurrency + + " threads: " + + e.getMessage() + ); + } + System.out.flush(); + pb.step(); + System.out.flush(); + } + } + } + } + + System.out.println( + "Benchmark suite completed. Total results: " + allResults.size() + ); + return allResults; + } + + + public record Result( + double putLatencyMs, + double getLatencyMs + ) {} +} diff --git a/db-esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Program.java b/db-esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Program.java new file mode 100644 index 000000000..94bc36a32 --- /dev/null +++ b/db-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/db-esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Tests.java b/db-esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Tests.java new file mode 100644 index 000000000..ebaa01b04 --- /dev/null +++ b/db-esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/Tests.java @@ -0,0 +1,464 @@ +// 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 - run measurement but drop results + runMeasurementIterations( + 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() { + final var threadBean = + java.lang.management.ManagementFactory.getThreadMXBean(); + final var sunThreadBean = (com.sun.management.ThreadMXBean) threadBean; + + if (!sunThreadBean.isThreadAllocatedMemoryEnabled()) { + sunThreadBean.setThreadAllocatedMemoryEnabled(true); + } + + return sunThreadBean.getCurrentThreadAllocatedBytes(); + } + + 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.runItemEncryptorCycle(data); + final double totalMs = + (System.nanoTime() - iterationStart) / 1_000_000.0; + + encryptLatencies.add(result.putLatencyMs()); + decryptLatencies.add(result.getLatencyMs()); + 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); + + 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, + 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++) { + final var iterationResult = runSingleMemoryIteration( + benchmark, + data, + i + 1 + ); + + if (iterationResult.peakMemory > peakMemoryDelta) { + peakMemoryDelta = iterationResult.peakMemory; + } + if (iterationResult.totalAllocs > peakAllocations) { + peakAllocations = iterationResult.totalAllocs; + } + avgMemoryValues.add(iterationResult.avgMemory); + } + + 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); + } + + 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.runItemEncryptorCycle(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, + final int concurrency, + final int iterationsPerThread + ) { + System.out.println( + "Running concurrent test - Size: " + + dataSize + + " bytes, 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( + 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.runItemEncryptorCycle(data); + final double elapsed = + (System.nanoTime() - threadStartTime) / 1_000_000.0; + allTimes.add(elapsed); + + System.out.flush(); + 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( + "Concurrent test failed: No operations completed successfully. " + + "Concurrency: " + + concurrency + + ", Expected operations: " + + (concurrency * iterationsPerThread) + ); + } + + // Calculate metrics + final int totalOperations = allTimes.size(); + + return TestResult.createConcurrentResult( + allTimes, + totalOperations, + dataSize, + concurrency, + benchmark.cpuCount, + benchmark.totalMemoryMB + ); + } + + // Helper records + private record MeasurementResults( + List encryptLatencies, + List decryptLatencies, + List totalLatencies + ) {} + + private record MemoryResults(double peakMemoryMb, double avgMemoryMb) {} + + private record MemorySample(double heapMB, double allocsMB) {} +} \ No newline at end of file diff --git a/db-esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/BenchmarkMetadata.java b/db-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/db-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/db-esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/Config.java b/db-esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/Config.java new file mode 100644 index 000000000..05985bd05 --- /dev/null +++ b/db-esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/Config.java @@ -0,0 +1,99 @@ +// 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; + + @JsonProperty("table_name") + public String tableName; + + @JsonProperty("keyring") + public String keyring; + + /** + * 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/db-esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/Report.java b/db-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/db-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/db-esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/TestResult.java b/db-esdk-performance-testing/benchmarks/java/src/main/java/com/amazon/esdk/benchmark/model/TestResult.java new file mode 100644 index 000000000..672d0d3e1 --- /dev/null +++ b/db-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 putLatencies, + final List getLatencies, + 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 = + putLatencies + .stream() + .mapToDouble(Double::doubleValue) + .average() + .orElse(0.0); + result.decryptLatencyMs = + getLatencies + .stream() + .mapToDouble(Double::doubleValue) + .average() + .orElse(0.0); + result.iterations = putLatencies.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); + } +} \ No newline at end of file diff --git a/db-esdk-performance-testing/benchmarks/results/raw-data/java_results.json b/db-esdk-performance-testing/benchmarks/results/raw-data/java_results.json new file mode 100644 index 000000000..8f13d7b52 --- /dev/null +++ b/db-esdk-performance-testing/benchmarks/results/raw-data/java_results.json @@ -0,0 +1,451 @@ +{ + "metadata" : { + "language" : "java", + "timestamp" : "2025-09-09 12:09:07", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "total_tests" : 22 + }, + "results" : [ { + "language" : "java", + "test_name" : "throughput", + "data_size" : 1024, + "concurrency" : 1, + "operations_per_second" : 124.68011757335088, + "bytes_per_second" : 127672.4403951113, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 8.020525, + "p50_latency_ms" : 7.118834, + "p95_latency_ms" : 14.138417, + "p99_latency_ms" : 14.138417, + "encrypt_latency_ms" : 3.6590665, + "decrypt_latency_ms" : 4.3440709, + "timestamp" : "2025-09-09 12:02:56", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "throughput", + "data_size" : 5120, + "concurrency" : 1, + "operations_per_second" : 150.10197778268576, + "bytes_per_second" : 768522.126247351, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 6.662137400000001, + "p50_latency_ms" : 6.507416, + "p95_latency_ms" : 7.470375, + "p99_latency_ms" : 7.470375, + "encrypt_latency_ms" : 3.3877333999999997, + "decrypt_latency_ms" : 3.2609667, + "timestamp" : "2025-09-09 12:02:56", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "throughput", + "data_size" : 10240, + "concurrency" : 1, + "operations_per_second" : 160.71722827453837, + "bytes_per_second" : 1645744.4175312729, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 6.2221083, + "p50_latency_ms" : 6.159917, + "p95_latency_ms" : 6.624958, + "p99_latency_ms" : 6.624958, + "encrypt_latency_ms" : 3.1598876000000002, + "decrypt_latency_ms" : 3.0491501, + "timestamp" : "2025-09-09 12:02:56", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "throughput", + "data_size" : 102400, + "concurrency" : 1, + "operations_per_second" : 85.80953331558563, + "bytes_per_second" : 8786896.211515969, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 11.653716800000002, + "p50_latency_ms" : 11.60425, + "p95_latency_ms" : 12.147792, + "p99_latency_ms" : 12.147792, + "encrypt_latency_ms" : 6.3010252, + "decrypt_latency_ms" : 5.3375958, + "timestamp" : "2025-09-09 12:02:56", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "throughput", + "data_size" : 512000, + "concurrency" : 1, + "operations_per_second" : 25.967202535119814, + "bytes_per_second" : 1.3295207697981345E7, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 38.510116700000005, + "p50_latency_ms" : 38.376625, + "p95_latency_ms" : 39.801, + "p99_latency_ms" : 39.801, + "encrypt_latency_ms" : 21.3460708, + "decrypt_latency_ms" : 17.1229875, + "timestamp" : "2025-09-09 12:02:57", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "throughput", + "data_size" : 1048576, + "concurrency" : 1, + "operations_per_second" : 12.474584313106936, + "bytes_per_second" : 1.3080549720700419E7, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 80.1629918, + "p50_latency_ms" : 74.872917, + "p95_latency_ms" : 97.101375, + "p99_latency_ms" : 97.101375, + "encrypt_latency_ms" : 43.5257208, + "decrypt_latency_ms" : 36.5108709, + "timestamp" : "2025-09-09 12:02:58", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "throughput", + "data_size" : 10000000, + "concurrency" : 1, + "operations_per_second" : 1.5477552230482363, + "bytes_per_second" : 1.5477552230482364E7, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 646.0969959, + "p50_latency_ms" : 642.796542, + "p95_latency_ms" : 678.216167, + "p99_latency_ms" : 678.216167, + "encrypt_latency_ms" : 360.73167520000004, + "decrypt_latency_ms" : 285.0051416, + "timestamp" : "2025-09-09 12:03:08", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "throughput", + "data_size" : 10485760, + "concurrency" : 1, + "operations_per_second" : 1.4945977297250002, + "bytes_per_second" : 1.5671993090441218E7, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 669.0763542, + "p50_latency_ms" : 667.506375, + "p95_latency_ms" : 682.568083, + "p99_latency_ms" : 682.568083, + "encrypt_latency_ms" : 374.82977500000004, + "decrypt_latency_ms" : 293.89182489999996, + "timestamp" : "2025-09-09 12:03:18", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "throughput", + "data_size" : 52428800, + "concurrency" : 1, + "operations_per_second" : 0.2992430474929217, + "bytes_per_second" : 1.5688953888396893E7, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 3341.7651918, + "p50_latency_ms" : 3338.38875, + "p95_latency_ms" : 3427.230292, + "p99_latency_ms" : 3427.230292, + "encrypt_latency_ms" : 1880.0336415000002, + "decrypt_latency_ms" : 1459.0504125, + "timestamp" : "2025-09-09 12:04:09", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "throughput", + "data_size" : 100000000, + "concurrency" : 1, + "operations_per_second" : 0.15802778407148096, + "bytes_per_second" : 1.5802778407148097E7, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 6328.0011542, + "p50_latency_ms" : 6310.039834, + "p95_latency_ms" : 6440.9085, + "p99_latency_ms" : 6440.9085, + "encrypt_latency_ms" : 3563.6736251, + "decrypt_latency_ms" : 2761.5854582, + "timestamp" : "2025-09-09 12:05:46", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "throughput", + "data_size" : 104857600, + "concurrency" : 1, + "operations_per_second" : 0.14976087811631936, + "bytes_per_second" : 1.570356625316977E7, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 6677.311275, + "p50_latency_ms" : 6664.984958, + "p95_latency_ms" : 6770.083792, + "p99_latency_ms" : 6770.083792, + "encrypt_latency_ms" : 3757.9571707000005, + "decrypt_latency_ms" : 2916.5672417, + "timestamp" : "2025-09-09 12:07:27", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.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" : 3.51812744140625, + "memory_efficiency_ratio" : 2.775801946531115E-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-09 12:07:28", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.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" : 4.0543975830078125, + "memory_efficiency_ratio" : 0.0012043250322721474, + "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-09 12:07:29", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.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" : 3.2662124633789062, + "memory_efficiency_ratio" : 0.0029898927609557377, + "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-09 12:07:29", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.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" : 5.965385437011719, + "memory_efficiency_ratio" : 0.016370484527973704, + "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-09 12:07:30", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.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" : 16.054359436035156, + "memory_efficiency_ratio" : 0.03041424679355427, + "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-09 12:07:31", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.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" : 36.000083923339844, + "memory_efficiency_ratio" : 0.027777713022265275, + "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-09 12:07:31", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 0 + }, { + "language" : "java", + "test_name" : "memory", + "data_size" : 10000000, + "concurrency" : 1, + "operations_per_second" : 0.0, + "bytes_per_second" : 0.0, + "peak_memory_mb" : 52.008575439453125, + "memory_efficiency_ratio" : 0.18336866725305523, + "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-09 12:07:35", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.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" : 51.10216522216797, + "memory_efficiency_ratio" : 0.1956864245678191, + "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-09 12:07:39", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.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" : 212.0059051513672, + "memory_efficiency_ratio" : 0.2358424873321391, + "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-09 12:07:57", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 0 + }, { + "language" : "java", + "test_name" : "memory", + "data_size" : 100000000, + "concurrency" : 1, + "operations_per_second" : 0.0, + "bytes_per_second" : 0.0, + "peak_memory_mb" : 388.0062561035156, + "memory_efficiency_ratio" : 0.24578838650267038, + "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-09 12:08:31", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.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" : 419.98480224609375, + "memory_efficiency_ratio" : 0.23810385391375216, + "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-09 12:09:07", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 0 + } ] +} \ No newline at end of file diff --git a/db-esdk-performance-testing/benchmarks/results/raw-data/java_results_10MBdata.json b/db-esdk-performance-testing/benchmarks/results/raw-data/java_results_10MBdata.json new file mode 100644 index 000000000..17f0b028e --- /dev/null +++ b/db-esdk-performance-testing/benchmarks/results/raw-data/java_results_10MBdata.json @@ -0,0 +1,851 @@ +{ + "metadata" : { + "language" : "java", + "timestamp" : "2025-09-08 16:47:05", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "total_tests" : 42 + }, + "results" : [ { + "language" : "java", + "test_name" : "throughput", + "data_size" : 1024, + "concurrency" : 1, + "operations_per_second" : 114.43617103987165, + "bytes_per_second" : 117182.63914482857, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 8.738495799999999, + "p50_latency_ms" : 7.87575, + "p95_latency_ms" : 15.502958, + "p99_latency_ms" : 15.502958, + "encrypt_latency_ms" : 3.8807543000000004, + "decrypt_latency_ms" : 4.840279300000001, + "timestamp" : "2025-09-08 16:46:20", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "throughput", + "data_size" : 5120, + "concurrency" : 1, + "operations_per_second" : 142.19374201644348, + "bytes_per_second" : 728031.9591241906, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 7.0326583, + "p50_latency_ms" : 7.044292, + "p95_latency_ms" : 7.397542, + "p99_latency_ms" : 7.397542, + "encrypt_latency_ms" : 3.4365, + "decrypt_latency_ms" : 3.5825332000000003, + "timestamp" : "2025-09-08 16:46:20", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "throughput", + "data_size" : 10240, + "concurrency" : 1, + "operations_per_second" : 152.49646162460093, + "bytes_per_second" : 1561563.7670359134, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 6.5575292, + "p50_latency_ms" : 6.484709, + "p95_latency_ms" : 7.240083, + "p99_latency_ms" : 7.240083, + "encrypt_latency_ms" : 3.2205416999999996, + "decrypt_latency_ms" : 3.3228082, + "timestamp" : "2025-09-08 16:46:20", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "throughput", + "data_size" : 102400, + "concurrency" : 1, + "operations_per_second" : 63.59790777383748, + "bytes_per_second" : 6512425.756040958, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 15.723787699999999, + "p50_latency_ms" : 12.931416, + "p95_latency_ms" : 38.401584, + "p99_latency_ms" : 38.401584, + "encrypt_latency_ms" : 8.52655, + "decrypt_latency_ms" : 7.1710335, + "timestamp" : "2025-09-08 16:46:20", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "throughput", + "data_size" : 512000, + "concurrency" : 1, + "operations_per_second" : 25.28969088006202, + "bytes_per_second" : 1.2948321730591755E7, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 39.541804, + "p50_latency_ms" : 39.252166, + "p95_latency_ms" : 40.548958, + "p99_latency_ms" : 40.548958, + "encrypt_latency_ms" : 22.0167292, + "decrypt_latency_ms" : 17.469662500000002, + "timestamp" : "2025-09-08 16:46:21", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "throughput", + "data_size" : 1048576, + "concurrency" : 1, + "operations_per_second" : 13.582811844816092, + "bytes_per_second" : 1.4242610512989879E7, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 73.6224584, + "p50_latency_ms" : 72.973708, + "p95_latency_ms" : 76.11475, + "p99_latency_ms" : 76.11475, + "encrypt_latency_ms" : 41.2115001, + "decrypt_latency_ms" : 32.3443501, + "timestamp" : "2025-09-08 16:46:22", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "throughput", + "data_size" : 10000000, + "concurrency" : 1, + "operations_per_second" : 1.5284864113360808, + "bytes_per_second" : 1.5284864113360807E7, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 654.2419956, + "p50_latency_ms" : 648.106666, + "p95_latency_ms" : 689.763791, + "p99_latency_ms" : 689.763791, + "encrypt_latency_ms" : 369.118229, + "decrypt_latency_ms" : 284.7368376, + "timestamp" : "2025-09-08 16:46:32", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.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" : 3.3156280517578125, + "memory_efficiency_ratio" : 2.945331879075718E-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-08 16:46:33", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.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" : 2.257843017578125, + "memory_efficiency_ratio" : 0.0021626005271338784, + "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-08 16:46:34", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.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" : 3.457855224609375, + "memory_efficiency_ratio" : 0.0028241856195998483, + "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-08 16:46:34", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.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" : 4.816246032714844, + "memory_efficiency_ratio" : 0.02027642469605164, + "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-08 16:46:35", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.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" : 15.407798767089844, + "memory_efficiency_ratio" : 0.031690526166718906, + "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-08 16:46:36", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.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" : 36.92132568359375, + "memory_efficiency_ratio" : 0.02708461794058378, + "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-08 16:46:36", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 0 + }, { + "language" : "java", + "test_name" : "memory", + "data_size" : 10000000, + "concurrency" : 1, + "operations_per_second" : 0.0, + "bytes_per_second" : 0.0, + "peak_memory_mb" : 52.01019287109375, + "memory_efficiency_ratio" : 0.18336296478844313, + "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-08 16:46:40", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 0 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 1024, + "concurrency" : 2, + "operations_per_second" : 179.75696750139633, + "bytes_per_second" : 184071.13472142984, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 5.563066699999999, + "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-08 16:46:40", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 1024, + "concurrency" : 4, + "operations_per_second" : 182.44180272971067, + "bytes_per_second" : 186820.40599522373, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 5.48119995, + "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-08 16:46:40", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 20 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 1024, + "concurrency" : 8, + "operations_per_second" : 148.7957303124705, + "bytes_per_second" : 152366.8278399698, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 6.720622950000001, + "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-08 16:46:40", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 40 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 1024, + "concurrency" : 16, + "operations_per_second" : 138.87402020689902, + "bytes_per_second" : 142206.9966918646, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 7.200770875000001, + "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-08 16:46:41", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 80 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 5120, + "concurrency" : 2, + "operations_per_second" : 168.60835201808936, + "bytes_per_second" : 863274.7623326175, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 5.9309043, + "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-08 16:46:41", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 5120, + "concurrency" : 4, + "operations_per_second" : 169.1067931382551, + "bytes_per_second" : 865826.7808678662, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 5.913423, + "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-08 16:46:41", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 20 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 5120, + "concurrency" : 8, + "operations_per_second" : 131.33023555075857, + "bytes_per_second" : 672410.8060198838, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 7.6143928, + "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-08 16:46:41", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 40 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 5120, + "concurrency" : 16, + "operations_per_second" : 105.80449559836701, + "bytes_per_second" : 541719.0174636391, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 9.4513942375, + "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-08 16:46:41", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 80 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 10240, + "concurrency" : 2, + "operations_per_second" : 163.6512853605628, + "bytes_per_second" : 1675789.1620921632, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 6.1105539, + "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-08 16:46:42", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 10240, + "concurrency" : 4, + "operations_per_second" : 151.44253711318964, + "bytes_per_second" : 1550771.580039062, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 6.6031645999999995, + "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-08 16:46:42", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 20 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 10240, + "concurrency" : 8, + "operations_per_second" : 129.70191617038958, + "bytes_per_second" : 1328147.6215847894, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 7.709986325, + "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-08 16:46:42", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 40 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 10240, + "concurrency" : 16, + "operations_per_second" : 78.00538278289041, + "bytes_per_second" : 798775.1196967978, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 12.8196281375, + "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-08 16:46:42", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 80 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 102400, + "concurrency" : 2, + "operations_per_second" : 77.9955140412126, + "bytes_per_second" : 7986740.63782017, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 12.8212502, + "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-08 16:46:42", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 102400, + "concurrency" : 4, + "operations_per_second" : 75.83197209256029, + "bytes_per_second" : 7765193.942278174, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 13.1870499, + "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-08 16:46:42", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 20 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 102400, + "concurrency" : 8, + "operations_per_second" : 68.21811219428038, + "bytes_per_second" : 6985534.688694311, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 14.658863575000002, + "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-08 16:46:43", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 40 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 102400, + "concurrency" : 16, + "operations_per_second" : 47.46238907645142, + "bytes_per_second" : 4860148.641428626, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 21.06931445, + "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-08 16:46:43", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 80 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 512000, + "concurrency" : 2, + "operations_per_second" : 24.597117237045566, + "bytes_per_second" : 1.259372402536733E7, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 40.6551707, + "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-08 16:46:43", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 512000, + "concurrency" : 4, + "operations_per_second" : 24.22039219935766, + "bytes_per_second" : 1.2400840806071123E7, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 41.287523, + "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-08 16:46:43", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 20 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 512000, + "concurrency" : 8, + "operations_per_second" : 21.207543374301284, + "bytes_per_second" : 1.0858262207642257E7, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 47.15303335, + "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-08 16:46:44", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 40 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 512000, + "concurrency" : 16, + "operations_per_second" : 12.701903282243414, + "bytes_per_second" : 6503374.480508628, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 78.728358875, + "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-08 16:46:44", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 80 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 1048576, + "concurrency" : 2, + "operations_per_second" : 13.398087074183973, + "bytes_per_second" : 1.4048912551899534E7, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 74.63752059999999, + "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-08 16:46:45", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 1048576, + "concurrency" : 4, + "operations_per_second" : 13.02752980594925, + "bytes_per_second" : 1.366035509380304E7, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 76.7605229, + "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-08 16:46:45", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 20 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 1048576, + "concurrency" : 8, + "operations_per_second" : 11.442604144627765, + "bytes_per_second" : 1.1998440083557203E7, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 87.392693775, + "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-08 16:46:46", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 40 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 1048576, + "concurrency" : 16, + "operations_per_second" : 6.566227623799001, + "bytes_per_second" : 6885188.696852662, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 152.2944462625, + "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-08 16:46:47", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 80 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 10000000, + "concurrency" : 2, + "operations_per_second" : 1.5271685382817055, + "bytes_per_second" : 1.5271685382817056E7, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 654.806575, + "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-08 16:46:50", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 10 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 10000000, + "concurrency" : 4, + "operations_per_second" : 1.4978267092763307, + "bytes_per_second" : 1.4978267092763307E7, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 667.63397515, + "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-08 16:46:54", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 20 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 10000000, + "concurrency" : 8, + "operations_per_second" : 1.3425611721051591, + "bytes_per_second" : 1.342561172105159E7, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 744.8450177, + "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-08 16:46:58", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 40 + }, { + "language" : "java", + "test_name" : "concurrent", + "data_size" : 10000000, + "concurrency" : 16, + "operations_per_second" : 0.7310966037322482, + "bytes_per_second" : 7310966.037322481, + "peak_memory_mb" : 0.0, + "memory_efficiency_ratio" : 0.0, + "avg_latency_ms" : 1367.8082963250001, + "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-08 16:47:05", + "java_version" : "17.0.16", + "cpu_count" : 10, + "total_memory_gb" : 8.0, + "iterations" : 80 + } ] +} \ No newline at end of file