Skip to content

Commit 0558677

Browse files
authored
S3 Benchmarks - support java-based multipart client (#4288)
S3 Benchmarks - support java-based multipart client
1 parent 05d6946 commit 0558677

11 files changed

+464
-42
lines changed

test/s3-benchmarks/.scripts/benchmark

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ if [ ! -d result ]; then
6464
fi
6565

6666
sizes_str="1B 8MB+1 8MB-1 128MB 4GB 30GB"
67-
versions_str="v1 v2 CRT"
67+
versions_str="v1 v2 CRT java"
6868
sizes=( $sizes_str )
6969
versions=( $versions_str )
7070

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
head -c 1B </dev/urandom >/dev/shm/1B
2-
head -c 8388607B </dev/urandom >/dev/shm/8MB-1
3-
head -c 8388609B </dev/urandom >/dev/shm/8MB+1
4-
head -c 128M </dev/urandom >/dev/shm/128MB
5-
head -c 4B </dev/urandom >/dev/shm/4GB
6-
head -c 30GB </dev/urandom >/dev/shm/30GB
7-
8-
head -c 1B </dev/urandom >/1B
9-
head -c 8388607B </dev/urandom >/8MB-1
10-
head -c 8388609B </dev/urandom >/8MB+1
11-
head -c 128M </dev/urandom >/128MB
12-
head -c 4B </dev/urandom >/4GB
13-
head -c 30GB </dev/urandom >/30GB
1+
head -c 1 </dev/urandom >/dev/shm/1B
2+
head -c $((8*1024*1024-1)) </dev/urandom >/dev/shm/8MB-1
3+
head -c $((8*1024*1024+1)) </dev/urandom >/dev/shm/8MB+1
4+
head -c $((128*1024*1024)) </dev/urandom >/dev/shm/128MB
5+
head -c $((4*1024*1024*1024)) </dev/urandom >/dev/shm/4GB
6+
head -c $((30*1024*1024*1024)) </dev/urandom >/dev/shm/30GB
147

8+
head -c 1 </dev/urandom >/1B
9+
head -c $((8*1024*1024-1)) </dev/urandom >/8MB-1
10+
head -c $((8*1024*1024+1)) </dev/urandom >/8MB+1
11+
head -c $((128*1024*1024)) </dev/urandom >/128MB
12+
head -c $((4*1024*1024*1024)) </dev/urandom >/4GB
13+
head -c $((30*1024*1024*1024)) </dev/urandom >/30GB

test/s3-benchmarks/README.md

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# S3 Benchmark Harness
22

3-
4-
This module contains performance tests for `S3AsyncClient` and
3+
This module contains performance tests for `S3AsyncClient` and
54
`S3TransferManager`
65

76
## How to run
@@ -17,6 +16,31 @@ java -jar s3-benchmarks.jar --bucket=bucket --key=key -file=/path/to/destionfile
1716
java -jar s3-benchmarks.jar --bucket=bucket --key=key -file=/path/to/sourcefile/ --operation=upload --partSizeInMB=20 --maxThroughput=100.0
1817
```
1918

19+
## Command line arguments
20+
21+
### Benchmark version
22+
23+
The `--version` command line option is used to determine which component is under test:
24+
25+
- `--version=crt` : Indicate to run the benchmark for the CRT's S3Client
26+
- `--version=java` : Indicate to run the benchmark for the java based S3 Async Client (`MultipartS3AsyncClient` class)
27+
- `--version=v2`: SDK v2 transfer manager (using `S3CrtAsyncClient` to delegate requests)
28+
- `--version=v1`: SDK v1 transfer manager (using `AmazonS3Client` to delegate requests)
29+
30+
### Operation
31+
32+
The `--operation` command line argument determine which transfer operation is used
33+
34+
|operation|supported version|
35+
|---|-------|
36+
|download | v1 v2 java crt |
37+
|upload | v1 v2 java crt |
38+
|download_directory | v1 v2 |
39+
|upload_directory | v1 v2 |
40+
|copy | v1 v2 java |
41+
42+
> All command line argument can be found in the `BenchmarkRunner` class.
43+
2044
# Benchmark scripts Automation
2145
From the `.script` folder, use one of the `benchamrk` scripts to run a test suite.
2246

test/s3-benchmarks/pom.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,16 @@
8787
<artifactId>log4j-slf4j-impl</artifactId>
8888
<scope>compile</scope>
8989
</dependency>
90+
<dependency>
91+
<groupId>software.amazon.awssdk</groupId>
92+
<artifactId>netty-nio-client</artifactId>
93+
<version>${awsjavasdk.version}</version>
94+
</dependency>
95+
<dependency>
96+
<groupId>software.amazon.awssdk</groupId>
97+
<artifactId>aws-crt-client</artifactId>
98+
<version>${awsjavasdk.version}</version>
99+
</dependency>
90100
</dependencies>
91101

92102
<build>
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.s3benchmarks;
17+
18+
import static software.amazon.awssdk.s3benchmarks.BenchmarkUtils.BENCHMARK_ITERATIONS;
19+
import static software.amazon.awssdk.s3benchmarks.BenchmarkUtils.DEFAULT_TIMEOUT;
20+
import static software.amazon.awssdk.s3benchmarks.BenchmarkUtils.printOutResult;
21+
import static software.amazon.awssdk.transfer.s3.SizeConstant.MB;
22+
23+
import java.time.Duration;
24+
import java.util.ArrayList;
25+
import java.util.List;
26+
import software.amazon.awssdk.http.async.SdkAsyncHttpClient;
27+
import software.amazon.awssdk.http.crt.AwsCrtAsyncHttpClient;
28+
import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient;
29+
import software.amazon.awssdk.services.s3.S3AsyncClient;
30+
import software.amazon.awssdk.services.s3.S3Client;
31+
import software.amazon.awssdk.services.s3.model.ChecksumAlgorithm;
32+
import software.amazon.awssdk.utils.Logger;
33+
import software.amazon.awssdk.utils.Validate;
34+
35+
public abstract class BaseJavaS3ClientBenchmark implements TransferManagerBenchmark {
36+
private static final Logger logger = Logger.loggerFor(BaseJavaS3ClientBenchmark.class);
37+
38+
protected final S3Client s3Client;
39+
40+
protected final S3AsyncClient s3AsyncClient;
41+
protected final String bucket;
42+
protected final String key;
43+
protected final Duration timeout;
44+
private final ChecksumAlgorithm checksumAlgorithm;
45+
private final int iteration;
46+
47+
protected BaseJavaS3ClientBenchmark(TransferManagerBenchmarkConfig config) {
48+
this.bucket = Validate.paramNotNull(config.bucket(), "bucket");
49+
this.key = Validate.paramNotNull(config.key(), "key");
50+
this.timeout = Validate.getOrDefault(config.timeout(), () -> DEFAULT_TIMEOUT);
51+
this.iteration = Validate.getOrDefault(config.iteration(), () -> BENCHMARK_ITERATIONS);
52+
this.checksumAlgorithm = config.checksumAlgorithm();
53+
54+
this.s3Client = S3Client.create();
55+
56+
long partSizeInMb = Validate.paramNotNull(config.partSizeInMb(), "partSize");
57+
long readBufferInMb = Validate.paramNotNull(config.readBufferSizeInMb(), "readBufferSizeInMb");
58+
Validate.mutuallyExclusive("cannot use forceCrtHttpClient and connectionAcquisitionTimeoutInSec",
59+
config.forceCrtHttpClient(), config.connectionAcquisitionTimeoutInSec());
60+
this.s3AsyncClient = S3AsyncClient.builder()
61+
.multipartEnabled(true)
62+
.multipartConfiguration(c -> c.minimumPartSizeInBytes(partSizeInMb * MB)
63+
.thresholdInBytes(partSizeInMb * 2 * MB)
64+
.apiCallBufferSizeInBytes(readBufferInMb * MB))
65+
.httpClientBuilder(httpClient(config))
66+
.build();
67+
}
68+
69+
private SdkAsyncHttpClient.Builder httpClient(TransferManagerBenchmarkConfig config) {
70+
if (config.forceCrtHttpClient()) {
71+
logger.info(() -> "Using CRT HTTP client");
72+
AwsCrtAsyncHttpClient.Builder builder = AwsCrtAsyncHttpClient.builder();
73+
if (config.readBufferSizeInMb() != null) {
74+
builder.readBufferSizeInBytes(config.readBufferSizeInMb() * MB);
75+
}
76+
if (config.maxConcurrency() != null) {
77+
builder.maxConcurrency(config.maxConcurrency());
78+
}
79+
return builder;
80+
}
81+
NettyNioAsyncHttpClient.Builder builder = NettyNioAsyncHttpClient.builder();
82+
if (config.connectionAcquisitionTimeoutInSec() != null) {
83+
Duration connAcqTimeout = Duration.ofSeconds(config.connectionAcquisitionTimeoutInSec());
84+
builder.connectionAcquisitionTimeout(connAcqTimeout);
85+
}
86+
if (config.maxConcurrency() != null) {
87+
builder.maxConcurrency(config.maxConcurrency());
88+
}
89+
return builder;
90+
}
91+
92+
protected abstract void sendOneRequest(List<Double> latencies) throws Exception;
93+
94+
protected abstract long contentLength() throws Exception;
95+
96+
@Override
97+
public void run() {
98+
try {
99+
warmUp();
100+
doRunBenchmark();
101+
} catch (Exception e) {
102+
logger.error(() -> "Exception occurred", e);
103+
} finally {
104+
cleanup();
105+
}
106+
}
107+
108+
private void cleanup() {
109+
s3Client.close();
110+
s3AsyncClient.close();
111+
}
112+
113+
private void warmUp() throws Exception {
114+
logger.info(() -> "Starting to warm up");
115+
for (int i = 0; i < 3; i++) {
116+
sendOneRequest(new ArrayList<>());
117+
Thread.sleep(500);
118+
}
119+
logger.info(() -> "Ending warm up");
120+
}
121+
122+
private void doRunBenchmark() throws Exception {
123+
List<Double> metrics = new ArrayList<>();
124+
for (int i = 0; i < iteration; i++) {
125+
sendOneRequest(metrics);
126+
}
127+
printOutResult(metrics, "S3 Async client", contentLength());
128+
}
129+
130+
}

test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/BaseTransferManagerBenchmark.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
3535
import software.amazon.awssdk.services.s3.S3AsyncClient;
3636
import software.amazon.awssdk.services.s3.S3Client;
37+
import software.amazon.awssdk.services.s3.S3CrtAsyncClientBuilder;
3738
import software.amazon.awssdk.services.s3.internal.crt.S3CrtAsyncClient;
3839
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
3940
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
@@ -61,15 +62,18 @@ public abstract class BaseTransferManagerBenchmark implements TransferManagerBen
6162
logger.info(() -> "Benchmark config: " + config);
6263
Long partSizeInMb = config.partSizeInMb() == null ? null : config.partSizeInMb() * MB;
6364
Long readBufferSizeInMb = config.readBufferSizeInMb() == null ? null : config.readBufferSizeInMb() * MB;
64-
s3 = S3CrtAsyncClient.builder()
65-
.targetThroughputInGbps(config.targetThroughput())
66-
.minimumPartSizeInBytes(partSizeInMb)
67-
.initialReadBufferSizeInBytes(readBufferSizeInMb)
68-
.targetThroughputInGbps(config.targetThroughput() == null ?
69-
Double.valueOf(100.0) : config.targetThroughput())
70-
.build();
71-
s3Sync = S3Client.builder()
72-
.build();
65+
S3CrtAsyncClientBuilder builder = S3CrtAsyncClient.builder()
66+
.targetThroughputInGbps(config.targetThroughput())
67+
.minimumPartSizeInBytes(partSizeInMb)
68+
.initialReadBufferSizeInBytes(readBufferSizeInMb)
69+
.targetThroughputInGbps(config.targetThroughput() == null ?
70+
Double.valueOf(100.0) :
71+
config.targetThroughput());
72+
if (config.maxConcurrency() != null) {
73+
builder.maxConcurrency(config.maxConcurrency());
74+
}
75+
s3 = builder.build();
76+
s3Sync = S3Client.builder().build();
7377
transferManager = S3TransferManager.builder()
7478
.s3Client(s3)
7579
.build();

test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/BenchmarkRunner.java

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ public final class BenchmarkRunner {
4545

4646
private static final String TIMEOUT = "timeoutInMin";
4747

48+
private static final String CONN_ACQ_TIMEOUT_IN_SEC = "connAcqTimeoutInSec";
49+
50+
private static final String FORCE_CRT_HTTP_CLIENT = "crtHttp";
51+
private static final String MAX_CONCURRENCY = "maxConcurrency";
52+
4853
private static final Map<TransferManagerOperation, Function<TransferManagerBenchmarkConfig, TransferManagerBenchmark>>
4954
OPERATION_TO_BENCHMARK_V1 = new EnumMap<>(TransferManagerOperation.class);
5055
private static final Map<TransferManagerOperation, Function<TransferManagerBenchmarkConfig, TransferManagerBenchmark>>
@@ -83,8 +88,8 @@ public static void main(String... args) throws org.apache.commons.cli.ParseExcep
8388
options.addOption(null, CHECKSUM_ALGORITHM, true, "The checksum algorithm to use");
8489
options.addOption(null, ITERATION, true, "The number of iterations");
8590
options.addOption(null, READ_BUFFER_IN_MB, true, "Read buffer size in MB");
86-
options.addOption(null, VERSION, true, "The major version of the transfer manager to run test: v1 | v2 | crt, default: "
87-
+ "v2");
91+
options.addOption(null, VERSION, true, "The major version of the transfer manager to run test: "
92+
+ "v1 | v2 | crt | java, default: v2");
8893
options.addOption(null, PREFIX, true, "S3 Prefix used in downloadDirectory and uploadDirectory");
8994

9095
options.addOption(null, CONTENT_LENGTH, true, "Content length to upload from memory. Used only in the "
@@ -93,6 +98,12 @@ public static void main(String... args) throws org.apache.commons.cli.ParseExcep
9398

9499
options.addOption(null, TIMEOUT, true, "Amount of minute to wait before a single operation "
95100
+ "times out and is cancelled. Optional, defaults to 10 minutes if no specified");
101+
options.addOption(null, CONN_ACQ_TIMEOUT_IN_SEC, true, "Timeout for acquiring an already-established"
102+
+ " connection from a connection pool to a remote service.");
103+
options.addOption(null, FORCE_CRT_HTTP_CLIENT, true,
104+
"Force the CRT http client to be used in JavaBased benchmarks");
105+
options.addOption(null, MAX_CONCURRENCY, true,
106+
"The Maximum number of allowed concurrent requests. For HTTP/1.1 this is the same as max connections.");
96107

97108
CommandLine cmd = parser.parse(options, args);
98109
TransferManagerBenchmarkConfig config = parseConfig(cmd);
@@ -114,11 +125,22 @@ public static void main(String... args) throws org.apache.commons.cli.ParseExcep
114125
if (operation == TransferManagerOperation.DOWNLOAD) {
115126
benchmark = new CrtS3ClientDownloadBenchmark(config);
116127
break;
117-
} else if (operation == TransferManagerOperation.UPLOAD) {
128+
}
129+
if (operation == TransferManagerOperation.UPLOAD) {
118130
benchmark = new CrtS3ClientUploadBenchmark(config);
119131
break;
120132
}
121133
throw new UnsupportedOperationException();
134+
case JAVA:
135+
if (operation == TransferManagerOperation.UPLOAD) {
136+
benchmark = new JavaS3ClientUploadBenchmark(config);
137+
break;
138+
}
139+
if (operation == TransferManagerOperation.COPY) {
140+
benchmark = new JavaS3ClientCopyBenchmark(config);
141+
break;
142+
}
143+
throw new UnsupportedOperationException("Java based s3 client benchmark only support upload and copy");
122144
default:
123145
throw new UnsupportedOperationException();
124146
}
@@ -158,6 +180,15 @@ private static TransferManagerBenchmarkConfig parseConfig(CommandLine cmd) {
158180
Duration timeout = cmd.getOptionValue(TIMEOUT) == null ? null :
159181
Duration.ofMinutes(Long.parseLong(cmd.getOptionValue(TIMEOUT)));
160182

183+
Long connAcqTimeoutInSec = cmd.getOptionValue(CONN_ACQ_TIMEOUT_IN_SEC) == null ? null :
184+
Long.parseLong(cmd.getOptionValue(CONN_ACQ_TIMEOUT_IN_SEC));
185+
186+
Boolean forceCrtHttpClient = cmd.getOptionValue(FORCE_CRT_HTTP_CLIENT) != null
187+
&& Boolean.parseBoolean(cmd.getOptionValue(FORCE_CRT_HTTP_CLIENT));
188+
189+
Integer maxConcurrency = cmd.getOptionValue(MAX_CONCURRENCY) == null ? null :
190+
Integer.parseInt(cmd.getOptionValue(MAX_CONCURRENCY));
191+
161192
return TransferManagerBenchmarkConfig.builder()
162193
.key(key)
163194
.bucket(bucket)
@@ -171,6 +202,9 @@ private static TransferManagerBenchmarkConfig parseConfig(CommandLine cmd) {
171202
.prefix(prefix)
172203
.contentLengthInMb(contentLengthInMb)
173204
.timeout(timeout)
205+
.connectionAcquisitionTimeoutInSec(connAcqTimeoutInSec)
206+
.forceCrtHttpClient(forceCrtHttpClient)
207+
.maxConcurrency(maxConcurrency)
174208
.build();
175209
}
176210

@@ -185,6 +219,7 @@ public enum TransferManagerOperation {
185219
private enum SdkVersion {
186220
V1,
187221
V2,
188-
CRT
222+
CRT,
223+
JAVA
189224
}
190225
}

0 commit comments

Comments
 (0)