Skip to content

Commit 5061901

Browse files
committed
updated performance comparison logic
1 parent 8e7ce75 commit 5061901

File tree

2 files changed

+107
-44
lines changed

2 files changed

+107
-44
lines changed

test/http-client-benchmarks/README.md

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,55 @@
1-
# Sdk Benchmark Harness
1+
````markdown
2+
# HTTP Client Benchmark Harness
23

3-
4-
This module contains sdk benchmark harness using [JMH].
4+
This module contains HTTP client benchmark harness using [JMH].
55

66
Each benchmark class has a set of default
7-
JMH configurations tailored to SDK's build job and you might need to
7+
JMH configurations tailored to HTTP client performance testing and you might need to
88
adjust them based on your test environment such as increasing warmup iterations
99
or measurement time in order to get more reliable data.
1010

1111
There are three ways to run benchmarks.
1212

1313
- Using the executable JAR (Preferred usage per JMH site)
1414
```bash
15-
mvn clean install -P quick -pl :sdk-benchmarks --am
15+
mvn clean install -P quick -pl :http-client-benchmarks --am
1616

1717
# Run specific benchmark
18-
java -jar target/benchmarks.jar ApacheHttpClientBenchmark
18+
java -jar target/benchmarks.jar Apache5Benchmark
1919

2020
# Run all benchmarks: 3 warm up iterations, 3 benchmark iterations, 1 fork
2121
java -jar target/benchmarks.jar -wi 3 -i 3 -f 1
2222
```
2323

24-
- Using`mvn exec:exec` commands to invoke `UnifiedBenchmarkRunner` main method
24+
- Using `mvn exec:exec` commands to invoke `UnifiedBenchmarkRunner` main method
2525
```bash
26-
mvn clean install -P quick -pl :sdk-benchmarks --am
27-
mvn clean install -pl :bom-internal
28-
cd test/sdk-benchmarks
29-
mvn exec:exec
26+
mvn clean install -P quick -pl :http-client-benchmarks --am
27+
mvn clean install -pl :bom-internal
28+
cd test/http-client-benchmarks
29+
mvn exec:exec
3030
```
3131

3232
- From IDE
3333

34-
You can run the main method within each Benchmark class from your IDE. If you are using Eclipse, you might need to
35-
set up build configurations for JMH annotation, please check [JMH]. Note that the benchmark result from IDE
36-
might not be as reliable as the above approaches and is generally not recommended.
37-
34+
You can run the main method within `UnifiedBenchmarkRunner` class from your IDE to execute all benchmark comparisons, or run individual benchmark classes like `Apache4Benchmark` and `Apache5Benchmark`. If you are using Eclipse, you might need to set up build configurations for JMH annotation, please check [JMH]. Note that the benchmark result from IDE might not be as reliable as the above approaches and is generally not recommended.
35+
36+
## UnifiedBenchmarkRunner
37+
38+
The `UnifiedBenchmarkRunner` provides a comprehensive comparison between different HTTP client implementations:
39+
40+
- **Apache4**: Apache HttpClient 4.x baseline
41+
- **Apache5-Platform**: Apache HttpClient 5.x with platform threads
42+
- **Apache5-Virtual**: Apache HttpClient 5.x with virtual threads
43+
44+
The runner executes all benchmark variations, publishes metrics to CloudWatch, and generates a detailed comparison report showing performance improvements between implementations.
45+
46+
## Benchmark Operations
47+
48+
Each benchmark implementation tests the following operations:
49+
- `simpleGet`: Single-threaded GET operations
50+
- `simplePut`: Single-threaded PUT operations
51+
- `multiThreadedGet`: Multi-threaded GET operations (10 threads)
52+
- `multiThreadedPut`: Multi-threaded PUT operations (10 threads)
53+
3854
[JMH]: http://openjdk.java.net/projects/code-tools/jmh/
55+
````

test/http-client-benchmarks/src/main/java/software/amazon/awssdk/benchmark/UnifiedBenchmarkRunner.java

