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.s3express; 17 18 import java.util.ArrayList; 19 import java.util.List; 20 import java.util.Optional; 21 import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; 22 import software.amazon.awssdk.core.metrics.CoreMetric; 23 import software.amazon.awssdk.http.HttpMetric; 24 import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient; 25 import software.amazon.awssdk.metrics.MetricLevel; 26 import software.amazon.awssdk.metrics.MetricPublisher; 27 import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; 28 import software.amazon.awssdk.regions.Region; 29 import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient; 30 import software.amazon.awssdk.services.s3.S3AsyncClient; 31 import software.amazon.awssdk.services.s3.S3Client; 32 import software.amazon.awssdk.services.sts.StsClient; 33 import software.amazon.awssdk.services.sts.auth.StsAssumeRoleCredentialsProvider; 34 import software.amazon.awssdk.utils.Logger; 35 36 /** 37 * The S3BenchmarkRunner adds basic upload/download tests. 38 * 39 * Improvement suggestions 40 * - Add detailed metrics 41 * - Add more sophisticated support for test suites 42 * - Merge with existing benchmarking tests in this module 43 * - Dimensions: clients 44 * - Support checksumming 45 * 46 */ 47 public class S3BenchmarkRunner { 48 private static final Logger LOGGER = Logger.loggerFor("S3BenchmarkRunner"); 49 50 private static List<MetricPublisher> metricPublishers = new ArrayList<>(); 51 S3BenchmarkRunner()52 private S3BenchmarkRunner() { 53 } 54 runBenchmarks(boolean useS3Express)55 public static void runBenchmarks(boolean useS3Express) { 56 Region region = Region.US_EAST_1; 57 58 String namespacePrefix = useS3Express ? "Veyron" : "Standard"; 59 60 AwsCredentialsProvider credentialsProvider = credentialsProvider(); 61 62 CloudWatchAsyncClient cloudwatchClient = CloudWatchAsyncClient.builder() 63 .region(region) 64 .httpClient(NettyNioAsyncHttpClient.create()) 65 .credentialsProvider(credentialsProvider) 66 .build(); 67 68 S3Client s3Client = S3BenchmarkTestUtils.s3ClientBuilder(region) 69 .credentialsProvider(credentialsProvider) 70 .overrideConfiguration(o -> o.addMetricPublisher( 71 metricPublisher(cloudwatchClient, 72 namespacePrefix + "/SmallObject/Apache"))) 73 .build(); 74 75 LOGGER.info(() -> "Running small objects benchmark, 64Kb data, 5 buckets, 200 iterations"); 76 BenchmarkConfig smallObjectSyncConfig = BenchmarkConfig.builder() 77 .region(region) 78 .credentialsProvider(credentialsProvider) 79 .numBuckets(5) 80 .iteration(200) 81 .contentLengthInKb(64) 82 .useS3Express(useS3Express) 83 .az("use1-az5") 84 .build(); 85 S3PutGetDeleteSyncBenchmark syncBenchmark = new S3PutGetDeleteSyncBenchmark(smallObjectSyncConfig, s3Client); 86 syncBenchmark.run(); 87 s3Client.close(); 88 89 s3Client = S3BenchmarkTestUtils.s3ClientBuilder(region) 90 .credentialsProvider(credentialsProvider) 91 .overrideConfiguration(o -> o.addMetricPublisher( 92 metricPublisher(cloudwatchClient, 93 namespacePrefix + "/MediumObject/Apache"))) 94 .build(); 95 96 LOGGER.info(() -> "Running medium objects benchmark, 1024Kb data, 5 buckets, 200 iterations"); 97 BenchmarkConfig largeObjectSyncConfig = BenchmarkConfig.builder() 98 .region(region) 99 .credentialsProvider(credentialsProvider) 100 .numBuckets(5) 101 .iteration(200) 102 .contentLengthInKb(1024) 103 .useS3Express(useS3Express) 104 .az("use1-az5") 105 .build(); 106 syncBenchmark = new S3PutGetDeleteSyncBenchmark(largeObjectSyncConfig, s3Client); 107 syncBenchmark.run(); 108 109 s3Client.close(); 110 111 S3AsyncClient s3AsyncClient = S3BenchmarkTestUtils.s3AsyncClientBuilder(region) 112 .credentialsProvider(credentialsProvider) 113 .overrideConfiguration(o -> o.addMetricPublisher( 114 metricPublisher(cloudwatchClient, 115 namespacePrefix + "/SmallObject/Netty"))) 116 .httpClient(NettyNioAsyncHttpClient.create()) 117 .build(); 118 LOGGER.info(() -> "Running async small objects benchmark, 64Kb data, 5 buckets, 100 iterations"); 119 BenchmarkConfig smallObjectAsyncConfig = BenchmarkConfig.builder() 120 .region(region) 121 .credentialsProvider(credentialsProvider) 122 .numBuckets(5) 123 .iteration(100) 124 .contentLengthInKb(64) 125 .useS3Express(useS3Express) 126 .az("use1-az5") 127 .build(); 128 S3PutGetDeleteAsyncBenchmark asyncBenchmark = new S3PutGetDeleteAsyncBenchmark(smallObjectAsyncConfig, s3AsyncClient); 129 asyncBenchmark.run(); 130 s3AsyncClient.close(); 131 132 metricPublishers.forEach(MetricPublisher::close); 133 } 134 credentialsProvider()135 private static AwsCredentialsProvider credentialsProvider() { 136 Optional<String> roleArn = BenchmarkSystemSetting.BENCHMARK_TEST_ROLE.getStringValue(); 137 if (!roleArn.isPresent() || roleArn.get().trim().isEmpty()) { 138 throw new RuntimeException(String.format("%s environment variable not defined", 139 BenchmarkSystemSetting.BENCHMARK_TEST_ROLE)); 140 } 141 142 LOGGER.info(() -> String.format("Running benchmarks using role %s", roleArn)); 143 144 String runId = BenchmarkSystemSetting.RUN_ID.getStringValueOrThrow(); 145 return StsAssumeRoleCredentialsProvider.builder() 146 .stsClient(StsClient.create()) 147 .refreshRequest(r -> r.roleArn(roleArn.get()).roleSessionName(runId + "-s3express-perf-testing")) 148 .build(); 149 } 150 metricPublisher(CloudWatchAsyncClient cloudwatchClient, String namespace)151 private static CloudWatchMetricPublisher metricPublisher(CloudWatchAsyncClient cloudwatchClient, String namespace) { 152 CloudWatchMetricPublisher publisher = CloudWatchMetricPublisher.builder() 153 .cloudWatchClient(cloudwatchClient) 154 .namespace(namespace) 155 .dimensions(CoreMetric.SERVICE_ID, 156 CoreMetric.OPERATION_NAME, 157 HttpMetric.HTTP_CLIENT_NAME) 158 .metricLevel(MetricLevel.TRACE) 159 .build(); 160 metricPublishers.add(publisher); 161 return publisher; 162 } 163 main(String[] args)164 public static void main(String[] args) { 165 LOGGER.info(() -> "Running benchmarks against S3 Express"); 166 runBenchmarks(true); 167 LOGGER.info(() -> "Running benchmarks against Standard S3"); 168 runBenchmarks(false); 169 } 170 } 171