From 36ca8df24b2a6005231f3ebc2cb09943b3089ad2 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Tue, 10 Mar 2026 14:27:35 -0700 Subject: [PATCH 1/7] Add isolated protocol ser/de benchmarks for V1 vs V2 Benchmarks for all 6 AWS protocol types measuring serialization and deserialization in isolation (no HTTP, signing, or retries): - JSON (DynamoDB PutItem) - REST-JSON (Lambda CreateFunction) - REST-XML (CloudFront CreateDistribution) - Query (STS AssumeRole) - EC2 (EC2 DescribeInstances) - CBOR (CloudWatch GetMetricData) Each protocol has a V1 and V2 benchmark class with @Benchmark methods for both ser and deser, using the same JMH configuration and fixture data for fair comparison. --- .../amazon/awssdk/checkstyle-suppressions.xml | 4 + test/sdk-benchmarks/pom.xml | 42 +++- .../protocol/V1CborProtocolBenchmark.java | 140 ++++++++++++ .../protocol/V1Ec2ProtocolBenchmark.java | 98 ++++++++ .../protocol/V1JsonProtocolBenchmark.java | 125 +++++++++++ .../protocol/V1QueryProtocolBenchmark.java | 97 ++++++++ .../protocol/V1RestJsonProtocolBenchmark.java | 124 +++++++++++ .../protocol/V1RestXmlProtocolBenchmark.java | 138 ++++++++++++ .../protocol/V2CborProtocolBenchmark.java | 178 +++++++++++++++ .../protocol/V2Ec2ProtocolBenchmark.java | 117 ++++++++++ .../protocol/V2JsonProtocolBenchmark.java | 151 +++++++++++++ .../protocol/V2QueryProtocolBenchmark.java | 117 ++++++++++ .../protocol/V2RestJsonProtocolBenchmark.java | 153 +++++++++++++ .../protocol/V2RestXmlProtocolBenchmark.java | 154 +++++++++++++ .../describe-instances-response.xml | 37 ++++ .../json-protocol/putitem-response.json | 24 ++ .../query-protocol/assumerole-response.xml | 19 ++ .../createfunction-response.json | 43 ++++ .../create-distribution-response.xml | 209 ++++++++++++++++++ 19 files changed, 1969 insertions(+), 1 deletion(-) create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1CborProtocolBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1Ec2ProtocolBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1JsonProtocolBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1QueryProtocolBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1RestJsonProtocolBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1RestXmlProtocolBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2CborProtocolBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2Ec2ProtocolBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2JsonProtocolBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2QueryProtocolBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2RestJsonProtocolBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2RestXmlProtocolBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/resources/fixtures/ec2-protocol/describe-instances-response.xml create mode 100644 test/sdk-benchmarks/src/main/resources/fixtures/json-protocol/putitem-response.json create mode 100644 test/sdk-benchmarks/src/main/resources/fixtures/query-protocol/assumerole-response.xml create mode 100644 test/sdk-benchmarks/src/main/resources/fixtures/rest-json-protocol/createfunction-response.json create mode 100644 test/sdk-benchmarks/src/main/resources/fixtures/rest-xml-protocol/create-distribution-response.xml diff --git a/build-tools/src/main/resources/software/amazon/awssdk/checkstyle-suppressions.xml b/build-tools/src/main/resources/software/amazon/awssdk/checkstyle-suppressions.xml index 17c617c0d12b..ab1f3ade8258 100644 --- a/build-tools/src/main/resources/software/amazon/awssdk/checkstyle-suppressions.xml +++ b/build-tools/src/main/resources/software/amazon/awssdk/checkstyle-suppressions.xml @@ -50,6 +50,10 @@ + + + diff --git a/test/sdk-benchmarks/pom.xml b/test/sdk-benchmarks/pom.xml index 4f0a47cfc17a..983d5badbfd9 100644 --- a/test/sdk-benchmarks/pom.xml +++ b/test/sdk-benchmarks/pom.xml @@ -47,7 +47,7 @@ --> benchmarks - 1.11.404 + 1.12.797 1.6.0 @@ -87,18 +87,58 @@ aws-java-sdk-ec2 ${sdk-v1.version} + + com.amazonaws + aws-java-sdk-cloudfront + ${sdk-v1.version} + + + com.amazonaws + aws-java-sdk-sts + ${sdk-v1.version} + + + com.amazonaws + aws-java-sdk-lambda + ${sdk-v1.version} + + + com.amazonaws + aws-java-sdk-cloudwatch + ${sdk-v1.version} + software.amazon.awssdk ec2 ${awsjavasdk.version} + + software.amazon.awssdk + cloudfront + ${awsjavasdk.version} + + + software.amazon.awssdk + sts + ${awsjavasdk.version} + + + software.amazon.awssdk + lambda + ${awsjavasdk.version} + software.amazon.awssdk aws-query-protocol ${awsjavasdk.version} + + software.amazon.awssdk + smithy-rpcv2-protocol + ${awsjavasdk.version} + software.amazon.awssdk diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1CborProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1CborProtocolBenchmark.java new file mode 100644 index 000000000000..5b0e1e59a3dc --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1CborProtocolBenchmark.java @@ -0,0 +1,140 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.protocol; + +import com.amazonaws.protocol.rpcv2cbor.RpcV2CborClientMetadata; +import com.amazonaws.protocol.rpcv2cbor.SdkRpcV2CborProtocolFactory; +import com.amazonaws.protocol.rpcv2cbor.SdkStructuredCborFactory; +import com.amazonaws.protocol.rpcv2cbor.StructuredRpcV2CborGenerator; +import com.amazonaws.services.cloudwatch.model.GetMetricDataRequest; +import com.amazonaws.services.cloudwatch.model.Metric; +import com.amazonaws.services.cloudwatch.model.MetricDataQuery; +import com.amazonaws.services.cloudwatch.model.MetricStat; +import com.amazonaws.services.cloudwatch.model.transform.GetMetricDataRequestProtocolMarshaller; +import com.amazonaws.services.cloudwatch.model.transform.GetMetricDataResultRpcV2CborUnmarshaller; +import com.amazonaws.transform.rpcv2cbor.RpcV2CborUnmarshallerContextImpl; +import com.fasterxml.jackson.dataformat.cbor.CBORFactory; +import com.fasterxml.jackson.dataformat.cbor.CBORParser; +import java.util.Date; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +/** + * Isolated ser/de benchmark for V1 CloudWatch (smithy-rpc-v2-cbor protocol). + * Measures only CBOR parsing + object construction -- no HTTP, signing, or retries. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.SampleTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +public class V1CborProtocolBenchmark { + + private static final CBORFactory CBOR_FACTORY = new CBORFactory(); + + private SdkRpcV2CborProtocolFactory protocolFactory; + private byte[] responseBytes; + private GetMetricDataRequest request; + + @Setup + public void setup() throws Exception { + protocolFactory = new SdkRpcV2CborProtocolFactory(new RpcV2CborClientMetadata()); + responseBytes = createCborResponseFixture(); + request = createRequest(); + } + + @Benchmark + public void getMetricDataDeser(Blackhole bh) throws Exception { + CBORParser parser = CBOR_FACTORY.createParser(responseBytes); + RpcV2CborUnmarshallerContextImpl ctx = new RpcV2CborUnmarshallerContextImpl( + parser, SdkStructuredCborFactory.CBOR_SCALAR_UNMARSHALLERS, null); + ctx.nextToken(); + bh.consume(GetMetricDataResultRpcV2CborUnmarshaller.getInstance().unmarshall(ctx)); + } + + @Benchmark + public void getMetricDataSer(Blackhole bh) { + bh.consume(new GetMetricDataRequestProtocolMarshaller(protocolFactory).marshall(request)); + } + + private static GetMetricDataRequest createRequest() { + Date end = Date.from(java.time.Instant.parse("2026-03-09T00:00:00Z")); + Date start = Date.from(java.time.Instant.parse("2026-03-09T00:00:00Z").minusSeconds(3600)); + return new GetMetricDataRequest() + .withStartTime(start) + .withEndTime(end) + .withMaxDatapoints(1000) + .withMetricDataQueries( + new MetricDataQuery() + .withId("cpu") + .withMetricStat(new MetricStat() + .withMetric(new Metric() + .withNamespace("AWS/EC2") + .withMetricName("CPUUtilization")) + .withPeriod(300) + .withStat("Average")) + .withReturnData(true)); + } + + private static byte[] createCborResponseFixture() { + StructuredRpcV2CborGenerator gen = + SdkStructuredCborFactory.SDK_CBOR_FACTORY.createWriter("application/cbor"); + gen.writeStartObject(); + gen.writeFieldName("MetricDataResults"); + gen.writeStartArray(); + gen.writeStartObject(); + gen.writeFieldName("Id"); + gen.writeValue("cpu"); + gen.writeFieldName("Label"); + gen.writeValue("CPUUtilization"); + gen.writeFieldName("StatusCode"); + gen.writeValue("Complete"); + gen.writeFieldName("Timestamps"); + gen.writeStartArray(); + long base = 1772611200L; + for (int i = 0; i < 12; i++) { + gen.writeValue((double) ((base + i * 300) * 1000)); + } + gen.writeEndArray(); + gen.writeFieldName("Values"); + gen.writeStartArray(); + for (int i = 0; i < 12; i++) { + gen.writeValue(45.2 + i * 1.1); + } + gen.writeEndArray(); + gen.writeFieldName("Messages"); + gen.writeStartArray(); + gen.writeEndArray(); + gen.writeEndObject(); + gen.writeEndArray(); + gen.writeFieldName("Messages"); + gen.writeStartArray(); + gen.writeEndArray(); + gen.writeEndObject(); + return gen.getBytes(); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1Ec2ProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1Ec2ProtocolBenchmark.java new file mode 100644 index 000000000000..82d8e01d7bd7 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1Ec2ProtocolBenchmark.java @@ -0,0 +1,98 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.protocol; + +import com.amazonaws.services.ec2.model.DescribeInstancesRequest; +import com.amazonaws.services.ec2.model.Filter; +import com.amazonaws.services.ec2.model.transform.DescribeInstancesRequestMarshaller; +import com.amazonaws.services.ec2.model.transform.DescribeInstancesResultStaxUnmarshaller; +import com.amazonaws.transform.StaxUnmarshallerContext; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +/** + * Isolated ser/de benchmark for V1 EC2 (EC2 Query protocol). + * Measures only XML parsing + form encoding -- no HTTP, signing, or retries. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.SampleTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +public class V1Ec2ProtocolBenchmark { + + private static final XMLInputFactory XML_INPUT_FACTORY = + XMLInputFactory.newInstance(); + + private byte[] responseBytes; + private Map responseHeaders; + private DescribeInstancesRequestMarshaller marshaller; + private DescribeInstancesRequest request; + + @Setup + public void setup() throws Exception { + responseBytes = loadFixture("fixtures/ec2-protocol/describe-instances-response.xml"); + responseHeaders = new HashMap<>(); + marshaller = new DescribeInstancesRequestMarshaller(); + request = createRequest(); + } + + @Benchmark + public void describeInstancesDeser(Blackhole bh) throws Exception { + XMLEventReader reader = XML_INPUT_FACTORY.createXMLEventReader(new ByteArrayInputStream(responseBytes)); + StaxUnmarshallerContext ctx = new StaxUnmarshallerContext(reader, responseHeaders); + ctx.registerMetadataExpression("ResponseMetadata/RequestId", 2, "AWS_REQUEST_ID"); + + bh.consume(DescribeInstancesResultStaxUnmarshaller.getInstance().unmarshall(ctx)); + } + + @Benchmark + public void describeInstancesSer(Blackhole bh) { + bh.consume(marshaller.marshall(request)); + } + + private static DescribeInstancesRequest createRequest() { + return new DescribeInstancesRequest() + .withInstanceIds("i-0abcdef1234567890") + .withFilters( + new Filter("instance-state-name").withValues("running"), + new Filter("instance-type").withValues("m5.xlarge")) + .withMaxResults(100); + } + + private static byte[] loadFixture(String path) throws IOException { + return com.amazonaws.util.IOUtils.toByteArray( + V1Ec2ProtocolBenchmark.class.getClassLoader() + .getResourceAsStream(path)); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1JsonProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1JsonProtocolBenchmark.java new file mode 100644 index 000000000000..5cf300685a02 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1JsonProtocolBenchmark.java @@ -0,0 +1,125 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.protocol; + +import com.amazonaws.http.HttpResponse; +import com.amazonaws.protocol.json.JsonClientMetadata; +import com.amazonaws.protocol.json.SdkJsonProtocolFactory; +import com.amazonaws.protocol.json.SdkStructuredPlainJsonFactory; +import com.amazonaws.services.dynamodbv2.model.AttributeValue; +import com.amazonaws.services.dynamodbv2.model.PutItemRequest; +import com.amazonaws.services.dynamodbv2.model.transform.PutItemRequestProtocolMarshaller; +import com.amazonaws.services.dynamodbv2.model.transform.PutItemResultJsonUnmarshaller; +import com.amazonaws.transform.JsonUnmarshallerContextImpl; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +/** + * Isolated ser/de benchmark for V1 DynamoDB (JSON protocol). + * Measures only JSON parsing + object construction -- no HTTP, signing, or retries. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.SampleTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +public class V1JsonProtocolBenchmark { + + private static final JsonFactory JSON_FACTORY = new JsonFactory(); + private byte[] putItemResponseBytes; + private HttpResponse httpResponse; + private SdkJsonProtocolFactory protocolFactory; + private PutItemRequest putItemRequest; + + @Setup + public void setup() throws Exception { + putItemResponseBytes = loadFixture("fixtures/json-protocol/putitem-response.json"); + httpResponse = new HttpResponse(null, null); + httpResponse.setStatusCode(200); + protocolFactory = new SdkJsonProtocolFactory( + new JsonClientMetadata().withProtocolVersion("1.0")); + putItemRequest = new PutItemRequest() + .withTableName("benchmark-table") + .withItem(itemMap()); + } + + @Benchmark + public void putItemDeser(Blackhole bh) throws Exception { + JsonParser parser = JSON_FACTORY.createParser(new ByteArrayInputStream(putItemResponseBytes)); + JsonUnmarshallerContextImpl ctx = new JsonUnmarshallerContextImpl(parser, + SdkStructuredPlainJsonFactory.JSON_SCALAR_UNMARSHALLERS, + SdkStructuredPlainJsonFactory.JSON_CUSTOM_TYPE_UNMARSHALLERS, + httpResponse); + + bh.consume(PutItemResultJsonUnmarshaller.getInstance().unmarshall(ctx)); + } + + @Benchmark + public void putItemSer(Blackhole bh) { + bh.consume(new PutItemRequestProtocolMarshaller(protocolFactory).marshall(putItemRequest)); + } + + private static Map itemMap() { + Map item = new HashMap(); + item.put("pk", new AttributeValue().withS("benchmark-key")); + item.put("sk", new AttributeValue().withN("100")); + item.put("stringField", new AttributeValue().withS("test-value")); + item.put("numberField", new AttributeValue().withN("123.456")); + item.put("binaryField", new AttributeValue() + .withB(ByteBuffer.wrap("hello world".getBytes()))); + item.put("stringSetField", new AttributeValue() + .withSS("value1", "value2", "value3")); + item.put("numberSetField", new AttributeValue() + .withNS("1.1", "2.2", "3.3")); + item.put("boolField", new AttributeValue().withBOOL(false)); + item.put("nullField", new AttributeValue().withNULL(true)); + Map deep = new HashMap(); + deep.put("level2", new AttributeValue().withN("999")); + Map nested = new HashMap(); + nested.put("nested", new AttributeValue().withS("nested-value")); + nested.put("deepNested", new AttributeValue().withM(deep)); + item.put("mapField", new AttributeValue().withM(nested)); + item.put("listField", new AttributeValue().withL( + new AttributeValue().withS("item1"), + new AttributeValue().withN("42"), + new AttributeValue().withBOOL(true), + new AttributeValue().withNULL(true))); + return item; + } + + private static byte[] loadFixture(String path) throws IOException { + return com.amazonaws.util.IOUtils.toByteArray( + V1JsonProtocolBenchmark.class.getClassLoader().getResourceAsStream(path)); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1QueryProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1QueryProtocolBenchmark.java new file mode 100644 index 000000000000..1f004d209b85 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1QueryProtocolBenchmark.java @@ -0,0 +1,97 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.protocol; + +import com.amazonaws.services.securitytoken.model.AssumeRoleRequest; +import com.amazonaws.services.securitytoken.model.transform.AssumeRoleRequestMarshaller; +import com.amazonaws.services.securitytoken.model.transform.AssumeRoleResultStaxUnmarshaller; +import com.amazonaws.transform.StaxUnmarshallerContext; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +/** + * Isolated ser/de benchmark for V1 STS (Query protocol). + * Measures only XML parsing + form encoding -- no HTTP, signing, or retries. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.SampleTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +public class V1QueryProtocolBenchmark { + + private static final XMLInputFactory XML_INPUT_FACTORY = + XMLInputFactory.newInstance(); + + private byte[] responseBytes; + private Map responseHeaders; + private AssumeRoleRequestMarshaller marshaller; + private AssumeRoleRequest request; + + @Setup + public void setup() throws Exception { + responseBytes = loadFixture("fixtures/query-protocol/assumerole-response.xml"); + responseHeaders = new HashMap<>(); + marshaller = new AssumeRoleRequestMarshaller(); + request = createRequest(); + } + + @Benchmark + public void assumeRoleDeser(Blackhole bh) throws Exception { + XMLEventReader reader = XML_INPUT_FACTORY.createXMLEventReader(new ByteArrayInputStream(responseBytes)); + StaxUnmarshallerContext ctx = new StaxUnmarshallerContext(reader, responseHeaders); + ctx.registerMetadataExpression("ResponseMetadata/RequestId", 2, "AWS_REQUEST_ID"); + + bh.consume(AssumeRoleResultStaxUnmarshaller.getInstance().unmarshall(ctx)); + } + + @Benchmark + public void assumeRoleSer(Blackhole bh) { + bh.consume(marshaller.marshall(request)); + } + + private static AssumeRoleRequest createRequest() { + return new AssumeRoleRequest() + .withRoleArn("arn:aws:iam::123456789012:role/benchmark-role") + .withRoleSessionName("benchmark-session") + .withDurationSeconds(3600) + .withExternalId("benchmark-external-id") + .withPolicy("{\"Version\":\"2012-10-17\"}"); + } + + private static byte[] loadFixture(String path) throws IOException { + return com.amazonaws.util.IOUtils.toByteArray( + V1QueryProtocolBenchmark.class.getClassLoader() + .getResourceAsStream(path)); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1RestJsonProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1RestJsonProtocolBenchmark.java new file mode 100644 index 000000000000..c2a48bd076d2 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1RestJsonProtocolBenchmark.java @@ -0,0 +1,124 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.protocol; + +import com.amazonaws.http.HttpResponse; +import com.amazonaws.protocol.json.JsonClientMetadata; +import com.amazonaws.protocol.json.SdkJsonProtocolFactory; +import com.amazonaws.protocol.json.SdkStructuredPlainJsonFactory; +import com.amazonaws.services.lambda.model.CreateFunctionRequest; +import com.amazonaws.services.lambda.model.Environment; +import com.amazonaws.services.lambda.model.FunctionCode; +import com.amazonaws.services.lambda.model.Runtime; +import com.amazonaws.services.lambda.model.TracingConfig; +import com.amazonaws.services.lambda.model.TracingMode; +import com.amazonaws.services.lambda.model.transform.CreateFunctionRequestProtocolMarshaller; +import com.amazonaws.services.lambda.model.transform.CreateFunctionResultJsonUnmarshaller; +import com.amazonaws.transform.JsonUnmarshallerContextImpl; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +/** + * Isolated ser/de benchmark for V1 Lambda (REST-JSON protocol). + * Measures only JSON parsing + object construction -- no HTTP, signing, or retries. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.SampleTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +public class V1RestJsonProtocolBenchmark { + + private static final JsonFactory JSON_FACTORY = new JsonFactory(); + + private byte[] responseBytes; + private HttpResponse httpResponse; + private SdkJsonProtocolFactory protocolFactory; + private CreateFunctionRequest request; + + @Setup + public void setup() throws Exception { + responseBytes = loadFixture("fixtures/rest-json-protocol/createfunction-response.json"); + httpResponse = new HttpResponse(null, null); + httpResponse.setStatusCode(200); + protocolFactory = new SdkJsonProtocolFactory(new JsonClientMetadata() + .withProtocolVersion("1.1") + .withContentTypeOverride("application/json")); + request = createRequest(); + } + + @Benchmark + public void createFunctionDeser(Blackhole bh) throws Exception { + JsonParser parser = JSON_FACTORY.createParser(new ByteArrayInputStream(responseBytes)); + JsonUnmarshallerContextImpl ctx = new JsonUnmarshallerContextImpl( + parser, + SdkStructuredPlainJsonFactory.JSON_SCALAR_UNMARSHALLERS, + SdkStructuredPlainJsonFactory.JSON_CUSTOM_TYPE_UNMARSHALLERS, + httpResponse); + + bh.consume(CreateFunctionResultJsonUnmarshaller.getInstance().unmarshall(ctx)); + } + + @Benchmark + public void createFunctionSer(Blackhole bh) { + bh.consume(new CreateFunctionRequestProtocolMarshaller(protocolFactory) + .marshall(request)); + } + + private static CreateFunctionRequest createRequest() { + Map envVars = new HashMap<>(); + envVars.put("ENV_VAR_1", "value1"); + + return new CreateFunctionRequest() + .withFunctionName("benchmark-function") + .withRuntime(Runtime.Java8) + .withRole("arn:aws:iam::123456789012:role/lambda-role") + .withHandler("com.example.Handler::handleRequest") + .withCode(new FunctionCode() + .withS3Bucket("my-deploy-bucket") + .withS3Key("code/function.zip")) + .withDescription("Benchmark test function") + .withTimeout(30) + .withMemorySize(512) + .withPublish(false) + .withEnvironment(new Environment().withVariables(envVars)) + .withTracingConfig(new TracingConfig() + .withMode(TracingMode.Active)); + } + + private static byte[] loadFixture(String path) throws IOException { + return com.amazonaws.util.IOUtils.toByteArray( + V1RestJsonProtocolBenchmark.class.getClassLoader() + .getResourceAsStream(path)); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1RestXmlProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1RestXmlProtocolBenchmark.java new file mode 100644 index 000000000000..bca728d7ef52 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1RestXmlProtocolBenchmark.java @@ -0,0 +1,138 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.protocol; + +import com.amazonaws.http.HttpResponse; +import com.amazonaws.services.cloudfront.model.Aliases; +import com.amazonaws.services.cloudfront.model.AllowedMethods; +import com.amazonaws.services.cloudfront.model.CachedMethods; +import com.amazonaws.services.cloudfront.model.CreateDistributionRequest; +import com.amazonaws.services.cloudfront.model.DefaultCacheBehavior; +import com.amazonaws.services.cloudfront.model.DistributionConfig; +import com.amazonaws.services.cloudfront.model.Method; +import com.amazonaws.services.cloudfront.model.Origin; +import com.amazonaws.services.cloudfront.model.Origins; +import com.amazonaws.services.cloudfront.model.S3OriginConfig; +import com.amazonaws.services.cloudfront.model.ViewerProtocolPolicy; +import com.amazonaws.services.cloudfront.model.transform.CreateDistributionRequestMarshaller; +import com.amazonaws.services.cloudfront.model.transform.CreateDistributionResultStaxUnmarshaller; +import com.amazonaws.transform.StaxUnmarshallerContext; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +/** + * Isolated ser/de benchmark for V1 CloudFront (REST-XML protocol). + * Measures only XML parsing + object construction -- no HTTP, signing, or retries. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.SampleTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +public class V1RestXmlProtocolBenchmark { + + private static final XMLInputFactory XML_INPUT_FACTORY = XMLInputFactory.newInstance(); + + private byte[] responseBytes; + private Map responseHeaders; + private CreateDistributionRequestMarshaller marshaller; + private CreateDistributionRequest request; + + @Setup + public void setup() throws Exception { + responseBytes = loadFixture("fixtures/rest-xml-protocol/create-distribution-response.xml"); + + responseHeaders = new HashMap<>(); + responseHeaders.put("ETag", "E2QWRUHEXAMPLE"); + responseHeaders.put("Location", "https://cloudfront.amazonaws.com/2020-05-31/distribution/EDFDVBD6EXAMPLE"); + + HttpResponse httpResponse = new HttpResponse(null, null); + httpResponse.setStatusCode(200); + for (Map.Entry e : responseHeaders.entrySet()) { + httpResponse.addHeader(e.getKey(), e.getValue()); + } + + marshaller = new CreateDistributionRequestMarshaller(); + request = createRequest(); + } + + @Benchmark + public void createDistributionDeser(Blackhole bh) throws Exception { + XMLEventReader reader = XML_INPUT_FACTORY.createXMLEventReader(new ByteArrayInputStream(responseBytes)); + StaxUnmarshallerContext ctx = new StaxUnmarshallerContext( + reader, responseHeaders); + ctx.registerMetadataExpression("ResponseMetadata/RequestId", 2, "AWS_REQUEST_ID"); + bh.consume(CreateDistributionResultStaxUnmarshaller.getInstance().unmarshall(ctx)); + } + + @Benchmark + public void createDistributionSer(Blackhole bh) { + bh.consume(marshaller.marshall(request)); + } + + private static CreateDistributionRequest createRequest() { + return new CreateDistributionRequest() + .withDistributionConfig(new DistributionConfig() + .withCallerReference("benchmark-ref-2024") + .withAliases(new Aliases() + .withQuantity(2) + .withItems("www.example.com", "cdn.example.com")) + .withDefaultRootObject("index.html") + .withOrigins(new Origins() + .withQuantity(1) + .withItems(new Origin() + .withId("myS3Origin") + .withDomainName("mybucket.s3.amazonaws.com") + .withOriginPath("/production") + .withS3OriginConfig(new S3OriginConfig() + .withOriginAccessIdentity( + "origin-access-identity/cloudfront/E127EXAMPLE51Z")))) + .withDefaultCacheBehavior(new DefaultCacheBehavior() + .withTargetOriginId("myS3Origin") + .withViewerProtocolPolicy( + ViewerProtocolPolicy.RedirectToHttps) + .withAllowedMethods(new AllowedMethods() + .withQuantity(3) + .withItems(Method.GET, Method.HEAD, Method.OPTIONS) + .withCachedMethods(new CachedMethods() + .withQuantity(2) + .withItems(Method.GET, Method.HEAD))) + .withCompress(true))); + } + + private static byte[] loadFixture(String path) throws IOException { + return com.amazonaws.util.IOUtils.toByteArray( + V1RestXmlProtocolBenchmark.class.getClassLoader() + .getResourceAsStream(path)); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2CborProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2CborProtocolBenchmark.java new file mode 100644 index 000000000000..fd0ed68839e0 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2CborProtocolBenchmark.java @@ -0,0 +1,178 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.protocol; + +import java.io.ByteArrayInputStream; +import java.net.URI; +import java.time.Instant; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import software.amazon.awssdk.http.AbortableInputStream; +import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.SdkHttpFullResponse; +import software.amazon.awssdk.http.SdkHttpMethod; +import software.amazon.awssdk.protocols.core.OperationInfo; +import software.amazon.awssdk.protocols.core.ProtocolMarshaller; +import software.amazon.awssdk.protocols.json.AwsJsonProtocol; +import software.amazon.awssdk.protocols.json.AwsJsonProtocolMetadata; +import software.amazon.awssdk.protocols.json.StructuredJsonGenerator; +import software.amazon.awssdk.protocols.json.internal.marshall.JsonProtocolMarshallerBuilder; +import software.amazon.awssdk.protocols.json.internal.unmarshall.JsonProtocolUnmarshaller; +import software.amazon.awssdk.protocols.rpcv2.SmithyRpcV2CborProtocolFactory; +import software.amazon.awssdk.protocols.rpcv2.internal.SdkStructuredRpcV2CborFactory; +import software.amazon.awssdk.services.cloudwatch.model.GetMetricDataRequest; +import software.amazon.awssdk.services.cloudwatch.model.GetMetricDataResponse; +import software.amazon.awssdk.services.cloudwatch.model.Metric; +import software.amazon.awssdk.services.cloudwatch.model.MetricDataQuery; +import software.amazon.awssdk.services.cloudwatch.model.MetricStat; + +/** + * Isolated ser/de benchmark for V2 CloudWatch (smithy-rpc-v2-cbor protocol). + * Measures only CBOR parsing + object construction -- no HTTP, signing, or retries. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.SampleTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +public class V2CborProtocolBenchmark { + + private static final String CONTENT_TYPE = "application/cbor"; + private static final URI ENDPOINT = URI.create("http://localhost/"); + + private static final AwsJsonProtocolMetadata METADATA = AwsJsonProtocolMetadata.builder() + .protocol(AwsJsonProtocol.SMITHY_RPC_V2_CBOR) + .contentType(CONTENT_TYPE) + .build(); + + private static final OperationInfo OP_INFO = OperationInfo.builder() + .requestUri("/service/GraniteServiceVersion20100801/operation/GetMetricData") + .httpMethod(SdkHttpMethod.POST) + .hasExplicitPayloadMember(false) + .hasImplicitPayloadMembers(true) + .hasPayloadMembers(true) + .build(); + + private JsonProtocolUnmarshaller unmarshaller; + private byte[] responseBytes; + private GetMetricDataRequest request; + + @Setup + public void setup() throws Exception { + unmarshaller = JsonProtocolUnmarshaller.builder() + .enableFastUnmarshalling(true) + .protocolUnmarshallDependencies(SmithyRpcV2CborProtocolFactory.defaultProtocolUnmarshallDependencies()) + .build(); + + responseBytes = createCborResponseFixture(); + request = createRequest(); + } + + @Benchmark + public void getMetricDataDeser(Blackhole bh) throws Exception { + SdkHttpFullResponse response = SdkHttpFullResponse.builder() + .statusCode(200) + .putHeader("Content-Type", CONTENT_TYPE) + .content(AbortableInputStream.create(new ByteArrayInputStream(responseBytes))) + .build(); + bh.consume(unmarshaller.unmarshall(GetMetricDataResponse.builder(), response)); + } + + @Benchmark + public void getMetricDataSer(Blackhole bh) { + ProtocolMarshaller marshaller = JsonProtocolMarshallerBuilder.create() + .endpoint(ENDPOINT) + .jsonGenerator(SdkStructuredRpcV2CborFactory.SDK_CBOR_FACTORY.createWriter(CONTENT_TYPE)) + .contentType(CONTENT_TYPE) + .operationInfo(OP_INFO) + .sendExplicitNullForPayload(false) + .protocolMetadata(METADATA) + .build(); + bh.consume(marshaller.marshall(request)); + } + + private static GetMetricDataRequest createRequest() { + Instant end = Instant.parse("2026-03-09T00:00:00Z"); + Instant start = end.minusSeconds(3600); + return GetMetricDataRequest.builder() + .startTime(start) + .endTime(end) + .maxDatapoints(1000) + .metricDataQueries( + MetricDataQuery.builder() + .id("cpu") + .metricStat(MetricStat.builder() + .metric(Metric.builder() + .namespace("AWS/EC2") + .metricName("CPUUtilization") + .build()) + .period(300) + .stat("Average") + .build()) + .returnData(true) + .build()) + .build(); + } + + private static byte[] createCborResponseFixture() { + StructuredJsonGenerator gen = + SdkStructuredRpcV2CborFactory.SDK_CBOR_FACTORY.createWriter(CONTENT_TYPE); + gen.writeStartObject(); + gen.writeFieldName("MetricDataResults"); + gen.writeStartArray(); + gen.writeStartObject(); + gen.writeFieldName("Id"); + gen.writeValue("cpu"); + gen.writeFieldName("Label"); + gen.writeValue("CPUUtilization"); + gen.writeFieldName("StatusCode"); + gen.writeValue("Complete"); + gen.writeFieldName("Timestamps"); + gen.writeStartArray(); + long base = 1772611200L; + for (int i = 0; i < 12; i++) { + gen.writeValue((double) ((base + i * 300) * 1000)); + } + gen.writeEndArray(); + gen.writeFieldName("Values"); + gen.writeStartArray(); + for (int i = 0; i < 12; i++) { + gen.writeValue(45.2 + i * 1.1); + } + gen.writeEndArray(); + gen.writeFieldName("Messages"); + gen.writeStartArray(); + gen.writeEndArray(); + gen.writeEndObject(); + gen.writeEndArray(); + gen.writeFieldName("Messages"); + gen.writeStartArray(); + gen.writeEndArray(); + gen.writeEndObject(); + return gen.getBytes(); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2Ec2ProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2Ec2ProtocolBenchmark.java new file mode 100644 index 000000000000..2f3beb03a466 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2Ec2ProtocolBenchmark.java @@ -0,0 +1,117 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.protocol; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.URI; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import software.amazon.awssdk.http.AbortableInputStream; +import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.SdkHttpFullResponse; +import software.amazon.awssdk.http.SdkHttpMethod; +import software.amazon.awssdk.protocols.core.OperationInfo; +import software.amazon.awssdk.protocols.core.ProtocolMarshaller; +import software.amazon.awssdk.protocols.query.internal.marshall.QueryProtocolMarshaller; +import software.amazon.awssdk.protocols.query.internal.unmarshall.QueryProtocolUnmarshaller; +import software.amazon.awssdk.services.ec2.model.DescribeInstancesRequest; +import software.amazon.awssdk.services.ec2.model.DescribeInstancesResponse; +import software.amazon.awssdk.services.ec2.model.Filter; +import software.amazon.awssdk.utils.Pair; + +/** + * Isolated ser/de benchmark for V2 EC2 (EC2 Query protocol). + * Measures only XML parsing + form encoding -- no HTTP, signing, or retries. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.SampleTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +public class V2Ec2ProtocolBenchmark { + + private static final URI ENDPOINT = URI.create("http://localhost/"); + private static final OperationInfo OP_INFO = OperationInfo.builder() + .requestUri("/") + .httpMethod(SdkHttpMethod.POST) + .hasExplicitPayloadMember(false) + .hasPayloadMembers(true) + .operationIdentifier("DescribeInstances") + .apiVersion("2016-11-15") + .build(); + + private QueryProtocolUnmarshaller unmarshaller; + private byte[] responseBytes; + private DescribeInstancesRequest request; + + @Setup + public void setup() throws Exception { + unmarshaller = QueryProtocolUnmarshaller.builder().hasResultWrapper(false).build(); + responseBytes = loadFixture("fixtures/ec2-protocol/describe-instances-response.xml"); + request = createRequest(); + } + + @Benchmark + public void describeInstancesDeser(Blackhole bh) { + SdkHttpFullResponse response = SdkHttpFullResponse.builder() + .statusCode(200) + .content(AbortableInputStream.create(new ByteArrayInputStream(responseBytes))) + .build(); + + Pair result = unmarshaller.unmarshall(DescribeInstancesResponse.builder(), response); + bh.consume(result.left()); + } + + @Benchmark + public void describeInstancesSer(Blackhole bh) { + ProtocolMarshaller marshaller = QueryProtocolMarshaller.builder() + .endpoint(ENDPOINT) + .operationInfo(OP_INFO) + .isEc2(true) + .build(); + bh.consume(marshaller.marshall(request)); + } + + private static DescribeInstancesRequest createRequest() { + return DescribeInstancesRequest.builder() + .instanceIds("i-0abcdef1234567890") + .filters( + Filter.builder().name("instance-state-name") + .values("running").build(), + Filter.builder().name("instance-type") + .values("m5.xlarge").build()) + .maxResults(100) + .build(); + } + + private static byte[] loadFixture(String path) throws IOException { + return software.amazon.awssdk.utils.IoUtils.toByteArray( + V2Ec2ProtocolBenchmark.class.getClassLoader() + .getResourceAsStream(path)); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2JsonProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2JsonProtocolBenchmark.java new file mode 100644 index 000000000000..87ad57fd38fa --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2JsonProtocolBenchmark.java @@ -0,0 +1,151 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.protocol; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.URI; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.http.AbortableInputStream; +import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.SdkHttpFullResponse; +import software.amazon.awssdk.http.SdkHttpMethod; +import software.amazon.awssdk.protocols.core.OperationInfo; +import software.amazon.awssdk.protocols.core.ProtocolMarshaller; +import software.amazon.awssdk.protocols.json.AwsJsonProtocol; +import software.amazon.awssdk.protocols.json.AwsJsonProtocolMetadata; +import software.amazon.awssdk.protocols.json.internal.AwsStructuredPlainJsonFactory; +import software.amazon.awssdk.protocols.json.internal.marshall.JsonProtocolMarshallerBuilder; +import software.amazon.awssdk.protocols.json.internal.unmarshall.JsonProtocolUnmarshaller; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; +import software.amazon.awssdk.services.dynamodb.model.PutItemResponse; + +/** + * Isolated ser/de benchmark for V2 DynamoDB (JSON protocol). + * Measures only JSON parsing + object construction -- no HTTP, signing, or retries. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.SampleTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +public class V2JsonProtocolBenchmark { + + private static final String CONTENT_TYPE = "application/x-amz-json-1.0"; + private static final URI ENDPOINT = URI.create("http://localhost/"); + private static final OperationInfo OP_INFO = OperationInfo.builder() + .httpMethod(SdkHttpMethod.POST) + .hasImplicitPayloadMembers(true) + .build(); + + private static final AwsJsonProtocolMetadata METADATA = AwsJsonProtocolMetadata.builder() + .protocol(AwsJsonProtocol.AWS_JSON) + .contentType(CONTENT_TYPE) + .build(); + + private JsonProtocolUnmarshaller unmarshaller; + private byte[] putItemResponseBytes; + private PutItemRequest putItemRequest; + + @Setup + public void setup() throws Exception { + unmarshaller = JsonProtocolUnmarshaller.builder() + .enableFastUnmarshalling(true) + .protocolUnmarshallDependencies(JsonProtocolUnmarshaller.defaultProtocolUnmarshallDependencies()) + .build(); + + putItemResponseBytes = loadFixture("fixtures/json-protocol/putitem-response.json"); + putItemRequest = PutItemRequest.builder() + .tableName("benchmark-table") + .item(itemMap()) + .build(); + } + + @Benchmark + public void putItemDeser(Blackhole bh) throws Exception { + SdkHttpFullResponse response = SdkHttpFullResponse.builder() + .statusCode(200) + .putHeader("Content-Type", CONTENT_TYPE) + .content(AbortableInputStream.create(new ByteArrayInputStream(putItemResponseBytes))) + .build(); + + bh.consume(unmarshaller.unmarshall(PutItemResponse.builder(), response)); + } + + @Benchmark + public void putItemSer(Blackhole bh) { + ProtocolMarshaller marshaller = JsonProtocolMarshallerBuilder.create() + .endpoint(ENDPOINT) + .jsonGenerator(AwsStructuredPlainJsonFactory.SDK_JSON_FACTORY + .createWriter(CONTENT_TYPE)) + .contentType(CONTENT_TYPE) + .operationInfo(OP_INFO) + .sendExplicitNullForPayload(false) + .protocolMetadata(METADATA) + .build(); + + bh.consume(marshaller.marshall(putItemRequest)); + } + + private static Map itemMap() { + Map item = new HashMap(); + item.put("pk", AttributeValue.fromS("benchmark-key")); + item.put("sk", AttributeValue.fromN("100")); + item.put("stringField", AttributeValue.fromS("test-value")); + item.put("numberField", AttributeValue.fromN("123.456")); + item.put("binaryField", AttributeValue.fromB( + SdkBytes.fromByteArray("hello world".getBytes()))); + item.put("stringSetField", AttributeValue.builder() + .ss("value1", "value2", "value3").build()); + item.put("numberSetField", AttributeValue.builder() + .ns("1.1", "2.2", "3.3").build()); + item.put("boolField", AttributeValue.fromBool(false)); + item.put("nullField", AttributeValue.builder().nul(true).build()); + Map deep = new HashMap(); + deep.put("level2", AttributeValue.fromN("999")); + Map nested = new HashMap(); + nested.put("nested", AttributeValue.fromS("nested-value")); + nested.put("deepNested", AttributeValue.fromM(deep)); + item.put("mapField", AttributeValue.fromM(nested)); + item.put("listField", AttributeValue.builder().l( + AttributeValue.fromS("item1"), + AttributeValue.fromN("42"), + AttributeValue.fromBool(true), + AttributeValue.builder().nul(true).build()).build()); + return item; + } + + private static byte[] loadFixture(String path) throws IOException { + return software.amazon.awssdk.utils.IoUtils.toByteArray( + V2JsonProtocolBenchmark.class.getClassLoader().getResourceAsStream(path)); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2QueryProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2QueryProtocolBenchmark.java new file mode 100644 index 000000000000..1e6c6ac49b5d --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2QueryProtocolBenchmark.java @@ -0,0 +1,117 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.protocol; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.URI; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import software.amazon.awssdk.http.AbortableInputStream; +import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.SdkHttpFullResponse; +import software.amazon.awssdk.http.SdkHttpMethod; +import software.amazon.awssdk.protocols.core.OperationInfo; +import software.amazon.awssdk.protocols.core.ProtocolMarshaller; +import software.amazon.awssdk.protocols.query.internal.marshall.QueryProtocolMarshaller; +import software.amazon.awssdk.protocols.query.internal.unmarshall.QueryProtocolUnmarshaller; +import software.amazon.awssdk.services.sts.model.AssumeRoleRequest; +import software.amazon.awssdk.services.sts.model.AssumeRoleResponse; +import software.amazon.awssdk.utils.Pair; + +/** + * Isolated ser/de benchmark for V2 STS (Query protocol). + * Measures only XML parsing + form encoding -- no HTTP, signing, or retries. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.SampleTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +public class V2QueryProtocolBenchmark { + + private static final URI ENDPOINT = URI.create("http://localhost/"); + private static final OperationInfo OP_INFO = OperationInfo.builder() + .requestUri("/") + .httpMethod(SdkHttpMethod.POST) + .hasExplicitPayloadMember(false) + .hasPayloadMembers(true) + .operationIdentifier("AssumeRole") + .apiVersion("2011-06-15") + .build(); + + private QueryProtocolUnmarshaller unmarshaller; + private byte[] responseBytes; + private AssumeRoleRequest request; + + @Setup + public void setup() throws Exception { + unmarshaller = QueryProtocolUnmarshaller.builder() + .hasResultWrapper(true) + .build(); + + responseBytes = loadFixture("fixtures/query-protocol/assumerole-response.xml"); + request = createRequest(); + } + + @Benchmark + public void assumeRoleDeser(Blackhole bh) { + SdkHttpFullResponse response = SdkHttpFullResponse.builder() + .statusCode(200) + .content(AbortableInputStream.create(new ByteArrayInputStream(responseBytes))) + .build(); + + Pair result = unmarshaller.unmarshall(AssumeRoleResponse.builder(), response); + bh.consume(result.left()); + } + + @Benchmark + public void assumeRoleSer(Blackhole bh) { + ProtocolMarshaller marshaller = QueryProtocolMarshaller.builder() + .endpoint(ENDPOINT) + .operationInfo(OP_INFO) + .isEc2(false) + .build(); + bh.consume(marshaller.marshall(request)); + } + + private static AssumeRoleRequest createRequest() { + return AssumeRoleRequest.builder() + .roleArn("arn:aws:iam::123456789012:role/benchmark-role") + .roleSessionName("benchmark-session") + .durationSeconds(3600) + .externalId("benchmark-external-id") + .policy("{\"Version\":\"2012-10-17\"}") + .build(); + } + + private static byte[] loadFixture(String path) throws IOException { + return software.amazon.awssdk.utils.IoUtils.toByteArray( + V2QueryProtocolBenchmark.class.getClassLoader() + .getResourceAsStream(path)); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2RestJsonProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2RestJsonProtocolBenchmark.java new file mode 100644 index 000000000000..6f76afece417 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2RestJsonProtocolBenchmark.java @@ -0,0 +1,153 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.protocol; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.URI; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import software.amazon.awssdk.http.AbortableInputStream; +import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.SdkHttpFullResponse; +import software.amazon.awssdk.http.SdkHttpMethod; +import software.amazon.awssdk.protocols.core.OperationInfo; +import software.amazon.awssdk.protocols.core.ProtocolMarshaller; +import software.amazon.awssdk.protocols.json.AwsJsonProtocol; +import software.amazon.awssdk.protocols.json.AwsJsonProtocolMetadata; +import software.amazon.awssdk.protocols.json.internal.AwsStructuredPlainJsonFactory; +import software.amazon.awssdk.protocols.json.internal.marshall.JsonProtocolMarshallerBuilder; +import software.amazon.awssdk.protocols.json.internal.unmarshall.JsonProtocolUnmarshaller; +import software.amazon.awssdk.services.lambda.model.CreateFunctionRequest; +import software.amazon.awssdk.services.lambda.model.CreateFunctionResponse; +import software.amazon.awssdk.services.lambda.model.Environment; +import software.amazon.awssdk.services.lambda.model.FunctionCode; +import software.amazon.awssdk.services.lambda.model.Runtime; +import software.amazon.awssdk.services.lambda.model.TracingConfig; +import software.amazon.awssdk.services.lambda.model.TracingMode; + +/** + * Isolated ser/de benchmark for V2 Lambda (REST-JSON protocol). + * Measures only JSON parsing + object construction -- no HTTP, signing, or retries. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.SampleTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +public class V2RestJsonProtocolBenchmark { + + private static final String CONTENT_TYPE = "application/json"; + private static final URI ENDPOINT = URI.create("http://localhost/"); + private static final OperationInfo OP_INFO = OperationInfo.builder() + .requestUri("/2015-03-31/functions") + .httpMethod(SdkHttpMethod.POST) + .hasExplicitPayloadMember(false) + .hasImplicitPayloadMembers(true) + .hasPayloadMembers(true) + .build(); + + private static final AwsJsonProtocolMetadata METADATA = + AwsJsonProtocolMetadata.builder() + .protocol(AwsJsonProtocol.REST_JSON) + .protocolVersion("1.1") + .contentType(CONTENT_TYPE) + .build(); + + private JsonProtocolUnmarshaller unmarshaller; + private byte[] responseBytes; + private CreateFunctionRequest request; + + @Setup + public void setup() throws Exception { + unmarshaller = JsonProtocolUnmarshaller.builder() + .enableFastUnmarshalling(true) + .protocolUnmarshallDependencies(JsonProtocolUnmarshaller.defaultProtocolUnmarshallDependencies()) + .build(); + + responseBytes = loadFixture("fixtures/rest-json-protocol/createfunction-response.json"); + request = createRequest(); + } + + @Benchmark + public void createFunctionDeser(Blackhole bh) throws IOException { + SdkHttpFullResponse response = SdkHttpFullResponse.builder() + .statusCode(200) + .putHeader("Content-Type", CONTENT_TYPE) + .content(AbortableInputStream.create( + new ByteArrayInputStream(responseBytes))) + .build(); + bh.consume(unmarshaller.unmarshall(CreateFunctionResponse.builder(), response)); + } + + @Benchmark + public void createFunctionSer(Blackhole bh) { + ProtocolMarshaller marshaller = + JsonProtocolMarshallerBuilder.create() + .endpoint(ENDPOINT) + .jsonGenerator(AwsStructuredPlainJsonFactory.SDK_JSON_FACTORY + .createWriter(CONTENT_TYPE)) + .contentType(CONTENT_TYPE) + .operationInfo(OP_INFO) + .sendExplicitNullForPayload(false) + .protocolMetadata(METADATA) + .build(); + bh.consume(marshaller.marshall(request)); + } + + private static CreateFunctionRequest createRequest() { + Map envVars = new HashMap<>(); + envVars.put("ENV_VAR_1", "value1"); + + return CreateFunctionRequest.builder() + .functionName("benchmark-function") + .runtime(Runtime.JAVA8) + .role("arn:aws:iam::123456789012:role/lambda-role") + .handler("com.example.Handler::handleRequest") + .code(FunctionCode.builder() + .s3Bucket("my-deploy-bucket") + .s3Key("code/function.zip") + .build()) + .description("Benchmark test function") + .timeout(30) + .memorySize(512) + .publish(false) + .environment(Environment.builder().variables(envVars).build()) + .tracingConfig(TracingConfig.builder() + .mode(TracingMode.ACTIVE) + .build()) + .build(); + } + + private static byte[] loadFixture(String path) throws IOException { + return software.amazon.awssdk.utils.IoUtils.toByteArray( + V2RestJsonProtocolBenchmark.class.getClassLoader() + .getResourceAsStream(path)); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2RestXmlProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2RestXmlProtocolBenchmark.java new file mode 100644 index 000000000000..e2c61142c356 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2RestXmlProtocolBenchmark.java @@ -0,0 +1,154 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.protocol; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.URI; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import software.amazon.awssdk.http.AbortableInputStream; +import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.SdkHttpFullResponse; +import software.amazon.awssdk.http.SdkHttpMethod; +import software.amazon.awssdk.protocols.core.OperationInfo; +import software.amazon.awssdk.protocols.core.ProtocolMarshaller; +import software.amazon.awssdk.protocols.xml.AwsXmlProtocolFactory; +import software.amazon.awssdk.protocols.xml.internal.marshall.XmlGenerator; +import software.amazon.awssdk.protocols.xml.internal.marshall.XmlProtocolMarshaller; +import software.amazon.awssdk.protocols.xml.internal.unmarshall.XmlProtocolUnmarshaller; +import software.amazon.awssdk.services.cloudfront.model.Aliases; +import software.amazon.awssdk.services.cloudfront.model.AllowedMethods; +import software.amazon.awssdk.services.cloudfront.model.CachedMethods; +import software.amazon.awssdk.services.cloudfront.model.CreateDistributionRequest; +import software.amazon.awssdk.services.cloudfront.model.CreateDistributionResponse; +import software.amazon.awssdk.services.cloudfront.model.DefaultCacheBehavior; +import software.amazon.awssdk.services.cloudfront.model.DistributionConfig; +import software.amazon.awssdk.services.cloudfront.model.Method; +import software.amazon.awssdk.services.cloudfront.model.Origin; +import software.amazon.awssdk.services.cloudfront.model.Origins; +import software.amazon.awssdk.services.cloudfront.model.S3OriginConfig; +import software.amazon.awssdk.services.cloudfront.model.ViewerProtocolPolicy; + +/** + * Isolated ser/de benchmark for V2 CloudFront (REST-XML protocol). + * Measures only XML parsing + object construction -- no HTTP, signing, or retries. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.SampleTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +public class V2RestXmlProtocolBenchmark { + + private static final String XMLNS = "http://cloudfront.amazonaws.com/doc/2020-05-31/"; + private static final URI ENDPOINT = URI.create("http://localhost/"); + private static final OperationInfo OP_INFO = OperationInfo.builder() + .requestUri("/2020-05-31/distribution") + .httpMethod(SdkHttpMethod.POST) + .hasExplicitPayloadMember(true) + .hasPayloadMembers(true) + .putAdditionalMetadata(AwsXmlProtocolFactory.ROOT_MARSHALL_LOCATION_ATTRIBUTE, null) + .putAdditionalMetadata(AwsXmlProtocolFactory.XML_NAMESPACE_ATTRIBUTE, XMLNS) + .build(); + + private XmlProtocolUnmarshaller unmarshaller; + private byte[] responseBytes; + private CreateDistributionRequest request; + + @Setup + public void setup() throws Exception { + unmarshaller = XmlProtocolUnmarshaller.create(); + responseBytes = loadFixture("fixtures/rest-xml-protocol/create-distribution-response.xml"); + request = createRequest(); + } + + @Benchmark + public void createDistributionDeser(Blackhole bh) { + SdkHttpFullResponse response = SdkHttpFullResponse.builder() + .statusCode(200) + .putHeader("ETag", "E2QWRUHEXAMPLE") + .putHeader("Location", "https://cloudfront.amazonaws.com/2020-05-31/distribution/EDFDVBD6EXAMPLE") + .content(AbortableInputStream.create(new ByteArrayInputStream(responseBytes))) + .build(); + bh.consume(unmarshaller.unmarshall(CreateDistributionResponse.builder(), response)); + } + + @Benchmark + public void createDistributionSer(Blackhole bh) { + ProtocolMarshaller marshaller = XmlProtocolMarshaller.builder() + .endpoint(ENDPOINT) + .xmlGenerator(XmlGenerator.create(XMLNS, false)) + .operationInfo(OP_INFO) + .build(); + bh.consume(marshaller.marshall(request)); + } + + private static CreateDistributionRequest createRequest() { + return CreateDistributionRequest.builder() + .distributionConfig(DistributionConfig.builder() + .callerReference("benchmark-ref-2024") + .aliases(Aliases.builder() + .quantity(2) + .items("www.example.com", "cdn.example.com") + .build()) + .defaultRootObject("index.html") + .origins(Origins.builder() + .quantity(1) + .items(Origin.builder() + .id("myS3Origin") + .domainName("mybucket.s3.amazonaws.com") + .originPath("/production") + .s3OriginConfig(S3OriginConfig.builder() + .originAccessIdentity( + "origin-access-identity/cloudfront/E127EXAMPLE51Z") + .build()) + .build()) + .build()) + .defaultCacheBehavior(DefaultCacheBehavior.builder() + .targetOriginId("myS3Origin") + .viewerProtocolPolicy(ViewerProtocolPolicy.REDIRECT_TO_HTTPS) + .allowedMethods(AllowedMethods.builder() + .quantity(3) + .items(Method.GET, Method.HEAD, Method.OPTIONS) + .cachedMethods(CachedMethods.builder() + .quantity(2) + .items(Method.GET, Method.HEAD) + .build()) + .build()) + .compress(true) + .build()) + .build()) + .build(); + } + + private static byte[] loadFixture(String path) throws IOException { + return software.amazon.awssdk.utils.IoUtils.toByteArray( + V2RestXmlProtocolBenchmark.class.getClassLoader() + .getResourceAsStream(path)); + } +} diff --git a/test/sdk-benchmarks/src/main/resources/fixtures/ec2-protocol/describe-instances-response.xml b/test/sdk-benchmarks/src/main/resources/fixtures/ec2-protocol/describe-instances-response.xml new file mode 100644 index 000000000000..6a8153163fdb --- /dev/null +++ b/test/sdk-benchmarks/src/main/resources/fixtures/ec2-protocol/describe-instances-response.xml @@ -0,0 +1,37 @@ + + 8f7724cf-496f-496e-8fe2-example + + + r-0abcdef1234567890 + 123456789012 + + + i-0abcdef1234567890 + ami-0abcdef1234567890 + 16running + ip-10-0-0-1.ec2.internal + ec2-203-0-113-1.compute-1.amazonaws.com + m5.xlarge + 2024-01-15T10:30:00.000Z + us-east-1adefault + disabled + subnet-0abcdef1234567890 + vpc-0abcdef1234567890 + 10.0.0.1 + 203.0.113.1 + x86_64 + ebs + /dev/xvda + hvm + xen + + Namebenchmark-instance + Environmentproduction + + true + true + + + + + diff --git a/test/sdk-benchmarks/src/main/resources/fixtures/json-protocol/putitem-response.json b/test/sdk-benchmarks/src/main/resources/fixtures/json-protocol/putitem-response.json new file mode 100644 index 000000000000..df9f0e8ada3f --- /dev/null +++ b/test/sdk-benchmarks/src/main/resources/fixtures/json-protocol/putitem-response.json @@ -0,0 +1,24 @@ +{ + "Attributes": { + "pk": {"S": "benchmark-key"}, + "sk": {"N": "100"}, + "stringField": {"S": "test-value"}, + "numberField": {"N": "123.456"}, + "binaryField": {"B": "aGVsbG8gd29ybGQ="}, + "stringSetField": {"SS": ["value1", "value2", "value3"]}, + "numberSetField": {"NS": ["1.1", "2.2", "3.3"]}, + "binarySetField": {"BS": ["YmluMQ==", "YmluMg=="]}, + "mapField": {"M": { + "nested": {"S": "nested-value"}, + "deepNested": {"M": {"level2": {"N": "999"}}} + }}, + "listField": {"L": [ + {"S": "item1"}, + {"N": "42"}, + {"BOOL": true}, + {"NULL": true} + ]}, + "nullField": {"NULL": true}, + "boolField": {"BOOL": false} + } +} \ No newline at end of file diff --git a/test/sdk-benchmarks/src/main/resources/fixtures/query-protocol/assumerole-response.xml b/test/sdk-benchmarks/src/main/resources/fixtures/query-protocol/assumerole-response.xml new file mode 100644 index 000000000000..db2481e96745 --- /dev/null +++ b/test/sdk-benchmarks/src/main/resources/fixtures/query-protocol/assumerole-response.xml @@ -0,0 +1,19 @@ + + + + ASIAIOSFODNN7EXAMPLE + wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY + FwoGZXIvYXdzEBYaDHqa0AP1 + 2024-01-15T12:00:00Z + + + AROA3XFRBF23EXAMPLE:benchmark-session + arn:aws:sts::123456789012:assumed-role/benchmark-role/benchmark-session + + 42 + benchmark-source + + + c6104cbe-af31-11e0-8154-cde7cf80f29a + + diff --git a/test/sdk-benchmarks/src/main/resources/fixtures/rest-json-protocol/createfunction-response.json b/test/sdk-benchmarks/src/main/resources/fixtures/rest-json-protocol/createfunction-response.json new file mode 100644 index 000000000000..638c54e42837 --- /dev/null +++ b/test/sdk-benchmarks/src/main/resources/fixtures/rest-json-protocol/createfunction-response.json @@ -0,0 +1,43 @@ +{ + "FunctionName": "benchmark-function", + "FunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:benchmark-function", + "Runtime": "java21", + "Role": "arn:aws:iam::123456789012:role/lambda-role", + "Handler": "com.example.Handler::handleRequest", + "CodeSize": 5242880, + "Description": "Benchmark test function", + "Timeout": 30, + "MemorySize": 512, + "LastModified": "2024-01-15T10:30:00.000+0000", + "CodeSha256": "dGVzdGhhc2g=", + "Version": "$LATEST", + "Environment": { + "Variables": { + "ENV_VAR_1": "value1", + "ENV_VAR_2": "value2", + "TABLE_NAME": "my-table" + } + }, + "TracingConfig": { + "Mode": "Active" + }, + "RevisionId": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111", + "Layers": [ + { + "Arn": "arn:aws:lambda:us-east-1:123456789012:layer:my-layer:3", + "CodeSize": 1048576, + "SigningProfileVersionArn": "arn:aws:signer:us-east-1:123456789012:/signing-profiles/MyProfile" + } + ], + "State": "Active", + "LastUpdateStatus": "Successful", + "PackageType": "Zip", + "Architectures": ["arm64"], + "EphemeralStorage": { + "Size": 1024 + }, + "LoggingConfig": { + "LogFormat": "JSON", + "LogGroup": "/aws/lambda/benchmark-function" + } +} diff --git a/test/sdk-benchmarks/src/main/resources/fixtures/rest-xml-protocol/create-distribution-response.xml b/test/sdk-benchmarks/src/main/resources/fixtures/rest-xml-protocol/create-distribution-response.xml new file mode 100644 index 000000000000..1c88743e9b15 --- /dev/null +++ b/test/sdk-benchmarks/src/main/resources/fixtures/rest-xml-protocol/create-distribution-response.xml @@ -0,0 +1,209 @@ + + + EDFDVBD6EXAMPLE + arn:aws:cloudfront::123456789012:distribution/EDFDVBD6EXAMPLE + Deployed + 2024-01-15T10:30:00Z + 0 + d111111abcdef8.cloudfront.net + + false + 0 + + + false + 0 + + + benchmark-ref-2024 + + 2 + + www.example.com + cdn.example.com + + + index.html + + 2 + + + myS3Origin + mybucket.s3.amazonaws.com + /production + + 1 + + + X-Custom-Header + benchmark-value + + + + + origin-access-identity/cloudfront/E127EXAMPLE51Z + + 3 + 10 + + true + us-east-1 + + + + myCustomOrigin + api.example.com + + + 0 + + + 80 + 443 + https-only + + 1 + + TLSv1.2 + + + 30 + 5 + + 3 + 10 + + + + + myS3Origin + + false + 0 + + + false + 0 + + redirect-to-https + + 3 + + GET + HEAD + OPTIONS + + + 2 + + GET + HEAD + + + + false + true + + 0 + + + 0 + + + 658327ea-f89d-4fab-a63d-7e88639e58f6 + + + 1 + + + /api/* + myCustomOrigin + + false + 0 + + + false + 0 + + https-only + + 7 + + GET + HEAD + OPTIONS + PUT + POST + PATCH + DELETE + + + 2 + + GET + HEAD + + + + false + true + + 0 + + + 0 + + + 4135ea2d-6df8-44a3-9df3-4b5a84be39ad + 88a5eaf4-2fd4-4709-b370-b4c650ea3fcf + + + + + 2 + + + 404 + /errors/404.html + 404 + 300 + + + 500 + /errors/500.html + 500 + 60 + + + + Benchmark distribution + + true + false + mylogs.s3.amazonaws.com + cf-logs/ + + PriceClass_100 + true + + arn:aws:acm:us-east-1:123456789012:certificate/abcd-1234 + sni-only + TLSv1.2_2021 + + + + whitelist + 3 + + US + CA + GB + + + + + http2 + true + + From 5c6e7946e7221ed1fbcdc3bc5f5d8de0f1c0bcca Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Tue, 10 Mar 2026 22:47:07 -0700 Subject: [PATCH 2/7] Change benchmark mode to throughput --- .../awssdk/benchmark/protocol/V1CborProtocolBenchmark.java | 6 +----- .../awssdk/benchmark/protocol/V1Ec2ProtocolBenchmark.java | 6 +----- .../awssdk/benchmark/protocol/V1JsonProtocolBenchmark.java | 6 +----- .../awssdk/benchmark/protocol/V1QueryProtocolBenchmark.java | 6 +----- .../benchmark/protocol/V1RestJsonProtocolBenchmark.java | 6 +----- .../benchmark/protocol/V1RestXmlProtocolBenchmark.java | 6 +----- .../awssdk/benchmark/protocol/V2CborProtocolBenchmark.java | 6 +----- .../awssdk/benchmark/protocol/V2Ec2ProtocolBenchmark.java | 6 +----- .../awssdk/benchmark/protocol/V2JsonProtocolBenchmark.java | 6 +----- .../awssdk/benchmark/protocol/V2QueryProtocolBenchmark.java | 6 +----- .../benchmark/protocol/V2RestJsonProtocolBenchmark.java | 6 +----- .../benchmark/protocol/V2RestXmlProtocolBenchmark.java | 6 +----- 12 files changed, 12 insertions(+), 60 deletions(-) diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1CborProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1CborProtocolBenchmark.java index 5b0e1e59a3dc..2214d797edbf 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1CborProtocolBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1CborProtocolBenchmark.java @@ -42,12 +42,8 @@ import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; -/** - * Isolated ser/de benchmark for V1 CloudWatch (smithy-rpc-v2-cbor protocol). - * Measures only CBOR parsing + object construction -- no HTTP, signing, or retries. - */ @State(Scope.Benchmark) -@BenchmarkMode(Mode.SampleTime) +@BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.MICROSECONDS) @Warmup(iterations = 5) @Measurement(iterations = 5) diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1Ec2ProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1Ec2ProtocolBenchmark.java index 82d8e01d7bd7..9435f5c5c218 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1Ec2ProtocolBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1Ec2ProtocolBenchmark.java @@ -39,12 +39,8 @@ import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; -/** - * Isolated ser/de benchmark for V1 EC2 (EC2 Query protocol). - * Measures only XML parsing + form encoding -- no HTTP, signing, or retries. - */ @State(Scope.Benchmark) -@BenchmarkMode(Mode.SampleTime) +@BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.MICROSECONDS) @Warmup(iterations = 5) @Measurement(iterations = 5) diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1JsonProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1JsonProtocolBenchmark.java index 5cf300685a02..aee02c72626a 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1JsonProtocolBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1JsonProtocolBenchmark.java @@ -44,12 +44,8 @@ import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; -/** - * Isolated ser/de benchmark for V1 DynamoDB (JSON protocol). - * Measures only JSON parsing + object construction -- no HTTP, signing, or retries. - */ @State(Scope.Benchmark) -@BenchmarkMode(Mode.SampleTime) +@BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.MICROSECONDS) @Warmup(iterations = 5) @Measurement(iterations = 5) diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1QueryProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1QueryProtocolBenchmark.java index 1f004d209b85..9e3ca35ad618 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1QueryProtocolBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1QueryProtocolBenchmark.java @@ -38,12 +38,8 @@ import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; -/** - * Isolated ser/de benchmark for V1 STS (Query protocol). - * Measures only XML parsing + form encoding -- no HTTP, signing, or retries. - */ @State(Scope.Benchmark) -@BenchmarkMode(Mode.SampleTime) +@BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.MICROSECONDS) @Warmup(iterations = 5) @Measurement(iterations = 5) diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1RestJsonProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1RestJsonProtocolBenchmark.java index c2a48bd076d2..47da0763a6ac 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1RestJsonProtocolBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1RestJsonProtocolBenchmark.java @@ -47,12 +47,8 @@ import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; -/** - * Isolated ser/de benchmark for V1 Lambda (REST-JSON protocol). - * Measures only JSON parsing + object construction -- no HTTP, signing, or retries. - */ @State(Scope.Benchmark) -@BenchmarkMode(Mode.SampleTime) +@BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.MICROSECONDS) @Warmup(iterations = 5) @Measurement(iterations = 5) diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1RestXmlProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1RestXmlProtocolBenchmark.java index bca728d7ef52..b5b7f578992e 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1RestXmlProtocolBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V1RestXmlProtocolBenchmark.java @@ -49,12 +49,8 @@ import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; -/** - * Isolated ser/de benchmark for V1 CloudFront (REST-XML protocol). - * Measures only XML parsing + object construction -- no HTTP, signing, or retries. - */ @State(Scope.Benchmark) -@BenchmarkMode(Mode.SampleTime) +@BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.MICROSECONDS) @Warmup(iterations = 5) @Measurement(iterations = 5) diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2CborProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2CborProtocolBenchmark.java index fd0ed68839e0..4f2785ee156b 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2CborProtocolBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2CborProtocolBenchmark.java @@ -49,12 +49,8 @@ import software.amazon.awssdk.services.cloudwatch.model.MetricDataQuery; import software.amazon.awssdk.services.cloudwatch.model.MetricStat; -/** - * Isolated ser/de benchmark for V2 CloudWatch (smithy-rpc-v2-cbor protocol). - * Measures only CBOR parsing + object construction -- no HTTP, signing, or retries. - */ @State(Scope.Benchmark) -@BenchmarkMode(Mode.SampleTime) +@BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.MICROSECONDS) @Warmup(iterations = 5) @Measurement(iterations = 5) diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2Ec2ProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2Ec2ProtocolBenchmark.java index 2f3beb03a466..677772608ac7 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2Ec2ProtocolBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2Ec2ProtocolBenchmark.java @@ -43,12 +43,8 @@ import software.amazon.awssdk.services.ec2.model.Filter; import software.amazon.awssdk.utils.Pair; -/** - * Isolated ser/de benchmark for V2 EC2 (EC2 Query protocol). - * Measures only XML parsing + form encoding -- no HTTP, signing, or retries. - */ @State(Scope.Benchmark) -@BenchmarkMode(Mode.SampleTime) +@BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.MICROSECONDS) @Warmup(iterations = 5) @Measurement(iterations = 5) diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2JsonProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2JsonProtocolBenchmark.java index 87ad57fd38fa..1983abf9a931 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2JsonProtocolBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2JsonProtocolBenchmark.java @@ -48,12 +48,8 @@ import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; import software.amazon.awssdk.services.dynamodb.model.PutItemResponse; -/** - * Isolated ser/de benchmark for V2 DynamoDB (JSON protocol). - * Measures only JSON parsing + object construction -- no HTTP, signing, or retries. - */ @State(Scope.Benchmark) -@BenchmarkMode(Mode.SampleTime) +@BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.MICROSECONDS) @Warmup(iterations = 5) @Measurement(iterations = 5) diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2QueryProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2QueryProtocolBenchmark.java index 1e6c6ac49b5d..6d902e72fb5f 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2QueryProtocolBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2QueryProtocolBenchmark.java @@ -42,12 +42,8 @@ import software.amazon.awssdk.services.sts.model.AssumeRoleResponse; import software.amazon.awssdk.utils.Pair; -/** - * Isolated ser/de benchmark for V2 STS (Query protocol). - * Measures only XML parsing + form encoding -- no HTTP, signing, or retries. - */ @State(Scope.Benchmark) -@BenchmarkMode(Mode.SampleTime) +@BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.MICROSECONDS) @Warmup(iterations = 5) @Measurement(iterations = 5) diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2RestJsonProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2RestJsonProtocolBenchmark.java index 6f76afece417..1f090b87b629 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2RestJsonProtocolBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2RestJsonProtocolBenchmark.java @@ -51,12 +51,8 @@ import software.amazon.awssdk.services.lambda.model.TracingConfig; import software.amazon.awssdk.services.lambda.model.TracingMode; -/** - * Isolated ser/de benchmark for V2 Lambda (REST-JSON protocol). - * Measures only JSON parsing + object construction -- no HTTP, signing, or retries. - */ @State(Scope.Benchmark) -@BenchmarkMode(Mode.SampleTime) +@BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.MICROSECONDS) @Warmup(iterations = 5) @Measurement(iterations = 5) diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2RestXmlProtocolBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2RestXmlProtocolBenchmark.java index e2c61142c356..171099bd1be6 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2RestXmlProtocolBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/protocol/V2RestXmlProtocolBenchmark.java @@ -53,12 +53,8 @@ import software.amazon.awssdk.services.cloudfront.model.S3OriginConfig; import software.amazon.awssdk.services.cloudfront.model.ViewerProtocolPolicy; -/** - * Isolated ser/de benchmark for V2 CloudFront (REST-XML protocol). - * Measures only XML parsing + object construction -- no HTTP, signing, or retries. - */ @State(Scope.Benchmark) -@BenchmarkMode(Mode.SampleTime) +@BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.MICROSECONDS) @Warmup(iterations = 5) @Measurement(iterations = 5) From 0537ec736ad474e5946d08e411a6d06c2de70584 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Wed, 11 Mar 2026 13:45:54 -0700 Subject: [PATCH 3/7] Fix inconsistencies, checkstyle suppressions --- .../software/amazon/awssdk/checkstyle-suppressions.xml | 2 +- .../awssdk/benchmark/protocol/V2RestJsonProtocolBenchmark.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build-tools/src/main/resources/software/amazon/awssdk/checkstyle-suppressions.xml b/build-tools/src/main/resources/software/amazon/awssdk/checkstyle-suppressions.xml index ab1f3ade8258..2a6e22ef28ba 100644 --- a/build-tools/src/main/resources/software/amazon/awssdk/checkstyle-suppressions.xml +++ b/build-tools/src/main/resources/software/amazon/awssdk/checkstyle-suppressions.xml @@ -52,7 +52,7 @@ + files=".*benchmark[\\/]protocol[\\/]V1.*\.java$"/> Date: Mon, 16 Mar 2026 15:52:38 -0700 Subject: [PATCH 4/7] Add http servlet roundtrip benchmarks --- .../protocol/ProtocolRoundtripServer.java | 70 +++++++++ .../protocol/ProtocolRoundtripServlet.java | 131 ++++++++++++++++ .../protocol/V1CborRoundtripBenchmark.java | 142 +++++++++++++++++ .../protocol/V1Ec2RoundtripBenchmark.java | 89 +++++++++++ .../protocol/V1JsonRoundtripBenchmark.java | 114 ++++++++++++++ .../protocol/V1QueryRoundtripBenchmark.java | 88 +++++++++++ .../V1RestJsonRoundtripBenchmark.java | 106 +++++++++++++ .../protocol/V1RestXmlRoundtripBenchmark.java | 120 ++++++++++++++ .../protocol/V2CborRoundtripBenchmark.java | 147 ++++++++++++++++++ .../protocol/V2Ec2RoundtripBenchmark.java | 91 +++++++++++ .../protocol/V2JsonRoundtripBenchmark.java | 116 ++++++++++++++ .../protocol/V2QueryRoundtripBenchmark.java | 90 +++++++++++ .../V2RestJsonRoundtripBenchmark.java | 109 +++++++++++++ .../protocol/V2RestXmlRoundtripBenchmark.java | 130 ++++++++++++++++ 14 files changed, 1543 insertions(+) create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServer.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServlet.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1CborRoundtripBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestJsonRoundtripBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2CborRoundtripBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestJsonRoundtripBenchmark.java create mode 100644 test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServer.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServer.java new file mode 100644 index 000000000000..96911c4e9442 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServer.java @@ -0,0 +1,70 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.apicall.protocol; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import software.amazon.awssdk.benchmark.utils.BenchmarkUtils; +import software.amazon.awssdk.utils.IoUtils; + +/** + * Lightweight Jetty server for protocol roundtrip benchmarks. + */ +class ProtocolRoundtripServer { + + private final Server server; + private final int port; + + ProtocolRoundtripServer(ProtocolRoundtripServlet servlet) throws IOException { + port = BenchmarkUtils.getUnusedPort(); + server = new Server(); + ServerConnector connector = new ServerConnector(server); + connector.setPort(port); + server.setConnectors(new Connector[] {connector}); + + ServletContextHandler context = new ServletContextHandler(server, "/", ServletContextHandler.SESSIONS); + context.addServlet(new ServletHolder(servlet), "/*"); + server.setHandler(context); + } + + void start() throws Exception { + server.start(); + } + + void stop() throws Exception { + server.stop(); + } + + URI getHttpUri() { + return URI.create("http://localhost:" + port); + } + + static byte[] loadFixture(String path) throws IOException { + try (InputStream is = ProtocolRoundtripServer.class.getClassLoader() + .getResourceAsStream("fixtures/" + path)) { + if (is == null) { + throw new IOException("Fixture not found: fixtures/" + path); + } + return IoUtils.toByteArray(is); + } + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServlet.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServlet.java new file mode 100644 index 000000000000..dd2a97f14ddb --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServlet.java @@ -0,0 +1,131 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.apicall.protocol; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Minimal servlet for protocol roundtrip benchmarks. Returns pre-loaded canned responses + * with zero request inspection overhead. Routes are matched by URI prefix or X-Amz-Target header. + */ +class ProtocolRoundtripServlet extends HttpServlet { + + private final Map targetRoutes = new ConcurrentHashMap<>(); + private final Map uriRoutes = new ConcurrentHashMap<>(); + private CannedResponse defaultResponse; + + /** + * Register a route matched by X-Amz-Target header value. + */ + ProtocolRoundtripServlet routeByTarget(String target, String contentType, byte[] body) { + targetRoutes.put(target, new CannedResponse(contentType, body)); + return this; + } + + /** + * Register a route matched by URI prefix. + */ + ProtocolRoundtripServlet routeByUri(String uriPrefix, String contentType, byte[] body) { + uriRoutes.put(uriPrefix, new CannedResponse(contentType, body)); + return this; + } + + /** + * Register a route matched by URI prefix with additional response headers. + */ + ProtocolRoundtripServlet routeByUri(String uriPrefix, String contentType, byte[] body, + Map headers) { + uriRoutes.put(uriPrefix, new CannedResponse(contentType, body, headers)); + return this; + } + + /** + * Default response when no route matches. + */ + ProtocolRoundtripServlet defaultRoute(String contentType, byte[] body) { + this.defaultResponse = new CannedResponse(contentType, body); + return this; + } + + @Override + protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException { + // Consume request body to simulate real HTTP exchange + byte[] buf = new byte[8192]; + while (req.getInputStream().read(buf) != -1) { + // drain + } + + CannedResponse canned = resolve(req); + if (canned == null) { + resp.sendError(404); + return; + } + + resp.setStatus(200); + resp.setContentType(canned.contentType); + resp.setContentLength(canned.body.length); + resp.setHeader("x-amzn-RequestId", "benchmark-request-id"); + if (canned.headers != null) { + canned.headers.forEach(resp::setHeader); + } + try (OutputStream os = resp.getOutputStream()) { + os.write(canned.body); + } + } + + private CannedResponse resolve(HttpServletRequest req) { + // Try X-Amz-Target first (JSON/CBOR protocols) + String target = req.getHeader("X-Amz-Target"); + if (target != null) { + CannedResponse r = targetRoutes.get(target); + if (r != null) { + return r; + } + } + + // Try URI prefix match (REST protocols) + String uri = req.getRequestURI(); + for (Map.Entry entry : uriRoutes.entrySet()) { + if (uri.contains(entry.getKey())) { + return entry.getValue(); + } + } + + return defaultResponse; + } + + private static class CannedResponse { + final String contentType; + final byte[] body; + final Map headers; + + CannedResponse(String contentType, byte[] body) { + this(contentType, body, null); + } + + CannedResponse(String contentType, byte[] body, Map headers) { + this.contentType = contentType; + this.body = body; + this.headers = headers; + } + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1CborRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1CborRoundtripBenchmark.java new file mode 100644 index 000000000000..1e2e369e1e49 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1CborRoundtripBenchmark.java @@ -0,0 +1,142 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.apicall.protocol; + +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.client.builder.AwsClientBuilder; +import com.amazonaws.protocol.rpcv2cbor.SdkStructuredCborFactory; +import com.amazonaws.protocol.rpcv2cbor.StructuredRpcV2CborGenerator; +import com.amazonaws.services.cloudwatch.AmazonCloudWatch; +import com.amazonaws.services.cloudwatch.AmazonCloudWatchClientBuilder; +import com.amazonaws.services.cloudwatch.model.GetMetricDataRequest; +import com.amazonaws.services.cloudwatch.model.Metric; +import com.amazonaws.services.cloudwatch.model.MetricDataQuery; +import com.amazonaws.services.cloudwatch.model.MetricStat; +import java.util.Date; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +/** + * V1 roundtrip benchmark for SmithyRpcV2 CBOR protocol using CloudWatch GetMetricData via HTTP servlet. + */ +@State(Scope.Benchmark) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +public class V1CborRoundtripBenchmark { + + private ProtocolRoundtripServer server; + private AmazonCloudWatch client; + private GetMetricDataRequest request; + + @Setup(Level.Trial) + public void setup() throws Exception { + byte[] response = createCborResponseFixture(); + + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() + .defaultRoute("application/cbor", response); + + server = new ProtocolRoundtripServer(servlet); + server.start(); + + client = AmazonCloudWatchClientBuilder.standard() + .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration( + server.getHttpUri().toString(), "us-east-1")) + .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("test", "test"))) + .build(); + + Date end = Date.from(java.time.Instant.parse("2026-03-09T00:00:00Z")); + Date start = Date.from(java.time.Instant.parse("2026-03-09T00:00:00Z").minusSeconds(3600)); + request = new GetMetricDataRequest() + .withStartTime(start) + .withEndTime(end) + .withMaxDatapoints(1000) + .withMetricDataQueries( + new MetricDataQuery() + .withId("cpu") + .withMetricStat(new MetricStat() + .withMetric(new Metric() + .withNamespace("AWS/EC2") + .withMetricName("CPUUtilization")) + .withPeriod(300) + .withStat("Average")) + .withReturnData(true)); + } + + @TearDown(Level.Trial) + public void tearDown() throws Exception { + client.shutdown(); + server.stop(); + } + + @Benchmark + public void getMetricData(Blackhole bh) { + bh.consume(client.getMetricData(request)); + } + + private static byte[] createCborResponseFixture() { + StructuredRpcV2CborGenerator gen = + SdkStructuredCborFactory.SDK_CBOR_FACTORY.createWriter("application/cbor"); + gen.writeStartObject(); + gen.writeFieldName("MetricDataResults"); + gen.writeStartArray(); + gen.writeStartObject(); + gen.writeFieldName("Id"); + gen.writeValue("cpu"); + gen.writeFieldName("Label"); + gen.writeValue("CPUUtilization"); + gen.writeFieldName("StatusCode"); + gen.writeValue("Complete"); + gen.writeFieldName("Timestamps"); + gen.writeStartArray(); + long base = 1772611200L; + for (int i = 0; i < 12; i++) { + gen.writeValue((double) ((base + i * 300) * 1000)); + } + gen.writeEndArray(); + gen.writeFieldName("Values"); + gen.writeStartArray(); + for (int i = 0; i < 12; i++) { + gen.writeValue(45.2 + i * 1.1); + } + gen.writeEndArray(); + gen.writeFieldName("Messages"); + gen.writeStartArray(); + gen.writeEndArray(); + gen.writeEndObject(); + gen.writeEndArray(); + gen.writeFieldName("Messages"); + gen.writeStartArray(); + gen.writeEndArray(); + gen.writeEndObject(); + return gen.getBytes(); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java new file mode 100644 index 000000000000..ebe47b85a100 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java @@ -0,0 +1,89 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.apicall.protocol; + +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.client.builder.AwsClientBuilder; +import com.amazonaws.services.ec2.AmazonEC2; +import com.amazonaws.services.ec2.AmazonEC2ClientBuilder; +import com.amazonaws.services.ec2.model.DescribeInstancesRequest; +import com.amazonaws.services.ec2.model.Filter; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +/** + * V1 roundtrip benchmark for EC2 protocol using EC2 DescribeInstances via HTTP servlet. + */ +@State(Scope.Benchmark) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +public class V1Ec2RoundtripBenchmark { + + private ProtocolRoundtripServer server; + private AmazonEC2 client; + private DescribeInstancesRequest request; + + @Setup(Level.Trial) + public void setup() throws Exception { + byte[] response = ProtocolRoundtripServer.loadFixture("ec2-protocol/describe-instances-response.xml"); + + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() + .defaultRoute("text/xml", response); + + server = new ProtocolRoundtripServer(servlet); + server.start(); + + client = AmazonEC2ClientBuilder.standard() + .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration( + server.getHttpUri().toString(), "us-east-1")) + .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("test", "test"))) + .build(); + + request = new DescribeInstancesRequest() + .withInstanceIds("i-0abcdef1234567890") + .withFilters( + new Filter("instance-state-name").withValues("running"), + new Filter("instance-type").withValues("m5.xlarge")) + .withMaxResults(100); + } + + @TearDown(Level.Trial) + public void tearDown() throws Exception { + client.shutdown(); + server.stop(); + } + + @Benchmark + public void describeInstances(Blackhole bh) { + bh.consume(client.describeInstances(request)); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java new file mode 100644 index 000000000000..d931402e15a0 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java @@ -0,0 +1,114 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.apicall.protocol; + +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.client.builder.AwsClientBuilder; +import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; +import com.amazonaws.services.dynamodbv2.model.AttributeValue; +import com.amazonaws.services.dynamodbv2.model.PutItemRequest; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +/** + * V1 roundtrip benchmark for JSON protocol (aws-json) using DynamoDB PutItem via HTTP servlet. + */ +@State(Scope.Benchmark) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +public class V1JsonRoundtripBenchmark { + + private ProtocolRoundtripServer server; + private AmazonDynamoDB client; + private PutItemRequest putItemRequest; + + @Setup(Level.Trial) + public void setup() throws Exception { + byte[] response = ProtocolRoundtripServer.loadFixture("json-protocol/putitem-response.json"); + + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() + .routeByTarget("DynamoDB_20120810.PutItem", "application/x-amz-json-1.0", response); + + server = new ProtocolRoundtripServer(servlet); + server.start(); + + client = AmazonDynamoDBClientBuilder.standard() + .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration( + server.getHttpUri().toString(), "us-east-1")) + .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("test", "test"))) + .build(); + + putItemRequest = new PutItemRequest() + .withTableName("benchmark-table") + .withItem(itemMap()); + } + + @TearDown(Level.Trial) + public void tearDown() throws Exception { + client.shutdown(); + server.stop(); + } + + @Benchmark + public void putItem(Blackhole bh) { + bh.consume(client.putItem(putItemRequest)); + } + + private static Map itemMap() { + Map item = new HashMap<>(); + item.put("pk", new AttributeValue().withS("benchmark-key")); + item.put("sk", new AttributeValue().withN("100")); + item.put("stringField", new AttributeValue().withS("test-value")); + item.put("numberField", new AttributeValue().withN("123.456")); + item.put("binaryField", new AttributeValue().withB(ByteBuffer.wrap("hello world".getBytes()))); + item.put("stringSetField", new AttributeValue().withSS("value1", "value2", "value3")); + item.put("numberSetField", new AttributeValue().withNS("1.1", "2.2", "3.3")); + item.put("boolField", new AttributeValue().withBOOL(false)); + item.put("nullField", new AttributeValue().withNULL(true)); + Map deep = new HashMap<>(); + deep.put("level2", new AttributeValue().withN("999")); + Map nested = new HashMap<>(); + nested.put("nested", new AttributeValue().withS("nested-value")); + nested.put("deepNested", new AttributeValue().withM(deep)); + item.put("mapField", new AttributeValue().withM(nested)); + item.put("listField", new AttributeValue().withL( + new AttributeValue().withS("item1"), + new AttributeValue().withN("42"), + new AttributeValue().withBOOL(true), + new AttributeValue().withNULL(true))); + return item; + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java new file mode 100644 index 000000000000..9659bec30100 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java @@ -0,0 +1,88 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.apicall.protocol; + +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.client.builder.AwsClientBuilder; +import com.amazonaws.services.securitytoken.AWSSecurityTokenService; +import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder; +import com.amazonaws.services.securitytoken.model.AssumeRoleRequest; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +/** + * V1 roundtrip benchmark for Query protocol using STS AssumeRole via HTTP servlet. + */ +@State(Scope.Benchmark) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +public class V1QueryRoundtripBenchmark { + + private ProtocolRoundtripServer server; + private AWSSecurityTokenService client; + private AssumeRoleRequest request; + + @Setup(Level.Trial) + public void setup() throws Exception { + byte[] response = ProtocolRoundtripServer.loadFixture("query-protocol/assumerole-response.xml"); + + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() + .defaultRoute("text/xml", response); + + server = new ProtocolRoundtripServer(servlet); + server.start(); + + client = AWSSecurityTokenServiceClientBuilder.standard() + .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration( + server.getHttpUri().toString(), "us-east-1")) + .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("test", "test"))) + .build(); + + request = new AssumeRoleRequest() + .withRoleArn("arn:aws:iam::123456789012:role/benchmark-role") + .withRoleSessionName("benchmark-session") + .withDurationSeconds(3600) + .withExternalId("benchmark-external-id") + .withPolicy("{\"Version\":\"2012-10-17\"}"); + } + + @TearDown(Level.Trial) + public void tearDown() throws Exception { + client.shutdown(); + server.stop(); + } + + @Benchmark + public void assumeRole(Blackhole bh) { + bh.consume(client.assumeRole(request)); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestJsonRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestJsonRoundtripBenchmark.java new file mode 100644 index 000000000000..4283ac55a885 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestJsonRoundtripBenchmark.java @@ -0,0 +1,106 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.apicall.protocol; + +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.client.builder.AwsClientBuilder; +import com.amazonaws.services.lambda.AWSLambda; +import com.amazonaws.services.lambda.AWSLambdaClientBuilder; +import com.amazonaws.services.lambda.model.CreateFunctionRequest; +import com.amazonaws.services.lambda.model.Environment; +import com.amazonaws.services.lambda.model.FunctionCode; +import com.amazonaws.services.lambda.model.Runtime; +import com.amazonaws.services.lambda.model.TracingConfig; +import com.amazonaws.services.lambda.model.TracingMode; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +/** + * V1 roundtrip benchmark for REST-JSON protocol using Lambda CreateFunction via HTTP servlet. + */ +@State(Scope.Benchmark) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +public class V1RestJsonRoundtripBenchmark { + + private ProtocolRoundtripServer server; + private AWSLambda client; + private CreateFunctionRequest request; + + @Setup(Level.Trial) + public void setup() throws Exception { + byte[] response = ProtocolRoundtripServer.loadFixture("rest-json-protocol/createfunction-response.json"); + + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() + .routeByUri("/2015-03-31/functions", "application/json", response); + + server = new ProtocolRoundtripServer(servlet); + server.start(); + + client = AWSLambdaClientBuilder.standard() + .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration( + server.getHttpUri().toString(), "us-east-1")) + .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("test", "test"))) + .build(); + + Map envVars = new HashMap<>(); + envVars.put("ENV_VAR_1", "value1"); + + request = new CreateFunctionRequest() + .withFunctionName("benchmark-function") + .withRuntime(Runtime.Java8) + .withRole("arn:aws:iam::123456789012:role/lambda-role") + .withHandler("com.example.Handler::handleRequest") + .withCode(new FunctionCode() + .withS3Bucket("my-deploy-bucket") + .withS3Key("code/function.zip")) + .withDescription("Benchmark test function") + .withTimeout(30) + .withMemorySize(512) + .withPublish(false) + .withEnvironment(new Environment().withVariables(envVars)) + .withTracingConfig(new TracingConfig().withMode(TracingMode.Active)); + } + + @TearDown(Level.Trial) + public void tearDown() throws Exception { + client.shutdown(); + server.stop(); + } + + @Benchmark + public void createFunction(Blackhole bh) { + bh.consume(client.createFunction(request)); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java new file mode 100644 index 000000000000..ac9968862e0a --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java @@ -0,0 +1,120 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.apicall.protocol; + +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.client.builder.AwsClientBuilder; +import com.amazonaws.services.cloudfront.AmazonCloudFront; +import com.amazonaws.services.cloudfront.AmazonCloudFrontClientBuilder; +import com.amazonaws.services.cloudfront.model.Aliases; +import com.amazonaws.services.cloudfront.model.AllowedMethods; +import com.amazonaws.services.cloudfront.model.CachedMethods; +import com.amazonaws.services.cloudfront.model.CreateDistributionRequest; +import com.amazonaws.services.cloudfront.model.DefaultCacheBehavior; +import com.amazonaws.services.cloudfront.model.DistributionConfig; +import com.amazonaws.services.cloudfront.model.Method; +import com.amazonaws.services.cloudfront.model.Origin; +import com.amazonaws.services.cloudfront.model.Origins; +import com.amazonaws.services.cloudfront.model.S3OriginConfig; +import com.amazonaws.services.cloudfront.model.ViewerProtocolPolicy; +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +/** + * V1 roundtrip benchmark for REST-XML protocol using CloudFront CreateDistribution via HTTP servlet. + */ +@State(Scope.Benchmark) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +public class V1RestXmlRoundtripBenchmark { + + private ProtocolRoundtripServer server; + private AmazonCloudFront client; + private CreateDistributionRequest request; + + @Setup(Level.Trial) + public void setup() throws Exception { + byte[] response = ProtocolRoundtripServer.loadFixture("rest-xml-protocol/create-distribution-response.xml"); + + Map headers = Collections.singletonMap("ETag", "E2QWRUHEXAMPLE"); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() + .routeByUri("/2020-05-31/distribution", "application/xml", response, headers); + + server = new ProtocolRoundtripServer(servlet); + server.start(); + + client = AmazonCloudFrontClientBuilder.standard() + .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration( + server.getHttpUri().toString(), "us-east-1")) + .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("test", "test"))) + .build(); + + request = new CreateDistributionRequest() + .withDistributionConfig(new DistributionConfig() + .withCallerReference("benchmark-ref-2024") + .withAliases(new Aliases() + .withQuantity(2) + .withItems("www.example.com", "cdn.example.com")) + .withDefaultRootObject("index.html") + .withOrigins(new Origins() + .withQuantity(1) + .withItems(new Origin() + .withId("myS3Origin") + .withDomainName("mybucket.s3.amazonaws.com") + .withOriginPath("/production") + .withS3OriginConfig(new S3OriginConfig() + .withOriginAccessIdentity("origin-access-identity/cloudfront/E127EXAMPLE51Z")))) + .withDefaultCacheBehavior(new DefaultCacheBehavior() + .withTargetOriginId("myS3Origin") + .withViewerProtocolPolicy(ViewerProtocolPolicy.RedirectToHttps) + .withAllowedMethods(new AllowedMethods() + .withQuantity(3) + .withItems(Method.GET, Method.HEAD, Method.OPTIONS) + .withCachedMethods(new CachedMethods() + .withQuantity(2) + .withItems(Method.GET, Method.HEAD))) + .withCompress(true))); + } + + @TearDown(Level.Trial) + public void tearDown() throws Exception { + client.shutdown(); + server.stop(); + } + + @Benchmark + public void createDistribution(Blackhole bh) { + bh.consume(client.createDistribution(request)); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2CborRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2CborRoundtripBenchmark.java new file mode 100644 index 000000000000..13c92fc7a771 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2CborRoundtripBenchmark.java @@ -0,0 +1,147 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.apicall.protocol; + +import java.time.Instant; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.http.apache5.Apache5HttpClient; +import software.amazon.awssdk.protocols.json.StructuredJsonGenerator; +import software.amazon.awssdk.protocols.rpcv2.internal.SdkStructuredRpcV2CborFactory; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.cloudwatch.CloudWatchClient; +import software.amazon.awssdk.services.cloudwatch.model.GetMetricDataRequest; +import software.amazon.awssdk.services.cloudwatch.model.Metric; +import software.amazon.awssdk.services.cloudwatch.model.MetricDataQuery; +import software.amazon.awssdk.services.cloudwatch.model.MetricStat; + +/** + * Roundtrip benchmark for SmithyRpcV2 CBOR protocol using CloudWatch GetMetricData via HTTP servlet. + */ +@State(Scope.Benchmark) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +public class V2CborRoundtripBenchmark { + + private ProtocolRoundtripServer server; + private CloudWatchClient client; + private GetMetricDataRequest request; + + @Setup(Level.Trial) + public void setup() throws Exception { + byte[] response = createCborResponseFixture(); + + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() + .defaultRoute("application/cbor", response); + + server = new ProtocolRoundtripServer(servlet); + server.start(); + + client = CloudWatchClient.builder() + .endpointOverride(server.getHttpUri()) + .region(Region.US_EAST_1) + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("test", "test"))) + .httpClient(Apache5HttpClient.create()) + .build(); + + Instant end = Instant.parse("2026-03-09T00:00:00Z"); + Instant start = end.minusSeconds(3600); + request = GetMetricDataRequest.builder() + .startTime(start) + .endTime(end) + .maxDatapoints(1000) + .metricDataQueries( + MetricDataQuery.builder() + .id("cpu") + .metricStat(MetricStat.builder() + .metric(Metric.builder() + .namespace("AWS/EC2") + .metricName("CPUUtilization") + .build()) + .period(300) + .stat("Average") + .build()) + .returnData(true) + .build()) + .build(); + } + + @TearDown(Level.Trial) + public void tearDown() throws Exception { + client.close(); + server.stop(); + } + + @Benchmark + public void getMetricData(Blackhole bh) { + bh.consume(client.getMetricData(request)); + } + + private static byte[] createCborResponseFixture() { + StructuredJsonGenerator gen = + SdkStructuredRpcV2CborFactory.SDK_CBOR_FACTORY.createWriter("application/cbor"); + gen.writeStartObject(); + gen.writeFieldName("MetricDataResults"); + gen.writeStartArray(); + gen.writeStartObject(); + gen.writeFieldName("Id"); + gen.writeValue("cpu"); + gen.writeFieldName("Label"); + gen.writeValue("CPUUtilization"); + gen.writeFieldName("StatusCode"); + gen.writeValue("Complete"); + gen.writeFieldName("Timestamps"); + gen.writeStartArray(); + long base = 1772611200L; + for (int i = 0; i < 12; i++) { + gen.writeValue((double) ((base + i * 300) * 1000)); + } + gen.writeEndArray(); + gen.writeFieldName("Values"); + gen.writeStartArray(); + for (int i = 0; i < 12; i++) { + gen.writeValue(45.2 + i * 1.1); + } + gen.writeEndArray(); + gen.writeFieldName("Messages"); + gen.writeStartArray(); + gen.writeEndArray(); + gen.writeEndObject(); + gen.writeEndArray(); + gen.writeFieldName("Messages"); + gen.writeStartArray(); + gen.writeEndArray(); + gen.writeEndObject(); + return gen.getBytes(); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java new file mode 100644 index 000000000000..c52077bcadf3 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java @@ -0,0 +1,91 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.apicall.protocol; + +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.http.apache5.Apache5HttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.ec2.Ec2Client; +import software.amazon.awssdk.services.ec2.model.DescribeInstancesRequest; +import software.amazon.awssdk.services.ec2.model.Filter; + +/** + * Roundtrip benchmark for EC2 protocol using EC2 DescribeInstances via HTTP servlet. + */ +@State(Scope.Benchmark) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +public class V2Ec2RoundtripBenchmark { + + private ProtocolRoundtripServer server; + private Ec2Client client; + private DescribeInstancesRequest request; + + @Setup(Level.Trial) + public void setup() throws Exception { + byte[] response = ProtocolRoundtripServer.loadFixture("ec2-protocol/describe-instances-response.xml"); + + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() + .defaultRoute("text/xml", response); + + server = new ProtocolRoundtripServer(servlet); + server.start(); + + client = Ec2Client.builder() + .endpointOverride(server.getHttpUri()) + .region(Region.US_EAST_1) + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("test", "test"))) + .httpClient(Apache5HttpClient.create()) + .build(); + + request = DescribeInstancesRequest.builder() + .instanceIds("i-0abcdef1234567890") + .filters( + Filter.builder().name("instance-state-name").values("running").build(), + Filter.builder().name("instance-type").values("m5.xlarge").build()) + .maxResults(100) + .build(); + } + + @TearDown(Level.Trial) + public void tearDown() throws Exception { + client.close(); + server.stop(); + } + + @Benchmark + public void describeInstances(Blackhole bh) { + bh.consume(client.describeInstances(request)); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java new file mode 100644 index 000000000000..2c6453e9b79a --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java @@ -0,0 +1,116 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.apicall.protocol; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.http.apache5.Apache5HttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; + +/** + * Roundtrip benchmark for JSON protocol (aws-json) using DynamoDB PutItem via HTTP servlet. + */ +@State(Scope.Benchmark) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +public class V2JsonRoundtripBenchmark { + + private ProtocolRoundtripServer server; + private DynamoDbClient client; + private PutItemRequest putItemRequest; + + @Setup(Level.Trial) + public void setup() throws Exception { + byte[] response = ProtocolRoundtripServer.loadFixture("json-protocol/putitem-response.json"); + + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() + .routeByTarget("DynamoDB_20120810.PutItem", "application/x-amz-json-1.0", response); + + server = new ProtocolRoundtripServer(servlet); + server.start(); + + client = DynamoDbClient.builder() + .endpointOverride(server.getHttpUri()) + .region(Region.US_EAST_1) + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("test", "test"))) + .httpClient(Apache5HttpClient.create()) + .build(); + + putItemRequest = PutItemRequest.builder() + .tableName("benchmark-table") + .item(itemMap()) + .build(); + } + + @TearDown(Level.Trial) + public void tearDown() throws Exception { + client.close(); + server.stop(); + } + + @Benchmark + public void putItem(Blackhole bh) { + bh.consume(client.putItem(putItemRequest)); + } + + private static Map itemMap() { + Map item = new HashMap<>(); + item.put("pk", AttributeValue.fromS("benchmark-key")); + item.put("sk", AttributeValue.fromN("100")); + item.put("stringField", AttributeValue.fromS("test-value")); + item.put("numberField", AttributeValue.fromN("123.456")); + item.put("binaryField", AttributeValue.fromB(SdkBytes.fromUtf8String("hello world"))); + item.put("stringSetField", AttributeValue.builder().ss("value1", "value2", "value3").build()); + item.put("numberSetField", AttributeValue.builder().ns("1.1", "2.2", "3.3").build()); + item.put("boolField", AttributeValue.fromBool(false)); + item.put("nullField", AttributeValue.builder().nul(true).build()); + Map deep = new HashMap<>(); + deep.put("level2", AttributeValue.fromN("999")); + Map nested = new HashMap<>(); + nested.put("nested", AttributeValue.fromS("nested-value")); + nested.put("deepNested", AttributeValue.fromM(deep)); + item.put("mapField", AttributeValue.fromM(nested)); + item.put("listField", AttributeValue.builder().l( + AttributeValue.fromS("item1"), + AttributeValue.fromN("42"), + AttributeValue.fromBool(true), + AttributeValue.builder().nul(true).build()).build()); + return item; + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java new file mode 100644 index 000000000000..a1bbcbcc1b79 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java @@ -0,0 +1,90 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.apicall.protocol; + +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.http.apache5.Apache5HttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.sts.StsClient; +import software.amazon.awssdk.services.sts.model.AssumeRoleRequest; + +/** + * Roundtrip benchmark for Query protocol using STS AssumeRole via HTTP servlet. + */ +@State(Scope.Benchmark) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +public class V2QueryRoundtripBenchmark { + + private ProtocolRoundtripServer server; + private StsClient client; + private AssumeRoleRequest request; + + @Setup(Level.Trial) + public void setup() throws Exception { + byte[] response = ProtocolRoundtripServer.loadFixture("query-protocol/assumerole-response.xml"); + + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() + .defaultRoute("text/xml", response); + + server = new ProtocolRoundtripServer(servlet); + server.start(); + + client = StsClient.builder() + .endpointOverride(server.getHttpUri()) + .region(Region.US_EAST_1) + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("test", "test"))) + .httpClient(Apache5HttpClient.create()) + .build(); + + request = AssumeRoleRequest.builder() + .roleArn("arn:aws:iam::123456789012:role/benchmark-role") + .roleSessionName("benchmark-session") + .durationSeconds(3600) + .externalId("benchmark-external-id") + .policy("{\"Version\":\"2012-10-17\"}") + .build(); + } + + @TearDown(Level.Trial) + public void tearDown() throws Exception { + client.close(); + server.stop(); + } + + @Benchmark + public void assumeRole(Blackhole bh) { + bh.consume(client.assumeRole(request)); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestJsonRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestJsonRoundtripBenchmark.java new file mode 100644 index 000000000000..f5dbfab3b38b --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestJsonRoundtripBenchmark.java @@ -0,0 +1,109 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.apicall.protocol; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.http.apache5.Apache5HttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.lambda.LambdaClient; +import software.amazon.awssdk.services.lambda.model.CreateFunctionRequest; +import software.amazon.awssdk.services.lambda.model.Environment; +import software.amazon.awssdk.services.lambda.model.FunctionCode; +import software.amazon.awssdk.services.lambda.model.Runtime; +import software.amazon.awssdk.services.lambda.model.TracingConfig; +import software.amazon.awssdk.services.lambda.model.TracingMode; + +/** + * Roundtrip benchmark for REST-JSON protocol using Lambda CreateFunction via HTTP servlet. + */ +@State(Scope.Benchmark) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +public class V2RestJsonRoundtripBenchmark { + + private ProtocolRoundtripServer server; + private LambdaClient client; + private CreateFunctionRequest request; + + @Setup(Level.Trial) + public void setup() throws Exception { + byte[] response = ProtocolRoundtripServer.loadFixture("rest-json-protocol/createfunction-response.json"); + + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() + .routeByUri("/2015-03-31/functions", "application/json", response); + + server = new ProtocolRoundtripServer(servlet); + server.start(); + + client = LambdaClient.builder() + .endpointOverride(server.getHttpUri()) + .region(Region.US_EAST_1) + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("test", "test"))) + .httpClient(Apache5HttpClient.create()) + .build(); + + Map envVars = new HashMap<>(); + envVars.put("ENV_VAR_1", "value1"); + + request = CreateFunctionRequest.builder() + .functionName("benchmark-function") + .runtime(Runtime.JAVA8) + .role("arn:aws:iam::123456789012:role/lambda-role") + .handler("com.example.Handler::handleRequest") + .code(FunctionCode.builder() + .s3Bucket("my-deploy-bucket") + .s3Key("code/function.zip") + .build()) + .description("Benchmark test function") + .timeout(30) + .memorySize(512) + .publish(false) + .environment(Environment.builder().variables(envVars).build()) + .tracingConfig(TracingConfig.builder().mode(TracingMode.ACTIVE).build()) + .build(); + } + + @TearDown(Level.Trial) + public void tearDown() throws Exception { + client.close(); + server.stop(); + } + + @Benchmark + public void createFunction(Blackhole bh) { + bh.consume(client.createFunction(request)); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java new file mode 100644 index 000000000000..eee8fb19e3dc --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java @@ -0,0 +1,130 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.benchmark.apicall.protocol; + +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.http.apache5.Apache5HttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.cloudfront.CloudFrontClient; +import software.amazon.awssdk.services.cloudfront.model.Aliases; +import software.amazon.awssdk.services.cloudfront.model.AllowedMethods; +import software.amazon.awssdk.services.cloudfront.model.CachedMethods; +import software.amazon.awssdk.services.cloudfront.model.CreateDistributionRequest; +import software.amazon.awssdk.services.cloudfront.model.DefaultCacheBehavior; +import software.amazon.awssdk.services.cloudfront.model.DistributionConfig; +import software.amazon.awssdk.services.cloudfront.model.Method; +import software.amazon.awssdk.services.cloudfront.model.Origin; +import software.amazon.awssdk.services.cloudfront.model.Origins; +import software.amazon.awssdk.services.cloudfront.model.S3OriginConfig; +import software.amazon.awssdk.services.cloudfront.model.ViewerProtocolPolicy; + +/** + * Roundtrip benchmark for REST-XML protocol using CloudFront CreateDistribution via HTTP servlet. + */ +@State(Scope.Benchmark) +@Warmup(iterations = 5) +@Measurement(iterations = 5) +@Fork(2) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +public class V2RestXmlRoundtripBenchmark { + + private ProtocolRoundtripServer server; + private CloudFrontClient client; + private CreateDistributionRequest request; + + @Setup(Level.Trial) + public void setup() throws Exception { + byte[] response = ProtocolRoundtripServer.loadFixture("rest-xml-protocol/create-distribution-response.xml"); + + Map headers = Collections.singletonMap("ETag", "E2QWRUHEXAMPLE"); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() + .routeByUri("/2020-05-31/distribution", "application/xml", response, headers); + + server = new ProtocolRoundtripServer(servlet); + server.start(); + + client = CloudFrontClient.builder() + .endpointOverride(server.getHttpUri()) + .region(Region.US_EAST_1) + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("test", "test"))) + .httpClient(Apache5HttpClient.create()) + .build(); + + request = CreateDistributionRequest.builder() + .distributionConfig(DistributionConfig.builder() + .callerReference("benchmark-ref-2024") + .aliases(Aliases.builder() + .quantity(2) + .items("www.example.com", "cdn.example.com") + .build()) + .defaultRootObject("index.html") + .origins(Origins.builder() + .quantity(1) + .items(Origin.builder() + .id("myS3Origin") + .domainName("mybucket.s3.amazonaws.com") + .originPath("/production") + .s3OriginConfig(S3OriginConfig.builder() + .originAccessIdentity("origin-access-identity/cloudfront/E127EXAMPLE51Z") + .build()) + .build()) + .build()) + .defaultCacheBehavior(DefaultCacheBehavior.builder() + .targetOriginId("myS3Origin") + .viewerProtocolPolicy(ViewerProtocolPolicy.REDIRECT_TO_HTTPS) + .allowedMethods(AllowedMethods.builder() + .quantity(3) + .items(Method.GET, Method.HEAD, Method.OPTIONS) + .cachedMethods(CachedMethods.builder() + .quantity(2) + .items(Method.GET, Method.HEAD) + .build()) + .build()) + .compress(true) + .build()) + .build()) + .build(); + } + + @TearDown(Level.Trial) + public void tearDown() throws Exception { + client.close(); + server.stop(); + } + + @Benchmark + public void createDistribution(Blackhole bh) { + bh.consume(client.createDistribution(request)); + } +} From 29cdadb83eb53ab5c0deee2eb132ca07d348e577 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Tue, 17 Mar 2026 09:53:10 -0700 Subject: [PATCH 5/7] Change timeunit to seconds --- .../benchmark/apicall/protocol/V1CborRoundtripBenchmark.java | 2 +- .../benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java | 2 +- .../benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java | 2 +- .../benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java | 2 +- .../apicall/protocol/V1RestJsonRoundtripBenchmark.java | 2 +- .../benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java | 2 +- .../benchmark/apicall/protocol/V2CborRoundtripBenchmark.java | 2 +- .../benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java | 2 +- .../benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java | 2 +- .../benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java | 2 +- .../apicall/protocol/V2RestJsonRoundtripBenchmark.java | 2 +- .../benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1CborRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1CborRoundtripBenchmark.java index 1e2e369e1e49..402bec59dc1c 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1CborRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1CborRoundtripBenchmark.java @@ -50,7 +50,7 @@ @Measurement(iterations = 5) @Fork(2) @BenchmarkMode(Mode.Throughput) -@OutputTimeUnit(TimeUnit.MICROSECONDS) +@OutputTimeUnit(TimeUnit.SECONDS) public class V1CborRoundtripBenchmark { private ProtocolRoundtripServer server; diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java index ebe47b85a100..aab3116f4a29 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java @@ -45,7 +45,7 @@ @Measurement(iterations = 5) @Fork(2) @BenchmarkMode(Mode.Throughput) -@OutputTimeUnit(TimeUnit.MICROSECONDS) +@OutputTimeUnit(TimeUnit.SECONDS) public class V1Ec2RoundtripBenchmark { private ProtocolRoundtripServer server; diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java index d931402e15a0..0e345a761c3d 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java @@ -48,7 +48,7 @@ @Measurement(iterations = 5) @Fork(2) @BenchmarkMode(Mode.Throughput) -@OutputTimeUnit(TimeUnit.MICROSECONDS) +@OutputTimeUnit(TimeUnit.SECONDS) public class V1JsonRoundtripBenchmark { private ProtocolRoundtripServer server; diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java index 9659bec30100..cf77e8f91f15 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java @@ -44,7 +44,7 @@ @Measurement(iterations = 5) @Fork(2) @BenchmarkMode(Mode.Throughput) -@OutputTimeUnit(TimeUnit.MICROSECONDS) +@OutputTimeUnit(TimeUnit.SECONDS) public class V1QueryRoundtripBenchmark { private ProtocolRoundtripServer server; diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestJsonRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestJsonRoundtripBenchmark.java index 4283ac55a885..124bcda3452d 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestJsonRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestJsonRoundtripBenchmark.java @@ -51,7 +51,7 @@ @Measurement(iterations = 5) @Fork(2) @BenchmarkMode(Mode.Throughput) -@OutputTimeUnit(TimeUnit.MICROSECONDS) +@OutputTimeUnit(TimeUnit.SECONDS) public class V1RestJsonRoundtripBenchmark { private ProtocolRoundtripServer server; diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java index ac9968862e0a..78bd18462dc5 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java @@ -56,7 +56,7 @@ @Measurement(iterations = 5) @Fork(2) @BenchmarkMode(Mode.Throughput) -@OutputTimeUnit(TimeUnit.MICROSECONDS) +@OutputTimeUnit(TimeUnit.SECONDS) public class V1RestXmlRoundtripBenchmark { private ProtocolRoundtripServer server; diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2CborRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2CborRoundtripBenchmark.java index 13c92fc7a771..74af8b2563b0 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2CborRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2CborRoundtripBenchmark.java @@ -50,7 +50,7 @@ @Measurement(iterations = 5) @Fork(2) @BenchmarkMode(Mode.Throughput) -@OutputTimeUnit(TimeUnit.MICROSECONDS) +@OutputTimeUnit(TimeUnit.SECONDS) public class V2CborRoundtripBenchmark { private ProtocolRoundtripServer server; diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java index c52077bcadf3..e54090850fea 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java @@ -45,7 +45,7 @@ @Measurement(iterations = 5) @Fork(2) @BenchmarkMode(Mode.Throughput) -@OutputTimeUnit(TimeUnit.MICROSECONDS) +@OutputTimeUnit(TimeUnit.SECONDS) public class V2Ec2RoundtripBenchmark { private ProtocolRoundtripServer server; diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java index 2c6453e9b79a..110c8c140637 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java @@ -48,7 +48,7 @@ @Measurement(iterations = 5) @Fork(2) @BenchmarkMode(Mode.Throughput) -@OutputTimeUnit(TimeUnit.MICROSECONDS) +@OutputTimeUnit(TimeUnit.SECONDS) public class V2JsonRoundtripBenchmark { private ProtocolRoundtripServer server; diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java index a1bbcbcc1b79..d2757e96bcf0 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java @@ -44,7 +44,7 @@ @Measurement(iterations = 5) @Fork(2) @BenchmarkMode(Mode.Throughput) -@OutputTimeUnit(TimeUnit.MICROSECONDS) +@OutputTimeUnit(TimeUnit.SECONDS) public class V2QueryRoundtripBenchmark { private ProtocolRoundtripServer server; diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestJsonRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestJsonRoundtripBenchmark.java index f5dbfab3b38b..667d3ba419df 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestJsonRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestJsonRoundtripBenchmark.java @@ -51,7 +51,7 @@ @Measurement(iterations = 5) @Fork(2) @BenchmarkMode(Mode.Throughput) -@OutputTimeUnit(TimeUnit.MICROSECONDS) +@OutputTimeUnit(TimeUnit.SECONDS) public class V2RestJsonRoundtripBenchmark { private ProtocolRoundtripServer server; diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java index eee8fb19e3dc..f3b11e6e32b9 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java @@ -56,7 +56,7 @@ @Measurement(iterations = 5) @Fork(2) @BenchmarkMode(Mode.Throughput) -@OutputTimeUnit(TimeUnit.MICROSECONDS) +@OutputTimeUnit(TimeUnit.SECONDS) public class V2RestXmlRoundtripBenchmark { private ProtocolRoundtripServer server; From fa0445caaf07fb7b5d88130d9a38a8fe7be123fa Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Tue, 17 Mar 2026 13:57:48 -0700 Subject: [PATCH 6/7] Simplify servlet --- .../protocol/ProtocolRoundtripServlet.java | 105 +----------------- .../protocol/V1CborRoundtripBenchmark.java | 3 +- .../protocol/V1Ec2RoundtripBenchmark.java | 3 +- .../protocol/V1JsonRoundtripBenchmark.java | 3 +- .../protocol/V1QueryRoundtripBenchmark.java | 3 +- .../V1RestJsonRoundtripBenchmark.java | 3 +- .../protocol/V1RestXmlRoundtripBenchmark.java | 6 +- .../protocol/V2CborRoundtripBenchmark.java | 3 +- .../protocol/V2Ec2RoundtripBenchmark.java | 3 +- .../protocol/V2JsonRoundtripBenchmark.java | 3 +- .../protocol/V2QueryRoundtripBenchmark.java | 3 +- .../V2RestJsonRoundtripBenchmark.java | 3 +- .../protocol/V2RestXmlRoundtripBenchmark.java | 6 +- 13 files changed, 17 insertions(+), 130 deletions(-) diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServlet.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServlet.java index dd2a97f14ddb..ef4aeb9b9ca0 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServlet.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServlet.java @@ -16,116 +16,21 @@ package software.amazon.awssdk.benchmark.apicall.protocol; import java.io.IOException; -import java.io.OutputStream; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -/** - * Minimal servlet for protocol roundtrip benchmarks. Returns pre-loaded canned responses - * with zero request inspection overhead. Routes are matched by URI prefix or X-Amz-Target header. - */ class ProtocolRoundtripServlet extends HttpServlet { + private final byte[] body; - private final Map targetRoutes = new ConcurrentHashMap<>(); - private final Map uriRoutes = new ConcurrentHashMap<>(); - private CannedResponse defaultResponse; - - /** - * Register a route matched by X-Amz-Target header value. - */ - ProtocolRoundtripServlet routeByTarget(String target, String contentType, byte[] body) { - targetRoutes.put(target, new CannedResponse(contentType, body)); - return this; - } - - /** - * Register a route matched by URI prefix. - */ - ProtocolRoundtripServlet routeByUri(String uriPrefix, String contentType, byte[] body) { - uriRoutes.put(uriPrefix, new CannedResponse(contentType, body)); - return this; - } - - /** - * Register a route matched by URI prefix with additional response headers. - */ - ProtocolRoundtripServlet routeByUri(String uriPrefix, String contentType, byte[] body, - Map headers) { - uriRoutes.put(uriPrefix, new CannedResponse(contentType, body, headers)); - return this; - } - - /** - * Default response when no route matches. - */ - ProtocolRoundtripServlet defaultRoute(String contentType, byte[] body) { - this.defaultResponse = new CannedResponse(contentType, body); - return this; + ProtocolRoundtripServlet(byte[] body) { + this.body = body; } @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException { - // Consume request body to simulate real HTTP exchange - byte[] buf = new byte[8192]; - while (req.getInputStream().read(buf) != -1) { - // drain - } - - CannedResponse canned = resolve(req); - if (canned == null) { - resp.sendError(404); - return; - } - resp.setStatus(200); - resp.setContentType(canned.contentType); - resp.setContentLength(canned.body.length); - resp.setHeader("x-amzn-RequestId", "benchmark-request-id"); - if (canned.headers != null) { - canned.headers.forEach(resp::setHeader); - } - try (OutputStream os = resp.getOutputStream()) { - os.write(canned.body); - } - } - - private CannedResponse resolve(HttpServletRequest req) { - // Try X-Amz-Target first (JSON/CBOR protocols) - String target = req.getHeader("X-Amz-Target"); - if (target != null) { - CannedResponse r = targetRoutes.get(target); - if (r != null) { - return r; - } - } - - // Try URI prefix match (REST protocols) - String uri = req.getRequestURI(); - for (Map.Entry entry : uriRoutes.entrySet()) { - if (uri.contains(entry.getKey())) { - return entry.getValue(); - } - } - - return defaultResponse; - } - - private static class CannedResponse { - final String contentType; - final byte[] body; - final Map headers; - - CannedResponse(String contentType, byte[] body) { - this(contentType, body, null); - } - - CannedResponse(String contentType, byte[] body, Map headers) { - this.contentType = contentType; - this.body = body; - this.headers = headers; - } + resp.setContentLength(body.length); + resp.getOutputStream().write(body); } } diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1CborRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1CborRoundtripBenchmark.java index 402bec59dc1c..547dfc64aa5d 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1CborRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1CborRoundtripBenchmark.java @@ -61,8 +61,7 @@ public class V1CborRoundtripBenchmark { public void setup() throws Exception { byte[] response = createCborResponseFixture(); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() - .defaultRoute("application/cbor", response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); server = new ProtocolRoundtripServer(servlet); server.start(); diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java index aab3116f4a29..c4fe7638d684 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java @@ -56,8 +56,7 @@ public class V1Ec2RoundtripBenchmark { public void setup() throws Exception { byte[] response = ProtocolRoundtripServer.loadFixture("ec2-protocol/describe-instances-response.xml"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() - .defaultRoute("text/xml", response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); server = new ProtocolRoundtripServer(servlet); server.start(); diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java index 0e345a761c3d..2214709b5ea7 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java @@ -59,8 +59,7 @@ public class V1JsonRoundtripBenchmark { public void setup() throws Exception { byte[] response = ProtocolRoundtripServer.loadFixture("json-protocol/putitem-response.json"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() - .routeByTarget("DynamoDB_20120810.PutItem", "application/x-amz-json-1.0", response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); server = new ProtocolRoundtripServer(servlet); server.start(); diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java index cf77e8f91f15..03275d41be53 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java @@ -55,8 +55,7 @@ public class V1QueryRoundtripBenchmark { public void setup() throws Exception { byte[] response = ProtocolRoundtripServer.loadFixture("query-protocol/assumerole-response.xml"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() - .defaultRoute("text/xml", response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); server = new ProtocolRoundtripServer(servlet); server.start(); diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestJsonRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestJsonRoundtripBenchmark.java index 124bcda3452d..4db43a5ff2d0 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestJsonRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestJsonRoundtripBenchmark.java @@ -62,8 +62,7 @@ public class V1RestJsonRoundtripBenchmark { public void setup() throws Exception { byte[] response = ProtocolRoundtripServer.loadFixture("rest-json-protocol/createfunction-response.json"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() - .routeByUri("/2015-03-31/functions", "application/json", response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); server = new ProtocolRoundtripServer(servlet); server.start(); diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java index 78bd18462dc5..4d7c38624d02 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java @@ -31,8 +31,6 @@ import com.amazonaws.services.cloudfront.model.Origins; import com.amazonaws.services.cloudfront.model.S3OriginConfig; import com.amazonaws.services.cloudfront.model.ViewerProtocolPolicy; -import java.util.Collections; -import java.util.Map; import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; @@ -67,9 +65,7 @@ public class V1RestXmlRoundtripBenchmark { public void setup() throws Exception { byte[] response = ProtocolRoundtripServer.loadFixture("rest-xml-protocol/create-distribution-response.xml"); - Map headers = Collections.singletonMap("ETag", "E2QWRUHEXAMPLE"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() - .routeByUri("/2020-05-31/distribution", "application/xml", response, headers); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); server = new ProtocolRoundtripServer(servlet); server.start(); diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2CborRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2CborRoundtripBenchmark.java index 74af8b2563b0..0ab117fb6a3b 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2CborRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2CborRoundtripBenchmark.java @@ -61,8 +61,7 @@ public class V2CborRoundtripBenchmark { public void setup() throws Exception { byte[] response = createCborResponseFixture(); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() - .defaultRoute("application/cbor", response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); server = new ProtocolRoundtripServer(servlet); server.start(); diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java index e54090850fea..8c7bda089a7c 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java @@ -56,8 +56,7 @@ public class V2Ec2RoundtripBenchmark { public void setup() throws Exception { byte[] response = ProtocolRoundtripServer.loadFixture("ec2-protocol/describe-instances-response.xml"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() - .defaultRoute("text/xml", response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); server = new ProtocolRoundtripServer(servlet); server.start(); diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java index 110c8c140637..052df44b1111 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java @@ -59,8 +59,7 @@ public class V2JsonRoundtripBenchmark { public void setup() throws Exception { byte[] response = ProtocolRoundtripServer.loadFixture("json-protocol/putitem-response.json"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() - .routeByTarget("DynamoDB_20120810.PutItem", "application/x-amz-json-1.0", response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); server = new ProtocolRoundtripServer(servlet); server.start(); diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java index d2757e96bcf0..b88ef43e9942 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java @@ -55,8 +55,7 @@ public class V2QueryRoundtripBenchmark { public void setup() throws Exception { byte[] response = ProtocolRoundtripServer.loadFixture("query-protocol/assumerole-response.xml"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() - .defaultRoute("text/xml", response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); server = new ProtocolRoundtripServer(servlet); server.start(); diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestJsonRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestJsonRoundtripBenchmark.java index 667d3ba419df..a8b562f2c086 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestJsonRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestJsonRoundtripBenchmark.java @@ -62,8 +62,7 @@ public class V2RestJsonRoundtripBenchmark { public void setup() throws Exception { byte[] response = ProtocolRoundtripServer.loadFixture("rest-json-protocol/createfunction-response.json"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() - .routeByUri("/2015-03-31/functions", "application/json", response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); server = new ProtocolRoundtripServer(servlet); server.start(); diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java index f3b11e6e32b9..db4cbcedcd04 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java @@ -15,8 +15,6 @@ package software.amazon.awssdk.benchmark.apicall.protocol; -import java.util.Collections; -import java.util.Map; import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; @@ -67,9 +65,7 @@ public class V2RestXmlRoundtripBenchmark { public void setup() throws Exception { byte[] response = ProtocolRoundtripServer.loadFixture("rest-xml-protocol/create-distribution-response.xml"); - Map headers = Collections.singletonMap("ETag", "E2QWRUHEXAMPLE"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet() - .routeByUri("/2020-05-31/distribution", "application/xml", response, headers); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); server = new ProtocolRoundtripServer(servlet); server.start(); From 04975419c62b8223657dcaa9b719467d7df85b3f Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Wed, 18 Mar 2026 16:45:08 -0700 Subject: [PATCH 7/7] Move request creation into the benchmark runner --- .../protocol/ProtocolRoundtripServlet.java | 5 +- .../protocol/V1CborRoundtripBenchmark.java | 33 ++++--- .../protocol/V1Ec2RoundtripBenchmark.java | 17 ++-- .../protocol/V1JsonRoundtripBenchmark.java | 11 +-- .../protocol/V1QueryRoundtripBenchmark.java | 17 ++-- .../V1RestJsonRoundtripBenchmark.java | 27 +++--- .../protocol/V1RestXmlRoundtripBenchmark.java | 55 ++++++----- .../protocol/V2CborRoundtripBenchmark.java | 45 +++++---- .../protocol/V2Ec2RoundtripBenchmark.java | 19 ++-- .../protocol/V2JsonRoundtripBenchmark.java | 13 ++- .../protocol/V2QueryRoundtripBenchmark.java | 19 ++-- .../V2RestJsonRoundtripBenchmark.java | 43 +++++---- .../protocol/V2RestXmlRoundtripBenchmark.java | 93 +++++++++++-------- 13 files changed, 203 insertions(+), 194 deletions(-) diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServlet.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServlet.java index ef4aeb9b9ca0..abcce14534ad 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServlet.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServlet.java @@ -22,15 +22,18 @@ class ProtocolRoundtripServlet extends HttpServlet { private final byte[] body; + private final String contentType; - ProtocolRoundtripServlet(byte[] body) { + ProtocolRoundtripServlet(byte[] body, String contentType) { this.body = body; + this.contentType = contentType; } @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException { resp.setStatus(200); resp.setContentLength(body.length); + resp.setContentType(contentType); resp.getOutputStream().write(body); } } diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1CborRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1CborRoundtripBenchmark.java index 547dfc64aa5d..eb7dfccee20c 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1CborRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1CborRoundtripBenchmark.java @@ -55,13 +55,12 @@ public class V1CborRoundtripBenchmark { private ProtocolRoundtripServer server; private AmazonCloudWatch client; - private GetMetricDataRequest request; @Setup(Level.Trial) public void setup() throws Exception { byte[] response = createCborResponseFixture(); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "application/cbor"); server = new ProtocolRoundtripServer(servlet); server.start(); @@ -71,10 +70,19 @@ public void setup() throws Exception { server.getHttpUri().toString(), "us-east-1")) .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("test", "test"))) .build(); + } + @TearDown(Level.Trial) + public void tearDown() throws Exception { + client.shutdown(); + server.stop(); + } + + @Benchmark + public void getMetricData(Blackhole bh) { Date end = Date.from(java.time.Instant.parse("2026-03-09T00:00:00Z")); Date start = Date.from(java.time.Instant.parse("2026-03-09T00:00:00Z").minusSeconds(3600)); - request = new GetMetricDataRequest() + GetMetricDataRequest request = new GetMetricDataRequest() .withStartTime(start) .withEndTime(end) .withMaxDatapoints(1000) @@ -82,22 +90,13 @@ public void setup() throws Exception { new MetricDataQuery() .withId("cpu") .withMetricStat(new MetricStat() - .withMetric(new Metric() - .withNamespace("AWS/EC2") - .withMetricName("CPUUtilization")) - .withPeriod(300) - .withStat("Average")) + .withMetric(new Metric() + .withNamespace("AWS/EC2") + .withMetricName("CPUUtilization")) + .withPeriod(300) + .withStat("Average")) .withReturnData(true)); - } - @TearDown(Level.Trial) - public void tearDown() throws Exception { - client.shutdown(); - server.stop(); - } - - @Benchmark - public void getMetricData(Blackhole bh) { bh.consume(client.getMetricData(request)); } diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java index c4fe7638d684..6ae6df995a99 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java @@ -50,13 +50,12 @@ public class V1Ec2RoundtripBenchmark { private ProtocolRoundtripServer server; private AmazonEC2 client; - private DescribeInstancesRequest request; @Setup(Level.Trial) public void setup() throws Exception { byte[] response = ProtocolRoundtripServer.loadFixture("ec2-protocol/describe-instances-response.xml"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "text/xml"); server = new ProtocolRoundtripServer(servlet); server.start(); @@ -66,13 +65,6 @@ public void setup() throws Exception { server.getHttpUri().toString(), "us-east-1")) .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("test", "test"))) .build(); - - request = new DescribeInstancesRequest() - .withInstanceIds("i-0abcdef1234567890") - .withFilters( - new Filter("instance-state-name").withValues("running"), - new Filter("instance-type").withValues("m5.xlarge")) - .withMaxResults(100); } @TearDown(Level.Trial) @@ -83,6 +75,13 @@ public void tearDown() throws Exception { @Benchmark public void describeInstances(Blackhole bh) { + DescribeInstancesRequest request = new DescribeInstancesRequest() + .withInstanceIds("i-0abcdef1234567890") + .withFilters( + new Filter("instance-state-name").withValues("running"), + new Filter("instance-type").withValues("m5.xlarge")) + .withMaxResults(100); + bh.consume(client.describeInstances(request)); } } diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java index 2214709b5ea7..58146050360c 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java @@ -53,13 +53,12 @@ public class V1JsonRoundtripBenchmark { private ProtocolRoundtripServer server; private AmazonDynamoDB client; - private PutItemRequest putItemRequest; @Setup(Level.Trial) public void setup() throws Exception { byte[] response = ProtocolRoundtripServer.loadFixture("json-protocol/putitem-response.json"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "application/x-amz-json-1.0"); server = new ProtocolRoundtripServer(servlet); server.start(); @@ -69,10 +68,6 @@ public void setup() throws Exception { server.getHttpUri().toString(), "us-east-1")) .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("test", "test"))) .build(); - - putItemRequest = new PutItemRequest() - .withTableName("benchmark-table") - .withItem(itemMap()); } @TearDown(Level.Trial) @@ -83,6 +78,10 @@ public void tearDown() throws Exception { @Benchmark public void putItem(Blackhole bh) { + PutItemRequest putItemRequest = new PutItemRequest() + .withTableName("benchmark-table") + .withItem(itemMap()); + bh.consume(client.putItem(putItemRequest)); } diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java index 03275d41be53..3da508d4ff5c 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java @@ -49,13 +49,12 @@ public class V1QueryRoundtripBenchmark { private ProtocolRoundtripServer server; private AWSSecurityTokenService client; - private AssumeRoleRequest request; @Setup(Level.Trial) public void setup() throws Exception { byte[] response = ProtocolRoundtripServer.loadFixture("query-protocol/assumerole-response.xml"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "text/xml"); server = new ProtocolRoundtripServer(servlet); server.start(); @@ -65,13 +64,6 @@ public void setup() throws Exception { server.getHttpUri().toString(), "us-east-1")) .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("test", "test"))) .build(); - - request = new AssumeRoleRequest() - .withRoleArn("arn:aws:iam::123456789012:role/benchmark-role") - .withRoleSessionName("benchmark-session") - .withDurationSeconds(3600) - .withExternalId("benchmark-external-id") - .withPolicy("{\"Version\":\"2012-10-17\"}"); } @TearDown(Level.Trial) @@ -82,6 +74,13 @@ public void tearDown() throws Exception { @Benchmark public void assumeRole(Blackhole bh) { + AssumeRoleRequest request = new AssumeRoleRequest() + .withRoleArn("arn:aws:iam::123456789012:role/benchmark-role") + .withRoleSessionName("benchmark-session") + .withDurationSeconds(3600) + .withExternalId("benchmark-external-id") + .withPolicy("{\"Version\":\"2012-10-17\"}"); + bh.consume(client.assumeRole(request)); } } diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestJsonRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestJsonRoundtripBenchmark.java index 4db43a5ff2d0..5bc6d9ca080f 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestJsonRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestJsonRoundtripBenchmark.java @@ -56,13 +56,12 @@ public class V1RestJsonRoundtripBenchmark { private ProtocolRoundtripServer server; private AWSLambda client; - private CreateFunctionRequest request; @Setup(Level.Trial) public void setup() throws Exception { byte[] response = ProtocolRoundtripServer.loadFixture("rest-json-protocol/createfunction-response.json"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "application/json"); server = new ProtocolRoundtripServer(servlet); server.start(); @@ -72,34 +71,34 @@ public void setup() throws Exception { server.getHttpUri().toString(), "us-east-1")) .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("test", "test"))) .build(); + } + @TearDown(Level.Trial) + public void tearDown() throws Exception { + client.shutdown(); + server.stop(); + } + + @Benchmark + public void createFunction(Blackhole bh) { Map envVars = new HashMap<>(); envVars.put("ENV_VAR_1", "value1"); - request = new CreateFunctionRequest() + CreateFunctionRequest request = new CreateFunctionRequest() .withFunctionName("benchmark-function") .withRuntime(Runtime.Java8) .withRole("arn:aws:iam::123456789012:role/lambda-role") .withHandler("com.example.Handler::handleRequest") .withCode(new FunctionCode() - .withS3Bucket("my-deploy-bucket") - .withS3Key("code/function.zip")) + .withS3Bucket("my-deploy-bucket") + .withS3Key("code/function.zip")) .withDescription("Benchmark test function") .withTimeout(30) .withMemorySize(512) .withPublish(false) .withEnvironment(new Environment().withVariables(envVars)) .withTracingConfig(new TracingConfig().withMode(TracingMode.Active)); - } - @TearDown(Level.Trial) - public void tearDown() throws Exception { - client.shutdown(); - server.stop(); - } - - @Benchmark - public void createFunction(Blackhole bh) { bh.consume(client.createFunction(request)); } } diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java index 4d7c38624d02..ff42e19ada68 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java @@ -59,13 +59,12 @@ public class V1RestXmlRoundtripBenchmark { private ProtocolRoundtripServer server; private AmazonCloudFront client; - private CreateDistributionRequest request; @Setup(Level.Trial) public void setup() throws Exception { byte[] response = ProtocolRoundtripServer.loadFixture("rest-xml-protocol/create-distribution-response.xml"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "text/xml"); server = new ProtocolRoundtripServer(servlet); server.start(); @@ -75,32 +74,6 @@ public void setup() throws Exception { server.getHttpUri().toString(), "us-east-1")) .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("test", "test"))) .build(); - - request = new CreateDistributionRequest() - .withDistributionConfig(new DistributionConfig() - .withCallerReference("benchmark-ref-2024") - .withAliases(new Aliases() - .withQuantity(2) - .withItems("www.example.com", "cdn.example.com")) - .withDefaultRootObject("index.html") - .withOrigins(new Origins() - .withQuantity(1) - .withItems(new Origin() - .withId("myS3Origin") - .withDomainName("mybucket.s3.amazonaws.com") - .withOriginPath("/production") - .withS3OriginConfig(new S3OriginConfig() - .withOriginAccessIdentity("origin-access-identity/cloudfront/E127EXAMPLE51Z")))) - .withDefaultCacheBehavior(new DefaultCacheBehavior() - .withTargetOriginId("myS3Origin") - .withViewerProtocolPolicy(ViewerProtocolPolicy.RedirectToHttps) - .withAllowedMethods(new AllowedMethods() - .withQuantity(3) - .withItems(Method.GET, Method.HEAD, Method.OPTIONS) - .withCachedMethods(new CachedMethods() - .withQuantity(2) - .withItems(Method.GET, Method.HEAD))) - .withCompress(true))); } @TearDown(Level.Trial) @@ -111,6 +84,32 @@ public void tearDown() throws Exception { @Benchmark public void createDistribution(Blackhole bh) { + CreateDistributionRequest request = new CreateDistributionRequest() + .withDistributionConfig(new DistributionConfig() + .withCallerReference("benchmark-ref-2024") + .withAliases(new Aliases() + .withQuantity(2) + .withItems("www.example.com", "cdn.example.com")) + .withDefaultRootObject("index.html") + .withOrigins(new Origins() + .withQuantity(1) + .withItems(new Origin() + .withId("myS3Origin") + .withDomainName("mybucket.s3.amazonaws.com") + .withOriginPath("/production") + .withS3OriginConfig(new S3OriginConfig() + .withOriginAccessIdentity("origin-access-identity/cloudfront/E127EXAMPLE51Z")))) + .withDefaultCacheBehavior(new DefaultCacheBehavior() + .withTargetOriginId("myS3Origin") + .withViewerProtocolPolicy(ViewerProtocolPolicy.RedirectToHttps) + .withAllowedMethods(new AllowedMethods() + .withQuantity(3) + .withItems(Method.GET, Method.HEAD, Method.OPTIONS) + .withCachedMethods(new CachedMethods() + .withQuantity(2) + .withItems(Method.GET, Method.HEAD))) + .withCompress(true))); + bh.consume(client.createDistribution(request)); } } diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2CborRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2CborRoundtripBenchmark.java index 0ab117fb6a3b..f2f3e60a740b 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2CborRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2CborRoundtripBenchmark.java @@ -55,13 +55,12 @@ public class V2CborRoundtripBenchmark { private ProtocolRoundtripServer server; private CloudWatchClient client; - private GetMetricDataRequest request; @Setup(Level.Trial) public void setup() throws Exception { byte[] response = createCborResponseFixture(); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "application/cbor"); server = new ProtocolRoundtripServer(servlet); server.start(); @@ -72,27 +71,6 @@ public void setup() throws Exception { .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("test", "test"))) .httpClient(Apache5HttpClient.create()) .build(); - - Instant end = Instant.parse("2026-03-09T00:00:00Z"); - Instant start = end.minusSeconds(3600); - request = GetMetricDataRequest.builder() - .startTime(start) - .endTime(end) - .maxDatapoints(1000) - .metricDataQueries( - MetricDataQuery.builder() - .id("cpu") - .metricStat(MetricStat.builder() - .metric(Metric.builder() - .namespace("AWS/EC2") - .metricName("CPUUtilization") - .build()) - .period(300) - .stat("Average") - .build()) - .returnData(true) - .build()) - .build(); } @TearDown(Level.Trial) @@ -103,6 +81,27 @@ public void tearDown() throws Exception { @Benchmark public void getMetricData(Blackhole bh) { + Instant end = Instant.parse("2026-03-09T00:00:00Z"); + Instant start = end.minusSeconds(3600); + GetMetricDataRequest request = GetMetricDataRequest.builder() + .startTime(start) + .endTime(end) + .maxDatapoints(1000) + .metricDataQueries( + MetricDataQuery.builder() + .id("cpu") + .metricStat(MetricStat.builder() + .metric(Metric.builder() + .namespace("AWS/EC2") + .metricName("CPUUtilization") + .build()) + .period(300) + .stat("Average") + .build()) + .returnData(true) + .build()) + .build(); + bh.consume(client.getMetricData(request)); } diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java index 8c7bda089a7c..3dfdd9cd74d2 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java @@ -50,13 +50,12 @@ public class V2Ec2RoundtripBenchmark { private ProtocolRoundtripServer server; private Ec2Client client; - private DescribeInstancesRequest request; @Setup(Level.Trial) public void setup() throws Exception { byte[] response = ProtocolRoundtripServer.loadFixture("ec2-protocol/describe-instances-response.xml"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "text/xml"); server = new ProtocolRoundtripServer(servlet); server.start(); @@ -67,14 +66,6 @@ public void setup() throws Exception { .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("test", "test"))) .httpClient(Apache5HttpClient.create()) .build(); - - request = DescribeInstancesRequest.builder() - .instanceIds("i-0abcdef1234567890") - .filters( - Filter.builder().name("instance-state-name").values("running").build(), - Filter.builder().name("instance-type").values("m5.xlarge").build()) - .maxResults(100) - .build(); } @TearDown(Level.Trial) @@ -85,6 +76,14 @@ public void tearDown() throws Exception { @Benchmark public void describeInstances(Blackhole bh) { + DescribeInstancesRequest request = DescribeInstancesRequest.builder() + .instanceIds("i-0abcdef1234567890") + .filters( + Filter.builder().name("instance-state-name").values("running").build(), + Filter.builder().name("instance-type").values("m5.xlarge").build()) + .maxResults(100) + .build(); + bh.consume(client.describeInstances(request)); } } diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java index 052df44b1111..6d23fc581f6e 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java @@ -53,13 +53,12 @@ public class V2JsonRoundtripBenchmark { private ProtocolRoundtripServer server; private DynamoDbClient client; - private PutItemRequest putItemRequest; @Setup(Level.Trial) public void setup() throws Exception { byte[] response = ProtocolRoundtripServer.loadFixture("json-protocol/putitem-response.json"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "application/x-amz-json-1.0"); server = new ProtocolRoundtripServer(servlet); server.start(); @@ -70,11 +69,6 @@ public void setup() throws Exception { .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("test", "test"))) .httpClient(Apache5HttpClient.create()) .build(); - - putItemRequest = PutItemRequest.builder() - .tableName("benchmark-table") - .item(itemMap()) - .build(); } @TearDown(Level.Trial) @@ -85,6 +79,11 @@ public void tearDown() throws Exception { @Benchmark public void putItem(Blackhole bh) { + + PutItemRequest putItemRequest = PutItemRequest.builder() + .tableName("benchmark-table") + .item(itemMap()) + .build(); bh.consume(client.putItem(putItemRequest)); } diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java index b88ef43e9942..aff4d9c23cd2 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java @@ -49,13 +49,12 @@ public class V2QueryRoundtripBenchmark { private ProtocolRoundtripServer server; private StsClient client; - private AssumeRoleRequest request; @Setup(Level.Trial) public void setup() throws Exception { byte[] response = ProtocolRoundtripServer.loadFixture("query-protocol/assumerole-response.xml"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "text/xml"); server = new ProtocolRoundtripServer(servlet); server.start(); @@ -66,14 +65,6 @@ public void setup() throws Exception { .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("test", "test"))) .httpClient(Apache5HttpClient.create()) .build(); - - request = AssumeRoleRequest.builder() - .roleArn("arn:aws:iam::123456789012:role/benchmark-role") - .roleSessionName("benchmark-session") - .durationSeconds(3600) - .externalId("benchmark-external-id") - .policy("{\"Version\":\"2012-10-17\"}") - .build(); } @TearDown(Level.Trial) @@ -84,6 +75,14 @@ public void tearDown() throws Exception { @Benchmark public void assumeRole(Blackhole bh) { + AssumeRoleRequest request = AssumeRoleRequest.builder() + .roleArn("arn:aws:iam::123456789012:role/benchmark-role") + .roleSessionName("benchmark-session") + .durationSeconds(3600) + .externalId("benchmark-external-id") + .policy("{\"Version\":\"2012-10-17\"}") + .build(); + bh.consume(client.assumeRole(request)); } } diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestJsonRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestJsonRoundtripBenchmark.java index a8b562f2c086..563ad7fd1dd3 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestJsonRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestJsonRoundtripBenchmark.java @@ -56,13 +56,12 @@ public class V2RestJsonRoundtripBenchmark { private ProtocolRoundtripServer server; private LambdaClient client; - private CreateFunctionRequest request; @Setup(Level.Trial) public void setup() throws Exception { byte[] response = ProtocolRoundtripServer.loadFixture("rest-json-protocol/createfunction-response.json"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "application/json"); server = new ProtocolRoundtripServer(servlet); server.start(); @@ -73,26 +72,6 @@ public void setup() throws Exception { .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("test", "test"))) .httpClient(Apache5HttpClient.create()) .build(); - - Map envVars = new HashMap<>(); - envVars.put("ENV_VAR_1", "value1"); - - request = CreateFunctionRequest.builder() - .functionName("benchmark-function") - .runtime(Runtime.JAVA8) - .role("arn:aws:iam::123456789012:role/lambda-role") - .handler("com.example.Handler::handleRequest") - .code(FunctionCode.builder() - .s3Bucket("my-deploy-bucket") - .s3Key("code/function.zip") - .build()) - .description("Benchmark test function") - .timeout(30) - .memorySize(512) - .publish(false) - .environment(Environment.builder().variables(envVars).build()) - .tracingConfig(TracingConfig.builder().mode(TracingMode.ACTIVE).build()) - .build(); } @TearDown(Level.Trial) @@ -103,6 +82,26 @@ public void tearDown() throws Exception { @Benchmark public void createFunction(Blackhole bh) { + Map envVars = new HashMap<>(); + envVars.put("ENV_VAR_1", "value1"); + + CreateFunctionRequest request = CreateFunctionRequest.builder() + .functionName("benchmark-function") + .runtime(Runtime.JAVA8) + .role("arn:aws:iam::123456789012:role/lambda-role") + .handler("com.example.Handler::handleRequest") + .code(FunctionCode.builder() + .s3Bucket("my-deploy-bucket") + .s3Key("code/function.zip") + .build()) + .description("Benchmark test function") + .timeout(30) + .memorySize(512) + .publish(false) + .environment(Environment.builder().variables(envVars).build()) + .tracingConfig(TracingConfig.builder().mode(TracingMode.ACTIVE).build()) + .build(); + bh.consume(client.createFunction(request)); } } diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java index db4cbcedcd04..04cdea1b56ef 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java @@ -59,13 +59,12 @@ public class V2RestXmlRoundtripBenchmark { private ProtocolRoundtripServer server; private CloudFrontClient client; - private CreateDistributionRequest request; @Setup(Level.Trial) public void setup() throws Exception { byte[] response = ProtocolRoundtripServer.loadFixture("rest-xml-protocol/create-distribution-response.xml"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response); + ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "text/xml"); server = new ProtocolRoundtripServer(servlet); server.start(); @@ -73,44 +72,11 @@ public void setup() throws Exception { client = CloudFrontClient.builder() .endpointOverride(server.getHttpUri()) .region(Region.US_EAST_1) - .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("test", "test"))) + .credentialsProvider( + StaticCredentialsProvider.create( + AwsBasicCredentials.create("test", "test"))) .httpClient(Apache5HttpClient.create()) .build(); - - request = CreateDistributionRequest.builder() - .distributionConfig(DistributionConfig.builder() - .callerReference("benchmark-ref-2024") - .aliases(Aliases.builder() - .quantity(2) - .items("www.example.com", "cdn.example.com") - .build()) - .defaultRootObject("index.html") - .origins(Origins.builder() - .quantity(1) - .items(Origin.builder() - .id("myS3Origin") - .domainName("mybucket.s3.amazonaws.com") - .originPath("/production") - .s3OriginConfig(S3OriginConfig.builder() - .originAccessIdentity("origin-access-identity/cloudfront/E127EXAMPLE51Z") - .build()) - .build()) - .build()) - .defaultCacheBehavior(DefaultCacheBehavior.builder() - .targetOriginId("myS3Origin") - .viewerProtocolPolicy(ViewerProtocolPolicy.REDIRECT_TO_HTTPS) - .allowedMethods(AllowedMethods.builder() - .quantity(3) - .items(Method.GET, Method.HEAD, Method.OPTIONS) - .cachedMethods(CachedMethods.builder() - .quantity(2) - .items(Method.GET, Method.HEAD) - .build()) - .build()) - .compress(true) - .build()) - .build()) - .build(); } @TearDown(Level.Trial) @@ -121,6 +87,57 @@ public void tearDown() throws Exception { @Benchmark public void createDistribution(Blackhole bh) { + S3OriginConfig s3Config = S3OriginConfig.builder() + .originAccessIdentity( + "origin-access-identity/cloudfront/E127EXAMPLE51Z") + .build(); + + Origin origin = Origin.builder() + .id("myS3Origin") + .domainName("mybucket.s3.amazonaws.com") + .originPath("/production") + .s3OriginConfig(s3Config) + .build(); + + CachedMethods cached = CachedMethods.builder() + .quantity(2) + .items(Method.GET, Method.HEAD) + .build(); + + AllowedMethods allowed = AllowedMethods.builder() + .quantity(3) + .items(Method.GET, Method.HEAD, Method.OPTIONS) + .cachedMethods(cached) + .build(); + + DefaultCacheBehavior cacheBehavior = + DefaultCacheBehavior.builder() + .targetOriginId("myS3Origin") + .viewerProtocolPolicy( + ViewerProtocolPolicy.REDIRECT_TO_HTTPS) + .allowedMethods(allowed) + .compress(true) + .build(); + + DistributionConfig config = DistributionConfig.builder() + .callerReference("benchmark-ref-2024") + .aliases(Aliases.builder() + .quantity(2) + .items("www.example.com", "cdn.example.com") + .build()) + .defaultRootObject("index.html") + .origins(Origins.builder() + .quantity(1) + .items(origin) + .build()) + .defaultCacheBehavior(cacheBehavior) + .build(); + + CreateDistributionRequest request = + CreateDistributionRequest.builder() + .distributionConfig(config) + .build(); + bh.consume(client.createDistribution(request)); } }