Lines changed: 75 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,7 @@ public class UnifiedBenchmarkRunner {
3939
public static void main(String[] args) throws Exception {
4040
logger.info("Starting unified benchmark comparison");
4141

42-
// Generate unique run ID with timestamp
4342
String runId = Instant.now().toString();
44-
45-
// Initialize CloudWatch publisher
4643
CloudWatchMetricsPublisher publisher = new CloudWatchMetricsPublisher(
4744
Region.US_WEST_2,
4845
"S3-HTTP-Client-Comparison"
@@ -63,13 +60,20 @@ public static void main(String[] args) throws Exception {
6360
logger.info("Running Apache5 with virtual threads...");
6461
allResults.addAll(runBenchmark("Apache5-Virtual", Apache5Benchmark.class, "virtual"));
6562

66-
// Publish all results to CloudWatch with synchronized timestamp
63+
// Debug: Print all results to understand the structure
64+
logger.info("All benchmark results:");
65+
for (BenchmarkResult result : allResults) {
66+
logger.info(String.format("Client: %s, Benchmark: %s, Throughput: %.2f",
67+
result.getClientType(), result.getBenchmarkName(), result.getThroughput()));
68+
}
69+
70+
// Publish results to CloudWatch
6771
logger.info("Publishing results to CloudWatch...");
6872
for (BenchmarkResult result : allResults) {
6973
publisher.publishBenchmarkResult(result, runId);
7074
}
7175

72-
// Print comparison report to console
76+
// Print comparison report
7377
printComparisonReport(allResults);
7478

7579
logger.info("\nBenchmark complete! CloudWatch metrics published with run ID: " + runId);
@@ -89,7 +93,6 @@ private static List<BenchmarkResult> runBenchmark(String clientType,
8993
.warmupIterations(2)
9094
.measurementIterations(3);
9195

92-
// Add executor type parameter for Apache5
9396
if (executorType != null) {
9497
optBuilder.param("executorType", executorType);
9598
}
@@ -105,13 +108,20 @@ private static List<BenchmarkResult> runBenchmark(String clientType,
105108
private static BenchmarkResult convertToBenchmarkResult(String clientType,
106109
RunResult runResult) {
107110
String fullBenchmarkName = runResult.getPrimaryResult().getLabel();
108-
String benchmarkName = fullBenchmarkName.substring(fullBenchmarkName.lastIndexOf('.') + 1);
111+
112+
// Extract just the method name (everything after the last dot)
113+
String benchmarkName = fullBenchmarkName;
114+
if (fullBenchmarkName.contains(".")) {
115+
benchmarkName = fullBenchmarkName.substring(fullBenchmarkName.lastIndexOf('.') + 1);
116+
}
117+
118+
// Log for debugging
119+
logger.info(String.format("Converting: %s -> %s", fullBenchmarkName, benchmarkName));
109120

110121
double throughput = runResult.getPrimaryResult().getScore();
111-
double avgLatency = 1000.0 / throughput; // Convert to ms
112-
double p99Latency = avgLatency * 1.5; // Estimate
122+
double avgLatency = 1000.0 / throughput;
123+
double p99Latency = avgLatency * 1.5;
113124

114-
// Determine thread count from benchmark name
115125
int threadCount = benchmarkName.contains("multiThreaded") ? 10 : 1;
116126

117127
return new BenchmarkResult(
@@ -139,25 +149,51 @@ private static void printComparisonReport(List<BenchmarkResult> results) {
139149
)
140150
));
141151

142-
// Print results table
143-
System.out.printf("%-20s %-15s %-15s %-15s %-15s%n",
144-
"Client Type", "Simple GET", "Simple PUT", "MT GET (10t)", "MT PUT (10t)");
145-
System.out.println("-".repeat(80));
152+
// Print the structure we actually have , to view it on console
153+
System.out.println("Available results structure:");
154+
for (Map.Entry<String, Map<String, BenchmarkResult>> entry : grouped.entrySet()) {
155+
System.out.println("Client: " + entry.getKey());
156+
for (String benchmarkName : entry.getValue().keySet()) {
157+
System.out.println(" - " + benchmarkName);
158+
}
159+
}
160+
System.out.println();
161+
162+
// Get all unique benchmark names across all clients
163+
Set<String> allBenchmarkNames = grouped.values().stream()
164+
.flatMap(map -> map.keySet().stream())
165+
.collect(Collectors.toSet());
166+
167+
// Print results table with dynamic columns
168+
System.out.printf("%-20s", "Client Type");
169+
for (String benchmarkName : allBenchmarkNames) {
170+
System.out.printf(" %-15s", benchmarkName);
171+
}
172+
System.out.println();
173+
System.out.println("-".repeat(20 + (allBenchmarkNames.size() * 16)));
146174

147175
for (String clientType : Arrays.asList("Apache4", "Apache5-Platform", "Apache5-Virtual")) {
148176
Map<String, BenchmarkResult> clientResults = grouped.get(clientType);
149177
if (clientResults != null) {
150-
System.out.printf("%-20s %-15.2f %-15.2f %-15.2f %-15.2f%n",
151-
clientType,
152-
clientResults.get("simpleGet").getThroughput(),
153-
clientResults.get("simplePut").getThroughput(),
154-
clientResults.get("multiThreadedGet").getThroughput(),
155-
clientResults.get("multiThreadedPut").getThroughput()
156-
);
178+
System.out.printf("%-20s", clientType);
179+
for (String benchmarkName : allBenchmarkNames) {
180+
BenchmarkResult result = clientResults.get(benchmarkName);
181+
if (result != null) {
182+
System.out.printf(" %-15.2f", result.getThroughput());
183+
} else {
184+
System.out.printf(" %-15s", "N/A");
185+
}
186+
}
187+
System.out.println();
157188
}
158189
}
159190

160-
// Print performance improvements
191+
// Print performance improvements (only if we have matching benchmarks)
192+
printPerformanceImprovements(grouped);
193+
System.out.println("\n" + "=".repeat(80));
194+
}
195+
196+
private static void printPerformanceImprovements(Map<String, Map<String, BenchmarkResult>> grouped) {
161197
System.out.println("\n" + "=".repeat(80));
162198
System.out.println("PERFORMANCE IMPROVEMENTS");
163199
System.out.println("=".repeat(80));
@@ -180,17 +216,27 @@ private static void printComparisonReport(List<BenchmarkResult> results) {
180216
System.out.println("\nApache5 (Virtual) vs Apache4:");
181217
printImprovements(apache4, apache5Virtual);
182218
}
183-
184-
System.out.println("\n" + "=".repeat(80));
185219
}
186220

187221
private static void printImprovements(Map<String, BenchmarkResult> baseline,
188222
Map<String, BenchmarkResult> comparison) {
189-
for (String op : Arrays.asList("simpleGet", "simplePut",
190-
"multiThreadedGet", "multiThreadedPut")) {
191-
double improvement = (comparison.get(op).getThroughput() /
192-
baseline.get(op).getThroughput() - 1) * 100;
193-
System.out.printf(" %-20s: %+.1f%%%n", op, improvement);
223+
// Find common benchmark names
224+
Set<String> commonBenchmarks = new HashSet<>(baseline.keySet());
225+
commonBenchmarks.retainAll(comparison.keySet());
226+
227+
if (commonBenchmarks.isEmpty()) {
228+
System.out.println(" No common benchmarks found for comparison");
229+
return;
230+
}
231+
232+
for (String benchmarkName : commonBenchmarks) {
233+
BenchmarkResult baseResult = baseline.get(benchmarkName);
234+
BenchmarkResult compResult = comparison.get(benchmarkName);
235+
236+
if (baseResult != null && compResult != null) {
237+
double improvement = (compResult.getThroughput() / baseResult.getThroughput() - 1) * 100;
238+
System.out.printf(" %-20s: %+.1f%%%n", benchmarkName, improvement);
239+
}
194240
}
195241
}
196242
}

0 commit comments

Comments
 (0)