From 16463b0bda844db615ef1368485aa80f7c9bd7b1 Mon Sep 17 00:00:00 2001 From: Yuxuan Chen Date: Fri, 6 Jun 2025 17:05:01 -0400 Subject: [PATCH 01/77] remove s3 select tests temporarity --- .../BucketAndObjectOperationTest.cpp | 664 +++++++++--------- 1 file changed, 332 insertions(+), 332 deletions(-) diff --git a/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp b/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp index 9f1c56490ec..d41208d58d5 100644 --- a/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp +++ b/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp @@ -978,338 +978,338 @@ namespace AWS_ASSERT_SUCCESS(copyOutcome); } - TEST_F(BucketAndObjectOperationTest, TestObjectOperationWithEventStream) - { - Aws::String fullBucketName = CalculateBucketName(BASE_EVENT_STREAM_TEST_BUCKET_NAME.c_str()); - SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName); - CreateBucketRequest createBucketRequest; - createBucketRequest.SetBucket(fullBucketName); - createBucketRequest.SetACL(BucketCannedACL::private_); - CreateBucketOutcome createBucketOutcome = Client->CreateBucket(createBucketRequest); - AWS_ASSERT_SUCCESS(createBucketOutcome); - ASSERT_TRUE(WaitForBucketToPropagate(fullBucketName)); - TagTestBucket(fullBucketName, Client); - - PutObjectRequest putObjectRequest; - putObjectRequest.SetBucket(fullBucketName); - - std::shared_ptr objectStream = Aws::MakeShared(ALLOCATION_TAG); - *objectStream << "Name,Number\nAlice,1\nBob,2"; - Aws::String firstColumn = "Name\nAlice\nBob\n"; - objectStream->flush(); - putObjectRequest.SetBody(objectStream); - putObjectRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); - auto objectSize = putObjectRequest.GetBody()->tellp(); - putObjectRequest.SetContentLength(static_cast(objectSize)); - // putObjectRequest.SetContentMD5(HashingUtils::Base64Encode(HashingUtils::CalculateMD5(*putObjectRequest.GetBody()))); - putObjectRequest.SetContentType("text/csv"); - - PutObjectOutcome putObjectOutcome = Client->PutObject(putObjectRequest); - AWS_ASSERT_SUCCESS(putObjectOutcome); - - ASSERT_TRUE(WaitForObjectToPropagate(fullBucketName, TEST_EVENT_STREAM_OBJ_KEY)); - - SelectObjectContentRequest selectObjectContentRequest; - selectObjectContentRequest.SetBucket(fullBucketName); - selectObjectContentRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); - - selectObjectContentRequest.SetExpressionType(ExpressionType::SQL); - - selectObjectContentRequest.SetExpression("select s._1 from S3Object s"); - - CSVInput csvInput; - csvInput.SetFileHeaderInfo(FileHeaderInfo::NONE); - InputSerialization inputSerialization; - inputSerialization.SetCSV(csvInput); - selectObjectContentRequest.SetInputSerialization(inputSerialization); - - CSVOutput csvOutput; - OutputSerialization outputSerialization; - outputSerialization.SetCSV(csvOutput); - selectObjectContentRequest.SetOutputSerialization(outputSerialization); - - bool isRecordsEventReceived = false; - bool isStatsEventReceived = false; - - SelectObjectContentHandler handler; - handler.SetRecordsEventCallback([&](const RecordsEvent& recordsEvent) - { - isRecordsEventReceived = true; - auto recordsVector = recordsEvent.GetPayload(); - Aws::String records(recordsVector.begin(), recordsVector.end()); - ASSERT_STREQ(firstColumn.c_str(), records.c_str()); - }); - handler.SetStatsEventCallback([&](const StatsEvent& statsEvent) - { - isStatsEventReceived = true; - ASSERT_EQ(static_cast(objectSize), statsEvent.GetDetails().GetBytesScanned()); - ASSERT_EQ(static_cast(objectSize), statsEvent.GetDetails().GetBytesProcessed()); - ASSERT_EQ(static_cast(firstColumn.size()), statsEvent.GetDetails().GetBytesReturned()); - }); - - selectObjectContentRequest.SetEventStreamHandler(handler); - - auto selectObjectContentOutcome = Client->SelectObjectContent(selectObjectContentRequest); - AWS_ASSERT_SUCCESS(selectObjectContentOutcome); - ASSERT_TRUE(isRecordsEventReceived); - ASSERT_TRUE(isStatsEventReceived); - } - -#if 0 - // S3 CRT Client doesn't support custom retry strategy right now. - // This test is to test failed event stream request will not cause crash during retry. - TEST_F(BucketAndObjectOperationTest, TestSelectObjectOperationWithEventStreamFailWithRetry) - { - Aws::String fullBucketName = CalculateBucketName(BASE_EVENT_STREAM_TEST_BUCKET_NAME.c_str()); - SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName); - CreateBucketRequest createBucketRequest; - createBucketRequest.SetBucket(fullBucketName); - createBucketRequest.SetACL(BucketCannedACL::private_); - CreateBucketOutcome createBucketOutcome = Client->CreateBucket(createBucketRequest); - AWS_ASSERT_SUCCESS(createBucketOutcome); - ASSERT_TRUE(WaitForBucketToPropagate(fullBucketName)); - TagTestBucket(fullBucketName); - - PutObjectRequest putObjectRequest; - putObjectRequest.SetBucket(fullBucketName); - - std::shared_ptr objectStream = Aws::MakeShared(ALLOCATION_TAG); - *objectStream << "Name,Number\nAlice,1\nBob,2"; - Aws::String firstColumn = "Name\nAlice\nBob\n"; - objectStream->flush(); - putObjectRequest.SetBody(objectStream); - putObjectRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); - auto objectSize = putObjectRequest.GetBody()->tellp(); - putObjectRequest.SetContentLength(static_cast(objectSize)); - putObjectRequest.SetContentMD5(HashingUtils::Base64Encode(HashingUtils::CalculateMD5(*putObjectRequest.GetBody()))); - putObjectRequest.SetContentType("text/csv"); - - PutObjectOutcome putObjectOutcome = Client->PutObject(putObjectRequest); - AWS_ASSERT_SUCCESS(putObjectOutcome); - - ASSERT_TRUE(WaitForObjectToPropagate(fullBucketName, TEST_EVENT_STREAM_OBJ_KEY)); - - SelectObjectContentRequest selectObjectContentRequest; - selectObjectContentRequest.SetBucket(fullBucketName); - selectObjectContentRequest.SetKey("ANonExistenceKey"); - - selectObjectContentRequest.SetExpressionType(ExpressionType::SQL); - - selectObjectContentRequest.SetExpression("select s._1 from S3Object s"); - - CSVInput csvInput; - csvInput.SetFileHeaderInfo(FileHeaderInfo::NONE); - InputSerialization inputSerialization; - inputSerialization.SetCSV(csvInput); - selectObjectContentRequest.SetInputSerialization(inputSerialization); - - CSVOutput csvOutput; - OutputSerialization outputSerialization; - outputSerialization.SetCSV(csvOutput); - selectObjectContentRequest.SetOutputSerialization(outputSerialization); - - bool isRecordsEventReceived = false; - bool isStatsEventReceived = false; - - SelectObjectContentHandler handler; - handler.SetRecordsEventCallback([&](const RecordsEvent& recordsEvent) - { - isRecordsEventReceived = true; - auto recordsVector = recordsEvent.GetPayload(); - Aws::String records(recordsVector.begin(), recordsVector.end()); - ASSERT_STREQ(firstColumn.c_str(), records.c_str()); - }); - handler.SetStatsEventCallback([&](const StatsEvent& statsEvent) - { - isStatsEventReceived = true; - ASSERT_EQ(static_cast(objectSize), statsEvent.GetDetails().GetBytesScanned()); - ASSERT_EQ(static_cast(objectSize), statsEvent.GetDetails().GetBytesProcessed()); - ASSERT_EQ(static_cast(firstColumn.size()), statsEvent.GetDetails().GetBytesReturned()); - }); - - selectObjectContentRequest.SetEventStreamHandler(handler); - - auto selectObjectContentOutcome = retryClient->SelectObjectContent(selectObjectContentRequest); - ASSERT_FALSE(selectObjectContentOutcome.IsSuccess()); - } -#endif - - TEST_F(BucketAndObjectOperationTest, TestEventStreamWithLargeFile) - { - Aws::String fullBucketName = CalculateBucketName(BASE_EVENT_STREAM_LARGE_FILE_TEST_BUCKET_NAME.c_str()); - SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName); - CreateBucketRequest createBucketRequest; - createBucketRequest.SetBucket(fullBucketName); - createBucketRequest.SetACL(BucketCannedACL::private_); - CreateBucketOutcome createBucketOutcome = Client->CreateBucket(createBucketRequest); - AWS_ASSERT_SUCCESS(createBucketOutcome); - ASSERT_TRUE(WaitForBucketToPropagate(fullBucketName)); - TagTestBucket(fullBucketName, Client); - - PutObjectRequest putObjectRequest; - putObjectRequest.SetBucket(fullBucketName); - - std::shared_ptr objectStream = Aws::MakeShared(ALLOCATION_TAG); - *objectStream << "Name,Number\n"; - for (int i = 0; i < 1000000; i++) - { - *objectStream << "foo,0\n"; - } - objectStream->flush(); - putObjectRequest.SetBody(objectStream); - putObjectRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); - auto objectSize = putObjectRequest.GetBody()->tellp(); - putObjectRequest.SetContentLength(static_cast(objectSize)); - // putObjectRequest.SetContentMD5(HashingUtils::Base64Encode(HashingUtils::CalculateMD5(*putObjectRequest.GetBody()))); - putObjectRequest.SetContentType("text/csv"); - - PutObjectOutcome putObjectOutcome = Client->PutObject(putObjectRequest); - AWS_ASSERT_SUCCESS(putObjectOutcome); - - ASSERT_TRUE(WaitForObjectToPropagate(fullBucketName, TEST_EVENT_STREAM_OBJ_KEY)); - - SelectObjectContentRequest selectObjectContentRequest; - selectObjectContentRequest.SetBucket(fullBucketName); - selectObjectContentRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); - - selectObjectContentRequest.SetExpressionType(ExpressionType::SQL); - - selectObjectContentRequest.SetExpression("select * from S3Object where cast(number as int) < 1"); - - CSVInput csvInput; - csvInput.SetFileHeaderInfo(FileHeaderInfo::USE); - InputSerialization inputSerialization; - inputSerialization.SetCSV(csvInput); - selectObjectContentRequest.SetInputSerialization(inputSerialization); - - CSVOutput csvOutput; - OutputSerialization outputSerialization; - outputSerialization.SetCSV(csvOutput); - selectObjectContentRequest.SetOutputSerialization(outputSerialization); - - size_t recordsTotalLength = 0; - bool isStatsEventReceived = false; - - SelectObjectContentHandler handler; - handler.SetRecordsEventCallback([&](const RecordsEvent& recordsEvent) - { - recordsTotalLength += recordsEvent.GetPayload().size(); - }); - handler.SetStatsEventCallback([&](const StatsEvent& statsEvent) - { - isStatsEventReceived = true; - ASSERT_EQ(12ll/*length of the 1st row*/ + 6/*length of all the other row*/ * 1000000ll, statsEvent.GetDetails().GetBytesScanned()); - ASSERT_EQ(6000012ll, statsEvent.GetDetails().GetBytesProcessed()); - ASSERT_EQ(6000000ll, statsEvent.GetDetails().GetBytesReturned()); - }); - - selectObjectContentRequest.SetEventStreamHandler(handler); - - auto selectObjectContentOutcome = Client->SelectObjectContent(selectObjectContentRequest); - ASSERT_EQ(6000000u, recordsTotalLength); - ASSERT_TRUE(isStatsEventReceived); - } - - TEST_F(BucketAndObjectOperationTest, TestErrorsInXml) - { - SelectObjectContentRequest selectObjectContentRequest; - selectObjectContentRequest.SetBucket("adskflaklfakl"); - selectObjectContentRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); - - selectObjectContentRequest.SetExpressionType(ExpressionType::SQL); - - selectObjectContentRequest.SetExpression("select s._1 from S3Object s"); - - CSVInput csvInput; - csvInput.SetFileHeaderInfo(FileHeaderInfo::USE); - InputSerialization inputSerialization; - inputSerialization.SetCSV(csvInput); - selectObjectContentRequest.SetInputSerialization(inputSerialization); - - CSVOutput csvOutput; - OutputSerialization outputSerialization; - outputSerialization.SetCSV(csvOutput); - selectObjectContentRequest.SetOutputSerialization(outputSerialization); - - auto selectObjectContentOutcome = Client->SelectObjectContent(selectObjectContentRequest); - ASSERT_FALSE(selectObjectContentOutcome.IsSuccess()); -#if ENABLE_CURL_CLIENT - ASSERT_FALSE(selectObjectContentOutcome.GetError().GetRemoteHostIpAddress().empty()); -#endif - ASSERT_FALSE(selectObjectContentOutcome.GetError().GetRequestId().empty()); - ASSERT_EQ(S3CrtErrors::NO_SUCH_BUCKET, selectObjectContentOutcome.GetError().GetErrorType()); - } - - TEST_F(BucketAndObjectOperationTest, TestErrorsInEventStream) - { - Aws::String fullBucketName = CalculateBucketName(BASE_EVENT_STREAM_ERRORS_IN_EVENT_TEST_BUCKET_NAME.c_str()); - SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName); - CreateBucketRequest createBucketRequest; - createBucketRequest.SetBucket(fullBucketName); - createBucketRequest.SetACL(BucketCannedACL::private_); - CreateBucketOutcome createBucketOutcome = Client->CreateBucket(createBucketRequest); - AWS_ASSERT_SUCCESS(createBucketOutcome); - ASSERT_TRUE(WaitForBucketToPropagate(fullBucketName)); - TagTestBucket(fullBucketName, Client); - - PutObjectRequest putObjectRequest; - putObjectRequest.SetBucket(fullBucketName); - - std::shared_ptr objectStream = Aws::MakeShared(ALLOCATION_TAG); - *objectStream << "Name,Number\n"; - for (int i = 0; i < 1000000; i++) - { - *objectStream << "foo,0\n"; - } - *objectStream << "bar,NAN"; - objectStream->flush(); - putObjectRequest.SetBody(objectStream); - putObjectRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); - auto objectSize = putObjectRequest.GetBody()->tellp(); - putObjectRequest.SetContentLength(static_cast(objectSize)); - // putObjectRequest.SetContentMD5(HashingUtils::Base64Encode(HashingUtils::CalculateMD5(*putObjectRequest.GetBody()))); - putObjectRequest.SetContentType("text/csv"); - - PutObjectOutcome putObjectOutcome = Client->PutObject(putObjectRequest); - AWS_ASSERT_SUCCESS(putObjectOutcome); - - ASSERT_TRUE(WaitForObjectToPropagate(fullBucketName, TEST_EVENT_STREAM_OBJ_KEY)); - - SelectObjectContentRequest selectObjectContentRequest; - selectObjectContentRequest.SetBucket(fullBucketName); - selectObjectContentRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); - - selectObjectContentRequest.SetExpressionType(ExpressionType::SQL); - - selectObjectContentRequest.SetExpression("select * from S3Object where cast(number as int) < 1"); - - CSVInput csvInput; - csvInput.SetFileHeaderInfo(FileHeaderInfo::USE); - InputSerialization inputSerialization; - inputSerialization.SetCSV(csvInput); - selectObjectContentRequest.SetInputSerialization(inputSerialization); - - CSVOutput csvOutput; - OutputSerialization outputSerialization; - outputSerialization.SetCSV(csvOutput); - selectObjectContentRequest.SetOutputSerialization(outputSerialization); - - bool isErrorEventReceived = false; - - SelectObjectContentHandler handler; - handler.SetOnErrorCallback([&](const AWSError& s3Error) - { - isErrorEventReceived = true; - ASSERT_EQ(CoreErrors::UNKNOWN, static_cast(s3Error.GetErrorType())); - ASSERT_STREQ("CastFailed", s3Error.GetExceptionName().c_str()); - }); - - selectObjectContentRequest.SetEventStreamHandler(handler); - - Client->SelectObjectContent(selectObjectContentRequest); - - ASSERT_TRUE(isErrorEventReceived); - } +// TEST_F(BucketAndObjectOperationTest, TestObjectOperationWithEventStream) +// { +// Aws::String fullBucketName = CalculateBucketName(BASE_EVENT_STREAM_TEST_BUCKET_NAME.c_str()); +// SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName); +// CreateBucketRequest createBucketRequest; +// createBucketRequest.SetBucket(fullBucketName); +// createBucketRequest.SetACL(BucketCannedACL::private_); +// CreateBucketOutcome createBucketOutcome = Client->CreateBucket(createBucketRequest); +// AWS_ASSERT_SUCCESS(createBucketOutcome); +// ASSERT_TRUE(WaitForBucketToPropagate(fullBucketName)); +// TagTestBucket(fullBucketName, Client); + +// PutObjectRequest putObjectRequest; +// putObjectRequest.SetBucket(fullBucketName); + +// std::shared_ptr objectStream = Aws::MakeShared(ALLOCATION_TAG); +// *objectStream << "Name,Number\nAlice,1\nBob,2"; +// Aws::String firstColumn = "Name\nAlice\nBob\n"; +// objectStream->flush(); +// putObjectRequest.SetBody(objectStream); +// putObjectRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); +// auto objectSize = putObjectRequest.GetBody()->tellp(); +// putObjectRequest.SetContentLength(static_cast(objectSize)); +// // putObjectRequest.SetContentMD5(HashingUtils::Base64Encode(HashingUtils::CalculateMD5(*putObjectRequest.GetBody()))); +// putObjectRequest.SetContentType("text/csv"); + +// PutObjectOutcome putObjectOutcome = Client->PutObject(putObjectRequest); +// AWS_ASSERT_SUCCESS(putObjectOutcome); + +// ASSERT_TRUE(WaitForObjectToPropagate(fullBucketName, TEST_EVENT_STREAM_OBJ_KEY)); + +// SelectObjectContentRequest selectObjectContentRequest; +// selectObjectContentRequest.SetBucket(fullBucketName); +// selectObjectContentRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); + +// selectObjectContentRequest.SetExpressionType(ExpressionType::SQL); + +// selectObjectContentRequest.SetExpression("select s._1 from S3Object s"); + +// CSVInput csvInput; +// csvInput.SetFileHeaderInfo(FileHeaderInfo::NONE); +// InputSerialization inputSerialization; +// inputSerialization.SetCSV(csvInput); +// selectObjectContentRequest.SetInputSerialization(inputSerialization); + +// CSVOutput csvOutput; +// OutputSerialization outputSerialization; +// outputSerialization.SetCSV(csvOutput); +// selectObjectContentRequest.SetOutputSerialization(outputSerialization); + +// bool isRecordsEventReceived = false; +// bool isStatsEventReceived = false; + +// SelectObjectContentHandler handler; +// handler.SetRecordsEventCallback([&](const RecordsEvent& recordsEvent) +// { +// isRecordsEventReceived = true; +// auto recordsVector = recordsEvent.GetPayload(); +// Aws::String records(recordsVector.begin(), recordsVector.end()); +// ASSERT_STREQ(firstColumn.c_str(), records.c_str()); +// }); +// handler.SetStatsEventCallback([&](const StatsEvent& statsEvent) +// { +// isStatsEventReceived = true; +// ASSERT_EQ(static_cast(objectSize), statsEvent.GetDetails().GetBytesScanned()); +// ASSERT_EQ(static_cast(objectSize), statsEvent.GetDetails().GetBytesProcessed()); +// ASSERT_EQ(static_cast(firstColumn.size()), statsEvent.GetDetails().GetBytesReturned()); +// }); + +// selectObjectContentRequest.SetEventStreamHandler(handler); + +// auto selectObjectContentOutcome = Client->SelectObjectContent(selectObjectContentRequest); +// AWS_ASSERT_SUCCESS(selectObjectContentOutcome); +// ASSERT_TRUE(isRecordsEventReceived); +// ASSERT_TRUE(isStatsEventReceived); +// } + +// #if 0 +// // S3 CRT Client doesn't support custom retry strategy right now. +// // This test is to test failed event stream request will not cause crash during retry. +// TEST_F(BucketAndObjectOperationTest, TestSelectObjectOperationWithEventStreamFailWithRetry) +// { +// Aws::String fullBucketName = CalculateBucketName(BASE_EVENT_STREAM_TEST_BUCKET_NAME.c_str()); +// SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName); +// CreateBucketRequest createBucketRequest; +// createBucketRequest.SetBucket(fullBucketName); +// createBucketRequest.SetACL(BucketCannedACL::private_); +// CreateBucketOutcome createBucketOutcome = Client->CreateBucket(createBucketRequest); +// AWS_ASSERT_SUCCESS(createBucketOutcome); +// ASSERT_TRUE(WaitForBucketToPropagate(fullBucketName)); +// TagTestBucket(fullBucketName); + +// PutObjectRequest putObjectRequest; +// putObjectRequest.SetBucket(fullBucketName); + +// std::shared_ptr objectStream = Aws::MakeShared(ALLOCATION_TAG); +// *objectStream << "Name,Number\nAlice,1\nBob,2"; +// Aws::String firstColumn = "Name\nAlice\nBob\n"; +// objectStream->flush(); +// putObjectRequest.SetBody(objectStream); +// putObjectRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); +// auto objectSize = putObjectRequest.GetBody()->tellp(); +// putObjectRequest.SetContentLength(static_cast(objectSize)); +// putObjectRequest.SetContentMD5(HashingUtils::Base64Encode(HashingUtils::CalculateMD5(*putObjectRequest.GetBody()))); +// putObjectRequest.SetContentType("text/csv"); + +// PutObjectOutcome putObjectOutcome = Client->PutObject(putObjectRequest); +// AWS_ASSERT_SUCCESS(putObjectOutcome); + +// ASSERT_TRUE(WaitForObjectToPropagate(fullBucketName, TEST_EVENT_STREAM_OBJ_KEY)); + +// SelectObjectContentRequest selectObjectContentRequest; +// selectObjectContentRequest.SetBucket(fullBucketName); +// selectObjectContentRequest.SetKey("ANonExistenceKey"); + +// selectObjectContentRequest.SetExpressionType(ExpressionType::SQL); + +// selectObjectContentRequest.SetExpression("select s._1 from S3Object s"); + +// CSVInput csvInput; +// csvInput.SetFileHeaderInfo(FileHeaderInfo::NONE); +// InputSerialization inputSerialization; +// inputSerialization.SetCSV(csvInput); +// selectObjectContentRequest.SetInputSerialization(inputSerialization); + +// CSVOutput csvOutput; +// OutputSerialization outputSerialization; +// outputSerialization.SetCSV(csvOutput); +// selectObjectContentRequest.SetOutputSerialization(outputSerialization); + +// bool isRecordsEventReceived = false; +// bool isStatsEventReceived = false; + +// SelectObjectContentHandler handler; +// handler.SetRecordsEventCallback([&](const RecordsEvent& recordsEvent) +// { +// isRecordsEventReceived = true; +// auto recordsVector = recordsEvent.GetPayload(); +// Aws::String records(recordsVector.begin(), recordsVector.end()); +// ASSERT_STREQ(firstColumn.c_str(), records.c_str()); +// }); +// handler.SetStatsEventCallback([&](const StatsEvent& statsEvent) +// { +// isStatsEventReceived = true; +// ASSERT_EQ(static_cast(objectSize), statsEvent.GetDetails().GetBytesScanned()); +// ASSERT_EQ(static_cast(objectSize), statsEvent.GetDetails().GetBytesProcessed()); +// ASSERT_EQ(static_cast(firstColumn.size()), statsEvent.GetDetails().GetBytesReturned()); +// }); + +// selectObjectContentRequest.SetEventStreamHandler(handler); + +// auto selectObjectContentOutcome = retryClient->SelectObjectContent(selectObjectContentRequest); +// ASSERT_FALSE(selectObjectContentOutcome.IsSuccess()); +// } +// #endif + +// TEST_F(BucketAndObjectOperationTest, TestEventStreamWithLargeFile) +// { +// Aws::String fullBucketName = CalculateBucketName(BASE_EVENT_STREAM_LARGE_FILE_TEST_BUCKET_NAME.c_str()); +// SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName); +// CreateBucketRequest createBucketRequest; +// createBucketRequest.SetBucket(fullBucketName); +// createBucketRequest.SetACL(BucketCannedACL::private_); +// CreateBucketOutcome createBucketOutcome = Client->CreateBucket(createBucketRequest); +// AWS_ASSERT_SUCCESS(createBucketOutcome); +// ASSERT_TRUE(WaitForBucketToPropagate(fullBucketName)); +// TagTestBucket(fullBucketName, Client); + +// PutObjectRequest putObjectRequest; +// putObjectRequest.SetBucket(fullBucketName); + +// std::shared_ptr objectStream = Aws::MakeShared(ALLOCATION_TAG); +// *objectStream << "Name,Number\n"; +// for (int i = 0; i < 1000000; i++) +// { +// *objectStream << "foo,0\n"; +// } +// objectStream->flush(); +// putObjectRequest.SetBody(objectStream); +// putObjectRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); +// auto objectSize = putObjectRequest.GetBody()->tellp(); +// putObjectRequest.SetContentLength(static_cast(objectSize)); +// // putObjectRequest.SetContentMD5(HashingUtils::Base64Encode(HashingUtils::CalculateMD5(*putObjectRequest.GetBody()))); +// putObjectRequest.SetContentType("text/csv"); + +// PutObjectOutcome putObjectOutcome = Client->PutObject(putObjectRequest); +// AWS_ASSERT_SUCCESS(putObjectOutcome); + +// ASSERT_TRUE(WaitForObjectToPropagate(fullBucketName, TEST_EVENT_STREAM_OBJ_KEY)); + +// SelectObjectContentRequest selectObjectContentRequest; +// selectObjectContentRequest.SetBucket(fullBucketName); +// selectObjectContentRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); + +// selectObjectContentRequest.SetExpressionType(ExpressionType::SQL); + +// selectObjectContentRequest.SetExpression("select * from S3Object where cast(number as int) < 1"); + +// CSVInput csvInput; +// csvInput.SetFileHeaderInfo(FileHeaderInfo::USE); +// InputSerialization inputSerialization; +// inputSerialization.SetCSV(csvInput); +// selectObjectContentRequest.SetInputSerialization(inputSerialization); + +// CSVOutput csvOutput; +// OutputSerialization outputSerialization; +// outputSerialization.SetCSV(csvOutput); +// selectObjectContentRequest.SetOutputSerialization(outputSerialization); + +// size_t recordsTotalLength = 0; +// bool isStatsEventReceived = false; + +// SelectObjectContentHandler handler; +// handler.SetRecordsEventCallback([&](const RecordsEvent& recordsEvent) +// { +// recordsTotalLength += recordsEvent.GetPayload().size(); +// }); +// handler.SetStatsEventCallback([&](const StatsEvent& statsEvent) +// { +// isStatsEventReceived = true; +// ASSERT_EQ(12ll/*length of the 1st row*/ + 6/*length of all the other row*/ * 1000000ll, statsEvent.GetDetails().GetBytesScanned()); +// ASSERT_EQ(6000012ll, statsEvent.GetDetails().GetBytesProcessed()); +// ASSERT_EQ(6000000ll, statsEvent.GetDetails().GetBytesReturned()); +// }); + +// selectObjectContentRequest.SetEventStreamHandler(handler); + +// auto selectObjectContentOutcome = Client->SelectObjectContent(selectObjectContentRequest); +// ASSERT_EQ(6000000u, recordsTotalLength); +// ASSERT_TRUE(isStatsEventReceived); +// } + +// TEST_F(BucketAndObjectOperationTest, TestErrorsInXml) +// { +// SelectObjectContentRequest selectObjectContentRequest; +// selectObjectContentRequest.SetBucket("adskflaklfakl"); +// selectObjectContentRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); + +// selectObjectContentRequest.SetExpressionType(ExpressionType::SQL); + +// selectObjectContentRequest.SetExpression("select s._1 from S3Object s"); + +// CSVInput csvInput; +// csvInput.SetFileHeaderInfo(FileHeaderInfo::USE); +// InputSerialization inputSerialization; +// inputSerialization.SetCSV(csvInput); +// selectObjectContentRequest.SetInputSerialization(inputSerialization); + +// CSVOutput csvOutput; +// OutputSerialization outputSerialization; +// outputSerialization.SetCSV(csvOutput); +// selectObjectContentRequest.SetOutputSerialization(outputSerialization); + +// auto selectObjectContentOutcome = Client->SelectObjectContent(selectObjectContentRequest); +// ASSERT_FALSE(selectObjectContentOutcome.IsSuccess()); +// #if ENABLE_CURL_CLIENT +// ASSERT_FALSE(selectObjectContentOutcome.GetError().GetRemoteHostIpAddress().empty()); +// #endif +// ASSERT_FALSE(selectObjectContentOutcome.GetError().GetRequestId().empty()); +// ASSERT_EQ(S3CrtErrors::NO_SUCH_BUCKET, selectObjectContentOutcome.GetError().GetErrorType()); +// } + +// TEST_F(BucketAndObjectOperationTest, TestErrorsInEventStream) +// { +// Aws::String fullBucketName = CalculateBucketName(BASE_EVENT_STREAM_ERRORS_IN_EVENT_TEST_BUCKET_NAME.c_str()); +// SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName); +// CreateBucketRequest createBucketRequest; +// createBucketRequest.SetBucket(fullBucketName); +// createBucketRequest.SetACL(BucketCannedACL::private_); +// CreateBucketOutcome createBucketOutcome = Client->CreateBucket(createBucketRequest); +// AWS_ASSERT_SUCCESS(createBucketOutcome); +// ASSERT_TRUE(WaitForBucketToPropagate(fullBucketName)); +// TagTestBucket(fullBucketName, Client); + +// PutObjectRequest putObjectRequest; +// putObjectRequest.SetBucket(fullBucketName); + +// std::shared_ptr objectStream = Aws::MakeShared(ALLOCATION_TAG); +// *objectStream << "Name,Number\n"; +// for (int i = 0; i < 1000000; i++) +// { +// *objectStream << "foo,0\n"; +// } +// *objectStream << "bar,NAN"; +// objectStream->flush(); +// putObjectRequest.SetBody(objectStream); +// putObjectRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); +// auto objectSize = putObjectRequest.GetBody()->tellp(); +// putObjectRequest.SetContentLength(static_cast(objectSize)); +// // putObjectRequest.SetContentMD5(HashingUtils::Base64Encode(HashingUtils::CalculateMD5(*putObjectRequest.GetBody()))); +// putObjectRequest.SetContentType("text/csv"); + +// PutObjectOutcome putObjectOutcome = Client->PutObject(putObjectRequest); +// AWS_ASSERT_SUCCESS(putObjectOutcome); + +// ASSERT_TRUE(WaitForObjectToPropagate(fullBucketName, TEST_EVENT_STREAM_OBJ_KEY)); + +// SelectObjectContentRequest selectObjectContentRequest; +// selectObjectContentRequest.SetBucket(fullBucketName); +// selectObjectContentRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); + +// selectObjectContentRequest.SetExpressionType(ExpressionType::SQL); + +// selectObjectContentRequest.SetExpression("select * from S3Object where cast(number as int) < 1"); + +// CSVInput csvInput; +// csvInput.SetFileHeaderInfo(FileHeaderInfo::USE); +// InputSerialization inputSerialization; +// inputSerialization.SetCSV(csvInput); +// selectObjectContentRequest.SetInputSerialization(inputSerialization); + +// CSVOutput csvOutput; +// OutputSerialization outputSerialization; +// outputSerialization.SetCSV(csvOutput); +// selectObjectContentRequest.SetOutputSerialization(outputSerialization); + +// bool isErrorEventReceived = false; + +// SelectObjectContentHandler handler; +// handler.SetOnErrorCallback([&](const AWSError& s3Error) +// { +// isErrorEventReceived = true; +// ASSERT_EQ(CoreErrors::UNKNOWN, static_cast(s3Error.GetErrorType())); +// ASSERT_STREQ("CastFailed", s3Error.GetExceptionName().c_str()); +// }); + +// selectObjectContentRequest.SetEventStreamHandler(handler); + +// Client->SelectObjectContent(selectObjectContentRequest); + +// ASSERT_TRUE(isErrorEventReceived); +// } TEST_F(BucketAndObjectOperationTest, TestNullBody) { From 1ecd0c43aa2f5571fd542614eeba32010c365652 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Mon, 9 Jun 2025 12:19:46 -0400 Subject: [PATCH 02/77] fix removal of s3 select tests --- .../BucketAndObjectOperationTest.cpp | 333 ------------------ 1 file changed, 333 deletions(-) diff --git a/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp b/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp index d41208d58d5..a5d91fd27e9 100644 --- a/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp +++ b/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp @@ -978,339 +978,6 @@ namespace AWS_ASSERT_SUCCESS(copyOutcome); } -// TEST_F(BucketAndObjectOperationTest, TestObjectOperationWithEventStream) -// { -// Aws::String fullBucketName = CalculateBucketName(BASE_EVENT_STREAM_TEST_BUCKET_NAME.c_str()); -// SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName); -// CreateBucketRequest createBucketRequest; -// createBucketRequest.SetBucket(fullBucketName); -// createBucketRequest.SetACL(BucketCannedACL::private_); -// CreateBucketOutcome createBucketOutcome = Client->CreateBucket(createBucketRequest); -// AWS_ASSERT_SUCCESS(createBucketOutcome); -// ASSERT_TRUE(WaitForBucketToPropagate(fullBucketName)); -// TagTestBucket(fullBucketName, Client); - -// PutObjectRequest putObjectRequest; -// putObjectRequest.SetBucket(fullBucketName); - -// std::shared_ptr objectStream = Aws::MakeShared(ALLOCATION_TAG); -// *objectStream << "Name,Number\nAlice,1\nBob,2"; -// Aws::String firstColumn = "Name\nAlice\nBob\n"; -// objectStream->flush(); -// putObjectRequest.SetBody(objectStream); -// putObjectRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); -// auto objectSize = putObjectRequest.GetBody()->tellp(); -// putObjectRequest.SetContentLength(static_cast(objectSize)); -// // putObjectRequest.SetContentMD5(HashingUtils::Base64Encode(HashingUtils::CalculateMD5(*putObjectRequest.GetBody()))); -// putObjectRequest.SetContentType("text/csv"); - -// PutObjectOutcome putObjectOutcome = Client->PutObject(putObjectRequest); -// AWS_ASSERT_SUCCESS(putObjectOutcome); - -// ASSERT_TRUE(WaitForObjectToPropagate(fullBucketName, TEST_EVENT_STREAM_OBJ_KEY)); - -// SelectObjectContentRequest selectObjectContentRequest; -// selectObjectContentRequest.SetBucket(fullBucketName); -// selectObjectContentRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); - -// selectObjectContentRequest.SetExpressionType(ExpressionType::SQL); - -// selectObjectContentRequest.SetExpression("select s._1 from S3Object s"); - -// CSVInput csvInput; -// csvInput.SetFileHeaderInfo(FileHeaderInfo::NONE); -// InputSerialization inputSerialization; -// inputSerialization.SetCSV(csvInput); -// selectObjectContentRequest.SetInputSerialization(inputSerialization); - -// CSVOutput csvOutput; -// OutputSerialization outputSerialization; -// outputSerialization.SetCSV(csvOutput); -// selectObjectContentRequest.SetOutputSerialization(outputSerialization); - -// bool isRecordsEventReceived = false; -// bool isStatsEventReceived = false; - -// SelectObjectContentHandler handler; -// handler.SetRecordsEventCallback([&](const RecordsEvent& recordsEvent) -// { -// isRecordsEventReceived = true; -// auto recordsVector = recordsEvent.GetPayload(); -// Aws::String records(recordsVector.begin(), recordsVector.end()); -// ASSERT_STREQ(firstColumn.c_str(), records.c_str()); -// }); -// handler.SetStatsEventCallback([&](const StatsEvent& statsEvent) -// { -// isStatsEventReceived = true; -// ASSERT_EQ(static_cast(objectSize), statsEvent.GetDetails().GetBytesScanned()); -// ASSERT_EQ(static_cast(objectSize), statsEvent.GetDetails().GetBytesProcessed()); -// ASSERT_EQ(static_cast(firstColumn.size()), statsEvent.GetDetails().GetBytesReturned()); -// }); - -// selectObjectContentRequest.SetEventStreamHandler(handler); - -// auto selectObjectContentOutcome = Client->SelectObjectContent(selectObjectContentRequest); -// AWS_ASSERT_SUCCESS(selectObjectContentOutcome); -// ASSERT_TRUE(isRecordsEventReceived); -// ASSERT_TRUE(isStatsEventReceived); -// } - -// #if 0 -// // S3 CRT Client doesn't support custom retry strategy right now. -// // This test is to test failed event stream request will not cause crash during retry. -// TEST_F(BucketAndObjectOperationTest, TestSelectObjectOperationWithEventStreamFailWithRetry) -// { -// Aws::String fullBucketName = CalculateBucketName(BASE_EVENT_STREAM_TEST_BUCKET_NAME.c_str()); -// SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName); -// CreateBucketRequest createBucketRequest; -// createBucketRequest.SetBucket(fullBucketName); -// createBucketRequest.SetACL(BucketCannedACL::private_); -// CreateBucketOutcome createBucketOutcome = Client->CreateBucket(createBucketRequest); -// AWS_ASSERT_SUCCESS(createBucketOutcome); -// ASSERT_TRUE(WaitForBucketToPropagate(fullBucketName)); -// TagTestBucket(fullBucketName); - -// PutObjectRequest putObjectRequest; -// putObjectRequest.SetBucket(fullBucketName); - -// std::shared_ptr objectStream = Aws::MakeShared(ALLOCATION_TAG); -// *objectStream << "Name,Number\nAlice,1\nBob,2"; -// Aws::String firstColumn = "Name\nAlice\nBob\n"; -// objectStream->flush(); -// putObjectRequest.SetBody(objectStream); -// putObjectRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); -// auto objectSize = putObjectRequest.GetBody()->tellp(); -// putObjectRequest.SetContentLength(static_cast(objectSize)); -// putObjectRequest.SetContentMD5(HashingUtils::Base64Encode(HashingUtils::CalculateMD5(*putObjectRequest.GetBody()))); -// putObjectRequest.SetContentType("text/csv"); - -// PutObjectOutcome putObjectOutcome = Client->PutObject(putObjectRequest); -// AWS_ASSERT_SUCCESS(putObjectOutcome); - -// ASSERT_TRUE(WaitForObjectToPropagate(fullBucketName, TEST_EVENT_STREAM_OBJ_KEY)); - -// SelectObjectContentRequest selectObjectContentRequest; -// selectObjectContentRequest.SetBucket(fullBucketName); -// selectObjectContentRequest.SetKey("ANonExistenceKey"); - -// selectObjectContentRequest.SetExpressionType(ExpressionType::SQL); - -// selectObjectContentRequest.SetExpression("select s._1 from S3Object s"); - -// CSVInput csvInput; -// csvInput.SetFileHeaderInfo(FileHeaderInfo::NONE); -// InputSerialization inputSerialization; -// inputSerialization.SetCSV(csvInput); -// selectObjectContentRequest.SetInputSerialization(inputSerialization); - -// CSVOutput csvOutput; -// OutputSerialization outputSerialization; -// outputSerialization.SetCSV(csvOutput); -// selectObjectContentRequest.SetOutputSerialization(outputSerialization); - -// bool isRecordsEventReceived = false; -// bool isStatsEventReceived = false; - -// SelectObjectContentHandler handler; -// handler.SetRecordsEventCallback([&](const RecordsEvent& recordsEvent) -// { -// isRecordsEventReceived = true; -// auto recordsVector = recordsEvent.GetPayload(); -// Aws::String records(recordsVector.begin(), recordsVector.end()); -// ASSERT_STREQ(firstColumn.c_str(), records.c_str()); -// }); -// handler.SetStatsEventCallback([&](const StatsEvent& statsEvent) -// { -// isStatsEventReceived = true; -// ASSERT_EQ(static_cast(objectSize), statsEvent.GetDetails().GetBytesScanned()); -// ASSERT_EQ(static_cast(objectSize), statsEvent.GetDetails().GetBytesProcessed()); -// ASSERT_EQ(static_cast(firstColumn.size()), statsEvent.GetDetails().GetBytesReturned()); -// }); - -// selectObjectContentRequest.SetEventStreamHandler(handler); - -// auto selectObjectContentOutcome = retryClient->SelectObjectContent(selectObjectContentRequest); -// ASSERT_FALSE(selectObjectContentOutcome.IsSuccess()); -// } -// #endif - -// TEST_F(BucketAndObjectOperationTest, TestEventStreamWithLargeFile) -// { -// Aws::String fullBucketName = CalculateBucketName(BASE_EVENT_STREAM_LARGE_FILE_TEST_BUCKET_NAME.c_str()); -// SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName); -// CreateBucketRequest createBucketRequest; -// createBucketRequest.SetBucket(fullBucketName); -// createBucketRequest.SetACL(BucketCannedACL::private_); -// CreateBucketOutcome createBucketOutcome = Client->CreateBucket(createBucketRequest); -// AWS_ASSERT_SUCCESS(createBucketOutcome); -// ASSERT_TRUE(WaitForBucketToPropagate(fullBucketName)); -// TagTestBucket(fullBucketName, Client); - -// PutObjectRequest putObjectRequest; -// putObjectRequest.SetBucket(fullBucketName); - -// std::shared_ptr objectStream = Aws::MakeShared(ALLOCATION_TAG); -// *objectStream << "Name,Number\n"; -// for (int i = 0; i < 1000000; i++) -// { -// *objectStream << "foo,0\n"; -// } -// objectStream->flush(); -// putObjectRequest.SetBody(objectStream); -// putObjectRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); -// auto objectSize = putObjectRequest.GetBody()->tellp(); -// putObjectRequest.SetContentLength(static_cast(objectSize)); -// // putObjectRequest.SetContentMD5(HashingUtils::Base64Encode(HashingUtils::CalculateMD5(*putObjectRequest.GetBody()))); -// putObjectRequest.SetContentType("text/csv"); - -// PutObjectOutcome putObjectOutcome = Client->PutObject(putObjectRequest); -// AWS_ASSERT_SUCCESS(putObjectOutcome); - -// ASSERT_TRUE(WaitForObjectToPropagate(fullBucketName, TEST_EVENT_STREAM_OBJ_KEY)); - -// SelectObjectContentRequest selectObjectContentRequest; -// selectObjectContentRequest.SetBucket(fullBucketName); -// selectObjectContentRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); - -// selectObjectContentRequest.SetExpressionType(ExpressionType::SQL); - -// selectObjectContentRequest.SetExpression("select * from S3Object where cast(number as int) < 1"); - -// CSVInput csvInput; -// csvInput.SetFileHeaderInfo(FileHeaderInfo::USE); -// InputSerialization inputSerialization; -// inputSerialization.SetCSV(csvInput); -// selectObjectContentRequest.SetInputSerialization(inputSerialization); - -// CSVOutput csvOutput; -// OutputSerialization outputSerialization; -// outputSerialization.SetCSV(csvOutput); -// selectObjectContentRequest.SetOutputSerialization(outputSerialization); - -// size_t recordsTotalLength = 0; -// bool isStatsEventReceived = false; - -// SelectObjectContentHandler handler; -// handler.SetRecordsEventCallback([&](const RecordsEvent& recordsEvent) -// { -// recordsTotalLength += recordsEvent.GetPayload().size(); -// }); -// handler.SetStatsEventCallback([&](const StatsEvent& statsEvent) -// { -// isStatsEventReceived = true; -// ASSERT_EQ(12ll/*length of the 1st row*/ + 6/*length of all the other row*/ * 1000000ll, statsEvent.GetDetails().GetBytesScanned()); -// ASSERT_EQ(6000012ll, statsEvent.GetDetails().GetBytesProcessed()); -// ASSERT_EQ(6000000ll, statsEvent.GetDetails().GetBytesReturned()); -// }); - -// selectObjectContentRequest.SetEventStreamHandler(handler); - -// auto selectObjectContentOutcome = Client->SelectObjectContent(selectObjectContentRequest); -// ASSERT_EQ(6000000u, recordsTotalLength); -// ASSERT_TRUE(isStatsEventReceived); -// } - -// TEST_F(BucketAndObjectOperationTest, TestErrorsInXml) -// { -// SelectObjectContentRequest selectObjectContentRequest; -// selectObjectContentRequest.SetBucket("adskflaklfakl"); -// selectObjectContentRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); - -// selectObjectContentRequest.SetExpressionType(ExpressionType::SQL); - -// selectObjectContentRequest.SetExpression("select s._1 from S3Object s"); - -// CSVInput csvInput; -// csvInput.SetFileHeaderInfo(FileHeaderInfo::USE); -// InputSerialization inputSerialization; -// inputSerialization.SetCSV(csvInput); -// selectObjectContentRequest.SetInputSerialization(inputSerialization); - -// CSVOutput csvOutput; -// OutputSerialization outputSerialization; -// outputSerialization.SetCSV(csvOutput); -// selectObjectContentRequest.SetOutputSerialization(outputSerialization); - -// auto selectObjectContentOutcome = Client->SelectObjectContent(selectObjectContentRequest); -// ASSERT_FALSE(selectObjectContentOutcome.IsSuccess()); -// #if ENABLE_CURL_CLIENT -// ASSERT_FALSE(selectObjectContentOutcome.GetError().GetRemoteHostIpAddress().empty()); -// #endif -// ASSERT_FALSE(selectObjectContentOutcome.GetError().GetRequestId().empty()); -// ASSERT_EQ(S3CrtErrors::NO_SUCH_BUCKET, selectObjectContentOutcome.GetError().GetErrorType()); -// } - -// TEST_F(BucketAndObjectOperationTest, TestErrorsInEventStream) -// { -// Aws::String fullBucketName = CalculateBucketName(BASE_EVENT_STREAM_ERRORS_IN_EVENT_TEST_BUCKET_NAME.c_str()); -// SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName); -// CreateBucketRequest createBucketRequest; -// createBucketRequest.SetBucket(fullBucketName); -// createBucketRequest.SetACL(BucketCannedACL::private_); -// CreateBucketOutcome createBucketOutcome = Client->CreateBucket(createBucketRequest); -// AWS_ASSERT_SUCCESS(createBucketOutcome); -// ASSERT_TRUE(WaitForBucketToPropagate(fullBucketName)); -// TagTestBucket(fullBucketName, Client); - -// PutObjectRequest putObjectRequest; -// putObjectRequest.SetBucket(fullBucketName); - -// std::shared_ptr objectStream = Aws::MakeShared(ALLOCATION_TAG); -// *objectStream << "Name,Number\n"; -// for (int i = 0; i < 1000000; i++) -// { -// *objectStream << "foo,0\n"; -// } -// *objectStream << "bar,NAN"; -// objectStream->flush(); -// putObjectRequest.SetBody(objectStream); -// putObjectRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); -// auto objectSize = putObjectRequest.GetBody()->tellp(); -// putObjectRequest.SetContentLength(static_cast(objectSize)); -// // putObjectRequest.SetContentMD5(HashingUtils::Base64Encode(HashingUtils::CalculateMD5(*putObjectRequest.GetBody()))); -// putObjectRequest.SetContentType("text/csv"); - -// PutObjectOutcome putObjectOutcome = Client->PutObject(putObjectRequest); -// AWS_ASSERT_SUCCESS(putObjectOutcome); - -// ASSERT_TRUE(WaitForObjectToPropagate(fullBucketName, TEST_EVENT_STREAM_OBJ_KEY)); - -// SelectObjectContentRequest selectObjectContentRequest; -// selectObjectContentRequest.SetBucket(fullBucketName); -// selectObjectContentRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); - -// selectObjectContentRequest.SetExpressionType(ExpressionType::SQL); - -// selectObjectContentRequest.SetExpression("select * from S3Object where cast(number as int) < 1"); - -// CSVInput csvInput; -// csvInput.SetFileHeaderInfo(FileHeaderInfo::USE); -// InputSerialization inputSerialization; -// inputSerialization.SetCSV(csvInput); -// selectObjectContentRequest.SetInputSerialization(inputSerialization); - -// CSVOutput csvOutput; -// OutputSerialization outputSerialization; -// outputSerialization.SetCSV(csvOutput); -// selectObjectContentRequest.SetOutputSerialization(outputSerialization); - -// bool isErrorEventReceived = false; - -// SelectObjectContentHandler handler; -// handler.SetOnErrorCallback([&](const AWSError& s3Error) -// { -// isErrorEventReceived = true; -// ASSERT_EQ(CoreErrors::UNKNOWN, static_cast(s3Error.GetErrorType())); -// ASSERT_STREQ("CastFailed", s3Error.GetExceptionName().c_str()); -// }); - -// selectObjectContentRequest.SetEventStreamHandler(handler); - -// Client->SelectObjectContent(selectObjectContentRequest); - -// ASSERT_TRUE(isErrorEventReceived); -// } - TEST_F(BucketAndObjectOperationTest, TestNullBody) { const Aws::String fullBucketName = CalculateBucketName(BASE_PUT_OBJECTS_BUCKET_NAME.c_str()); From 8c8c776a3f5011f11e227f8a43a6b492978418b1 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Mon, 9 Jun 2025 13:24:49 -0400 Subject: [PATCH 03/77] fix again --- .../BucketAndObjectOperationTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp b/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp index a5d91fd27e9..37edc9a916d 100644 --- a/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp +++ b/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp @@ -83,7 +83,7 @@ namespace static const char* TEST_OBJ_KEY = "TestObjectKey"; static const char* TEST_NOT_MODIFIED_OBJ_KEY = "TestNotModifiedObjectKey"; static const char* TEST_DNS_UNFRIENDLY_OBJ_KEY = "WhySoHostile"; - static const char* TEST_EVENT_STREAM_OBJ_KEY = "TestEventStream.csv"; + // static const char* TEST_EVENT_STREAM_OBJ_KEY = "TestEventStream.csv"; //windows won't let you hard code unicode strings in a source file and assign them to a char*. Every other compiler does and I need to test this. //to get around this, this string is url encoded version of "TestUnicode中国Key". At test time, we'll convert it to the unicode string static const char* URLENCODED_UNICODE_KEY = "TestUnicode%E4%B8%AD%E5%9B%BDKey"; From 457dba82cfbb1db3f83d94503369e611ad2780ce Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Mon, 9 Jun 2025 15:08:04 -0400 Subject: [PATCH 04/77] remove tests from tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.c --- .../BucketAndObjectOperationTest.cpp | 330 ------------------ 1 file changed, 330 deletions(-) diff --git a/tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp b/tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp index 1f13967b7fb..1031f97915f 100644 --- a/tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp +++ b/tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp @@ -1592,336 +1592,6 @@ namespace AWS_ASSERT_SUCCESS(deleteObjectOutcome); } - TEST_F(BucketAndObjectOperationTest, TestObjectOperationWithEventStream) - { - const Aws::String fullBucketName = CalculateBucketName(BASE_EVENT_STREAM_TEST_BUCKET_NAME.c_str()); - SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName); - CreateBucketRequest createBucketRequest; - createBucketRequest.SetBucket(fullBucketName); - createBucketRequest.SetACL(BucketCannedACL::private_); - CreateBucketOutcome createBucketOutcome = CreateBucket(createBucketRequest); - AWS_ASSERT_SUCCESS(createBucketOutcome); - ASSERT_TRUE(WaitForBucketToPropagate(fullBucketName, Client)); - TagTestBucket(fullBucketName, Client); - - PutObjectRequest putObjectRequest; - putObjectRequest.SetBucket(fullBucketName); - - std::shared_ptr objectStream = Aws::MakeShared(ALLOCATION_TAG); - *objectStream << "Name,Number\nAlice,1\nBob,2"; - Aws::String firstColumn = "Name\nAlice\nBob\n"; - objectStream->flush(); - putObjectRequest.SetBody(objectStream); - putObjectRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); - auto objectSize = putObjectRequest.GetBody()->tellp(); - putObjectRequest.SetContentLength(static_cast(objectSize)); - putObjectRequest.SetContentMD5(HashingUtils::Base64Encode(HashingUtils::CalculateMD5(*putObjectRequest.GetBody()))); - putObjectRequest.SetContentType("text/csv"); - - PutObjectOutcome putObjectOutcome = Client->PutObject(putObjectRequest); - AWS_ASSERT_SUCCESS(putObjectOutcome); - - ASSERT_TRUE(WaitForObjectToPropagate(fullBucketName, TEST_EVENT_STREAM_OBJ_KEY)); - - SelectObjectContentRequest selectObjectContentRequest; - selectObjectContentRequest.SetBucket(fullBucketName); - selectObjectContentRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); - - selectObjectContentRequest.SetExpressionType(ExpressionType::SQL); - - selectObjectContentRequest.SetExpression("select s._1 from S3Object s"); - - CSVInput csvInput; - csvInput.SetFileHeaderInfo(FileHeaderInfo::NONE); - InputSerialization inputSerialization; - inputSerialization.SetCSV(csvInput); - selectObjectContentRequest.SetInputSerialization(inputSerialization); - - CSVOutput csvOutput; - OutputSerialization outputSerialization; - outputSerialization.SetCSV(csvOutput); - selectObjectContentRequest.SetOutputSerialization(outputSerialization); - - bool isRecordsEventReceived = false; - bool isStatsEventReceived = false; - - SelectObjectContentHandler handler; - handler.SetRecordsEventCallback([&](const RecordsEvent& recordsEvent) - { - isRecordsEventReceived = true; - auto recordsVector = recordsEvent.GetPayload(); - Aws::String records(recordsVector.begin(), recordsVector.end()); - ASSERT_STREQ(firstColumn.c_str(), records.c_str()); - }); - handler.SetStatsEventCallback([&](const StatsEvent& statsEvent) - { - isStatsEventReceived = true; - ASSERT_EQ(static_cast(objectSize), statsEvent.GetDetails().GetBytesScanned()); - ASSERT_EQ(static_cast(objectSize), statsEvent.GetDetails().GetBytesProcessed()); - ASSERT_EQ(static_cast(firstColumn.size()), statsEvent.GetDetails().GetBytesReturned()); - }); - - selectObjectContentRequest.SetEventStreamHandler(handler); - - auto selectObjectContentOutcome = Client->SelectObjectContent(selectObjectContentRequest); - AWS_ASSERT_SUCCESS(selectObjectContentOutcome); - ASSERT_TRUE(isRecordsEventReceived); - ASSERT_TRUE(isStatsEventReceived); - } - - // This test is to test failed event stream request will not cause crash during retry. - TEST_F(BucketAndObjectOperationTest, TestSelectObjectOperationWithEventStreamFailWithRetry) - { - const Aws::String fullBucketName = CalculateBucketName(BASE_EVENT_STREAM_TEST_BUCKET_NAME.c_str()); - SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName); - CreateBucketRequest createBucketRequest; - createBucketRequest.SetBucket(fullBucketName); - createBucketRequest.SetACL(BucketCannedACL::private_); - CreateBucketOutcome createBucketOutcome = CreateBucket(createBucketRequest); - AWS_ASSERT_SUCCESS(createBucketOutcome); - ASSERT_TRUE(WaitForBucketToPropagate(fullBucketName, Client)); - TagTestBucket(fullBucketName, Client); - - PutObjectRequest putObjectRequest; - putObjectRequest.SetBucket(fullBucketName); - - std::shared_ptr objectStream = Aws::MakeShared(ALLOCATION_TAG); - *objectStream << "Name,Number\nAlice,1\nBob,2"; - Aws::String firstColumn = "Name\nAlice\nBob\n"; - objectStream->flush(); - putObjectRequest.SetBody(objectStream); - putObjectRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); - auto objectSize = putObjectRequest.GetBody()->tellp(); - putObjectRequest.SetContentLength(static_cast(objectSize)); - putObjectRequest.SetContentMD5(HashingUtils::Base64Encode(HashingUtils::CalculateMD5(*putObjectRequest.GetBody()))); - putObjectRequest.SetContentType("text/csv"); - - PutObjectOutcome putObjectOutcome = Client->PutObject(putObjectRequest); - AWS_ASSERT_SUCCESS(putObjectOutcome); - - ASSERT_TRUE(WaitForObjectToPropagate(fullBucketName, TEST_EVENT_STREAM_OBJ_KEY)); - - SelectObjectContentRequest selectObjectContentRequest; - selectObjectContentRequest.SetBucket(fullBucketName); - selectObjectContentRequest.SetKey("ANonExistenceKey"); - - selectObjectContentRequest.SetExpressionType(ExpressionType::SQL); - - selectObjectContentRequest.SetExpression("select s._1 from S3Object s"); - - CSVInput csvInput; - csvInput.SetFileHeaderInfo(FileHeaderInfo::NONE); - InputSerialization inputSerialization; - inputSerialization.SetCSV(csvInput); - selectObjectContentRequest.SetInputSerialization(inputSerialization); - - CSVOutput csvOutput; - OutputSerialization outputSerialization; - outputSerialization.SetCSV(csvOutput); - selectObjectContentRequest.SetOutputSerialization(outputSerialization); - - bool isRecordsEventReceived = false; - bool isStatsEventReceived = false; - - SelectObjectContentHandler handler; - handler.SetRecordsEventCallback([&](const RecordsEvent& recordsEvent) - { - isRecordsEventReceived = true; - auto recordsVector = recordsEvent.GetPayload(); - Aws::String records(recordsVector.begin(), recordsVector.end()); - ASSERT_STREQ(firstColumn.c_str(), records.c_str()); - }); - handler.SetStatsEventCallback([&](const StatsEvent& statsEvent) - { - isStatsEventReceived = true; - ASSERT_EQ(static_cast(objectSize), statsEvent.GetDetails().GetBytesScanned()); - ASSERT_EQ(static_cast(objectSize), statsEvent.GetDetails().GetBytesProcessed()); - ASSERT_EQ(static_cast(firstColumn.size()), statsEvent.GetDetails().GetBytesReturned()); - }); - - selectObjectContentRequest.SetEventStreamHandler(handler); - - auto selectObjectContentOutcome = retryClient->SelectObjectContent(selectObjectContentRequest); - ASSERT_FALSE(selectObjectContentOutcome.IsSuccess()); - } - - TEST_F(BucketAndObjectOperationTest, TestEventStreamWithLargeFile) - { - const Aws::String fullBucketName = CalculateBucketName(BASE_EVENT_STREAM_LARGE_FILE_TEST_BUCKET_NAME.c_str()); - SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName); - CreateBucketRequest createBucketRequest; - createBucketRequest.SetBucket(fullBucketName); - createBucketRequest.SetACL(BucketCannedACL::private_); - CreateBucketOutcome createBucketOutcome = CreateBucket(createBucketRequest); - AWS_ASSERT_SUCCESS(createBucketOutcome); - ASSERT_TRUE(WaitForBucketToPropagate(fullBucketName, Client)); - TagTestBucket(fullBucketName, Client); - - PutObjectRequest putObjectRequest; - putObjectRequest.SetBucket(fullBucketName); - - std::shared_ptr objectStream = Aws::MakeShared(ALLOCATION_TAG); - *objectStream << "Name,Number\n"; - for (int i = 0; i < 1000000; i++) - { - *objectStream << "foo,0\n"; - } - objectStream->flush(); - putObjectRequest.SetBody(objectStream); - putObjectRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); - auto objectSize = putObjectRequest.GetBody()->tellp(); - putObjectRequest.SetContentLength(static_cast(objectSize)); - putObjectRequest.SetContentMD5(HashingUtils::Base64Encode(HashingUtils::CalculateMD5(*putObjectRequest.GetBody()))); - putObjectRequest.SetContentType("text/csv"); - - PutObjectOutcome putObjectOutcome = Client->PutObject(putObjectRequest); - AWS_ASSERT_SUCCESS(putObjectOutcome); - - ASSERT_TRUE(WaitForObjectToPropagate(fullBucketName, TEST_EVENT_STREAM_OBJ_KEY)); - - SelectObjectContentRequest selectObjectContentRequest; - selectObjectContentRequest.SetBucket(fullBucketName); - selectObjectContentRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); - - selectObjectContentRequest.SetExpressionType(ExpressionType::SQL); - - selectObjectContentRequest.SetExpression("select * from S3Object where cast(number as int) < 1"); - - CSVInput csvInput; - csvInput.SetFileHeaderInfo(FileHeaderInfo::USE); - InputSerialization inputSerialization; - inputSerialization.SetCSV(csvInput); - selectObjectContentRequest.SetInputSerialization(inputSerialization); - - CSVOutput csvOutput; - OutputSerialization outputSerialization; - outputSerialization.SetCSV(csvOutput); - selectObjectContentRequest.SetOutputSerialization(outputSerialization); - - size_t recordsTotalLength = 0; - bool isStatsEventReceived = false; - - SelectObjectContentHandler handler; - handler.SetRecordsEventCallback([&](const RecordsEvent& recordsEvent) - { - recordsTotalLength += recordsEvent.GetPayload().size(); - }); - handler.SetStatsEventCallback([&](const StatsEvent& statsEvent) - { - isStatsEventReceived = true; - ASSERT_EQ(12ll/*length of the 1st row*/ + 6/*length of all the other row*/ * 1000000ll, statsEvent.GetDetails().GetBytesScanned()); - ASSERT_EQ(6000012ll, statsEvent.GetDetails().GetBytesProcessed()); - ASSERT_EQ(6000000ll, statsEvent.GetDetails().GetBytesReturned()); - }); - - selectObjectContentRequest.SetEventStreamHandler(handler); - - auto selectObjectContentOutcome = Client->SelectObjectContent(selectObjectContentRequest); - ASSERT_EQ(6000000u, recordsTotalLength); - ASSERT_TRUE(isStatsEventReceived); - } - - TEST_F(BucketAndObjectOperationTest, TestErrorsInXml) - { - SelectObjectContentRequest selectObjectContentRequest; - selectObjectContentRequest.SetBucket("adskflaklfakl"); - selectObjectContentRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); - - selectObjectContentRequest.SetExpressionType(ExpressionType::SQL); - - selectObjectContentRequest.SetExpression("select s._1 from S3Object s"); - - CSVInput csvInput; - csvInput.SetFileHeaderInfo(FileHeaderInfo::USE); - InputSerialization inputSerialization; - inputSerialization.SetCSV(csvInput); - selectObjectContentRequest.SetInputSerialization(inputSerialization); - - CSVOutput csvOutput; - OutputSerialization outputSerialization; - outputSerialization.SetCSV(csvOutput); - selectObjectContentRequest.SetOutputSerialization(outputSerialization); - - auto selectObjectContentOutcome = Client->SelectObjectContent(selectObjectContentRequest); - ASSERT_FALSE(selectObjectContentOutcome.IsSuccess()); -#if ENABLE_CURL_CLIENT - ASSERT_FALSE(selectObjectContentOutcome.GetError().GetRemoteHostIpAddress().empty()); -#endif - ASSERT_FALSE(selectObjectContentOutcome.GetError().GetRequestId().empty()); - ASSERT_EQ(S3Errors::NO_SUCH_BUCKET, selectObjectContentOutcome.GetError().GetErrorType()); - } - - TEST_F(BucketAndObjectOperationTest, TestErrorsInEventStream) - { - const Aws::String fullBucketName = CalculateBucketName(BASE_EVENT_STREAM_ERRORS_IN_EVENT_TEST_BUCKET_NAME.c_str()); - SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName); - CreateBucketRequest createBucketRequest; - createBucketRequest.SetBucket(fullBucketName); - createBucketRequest.SetACL(BucketCannedACL::private_); - CreateBucketOutcome createBucketOutcome = CreateBucket(createBucketRequest); - AWS_ASSERT_SUCCESS(createBucketOutcome); - ASSERT_TRUE(WaitForBucketToPropagate(fullBucketName, Client)); - TagTestBucket(fullBucketName, Client); - - PutObjectRequest putObjectRequest; - putObjectRequest.SetBucket(fullBucketName); - - std::shared_ptr objectStream = Aws::MakeShared(ALLOCATION_TAG); - *objectStream << "Name,Number\n"; - for (int i = 0; i < 1000000; i++) - { - *objectStream << "foo,0\n"; - } - *objectStream << "bar,NAN"; - objectStream->flush(); - putObjectRequest.SetBody(objectStream); - putObjectRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); - auto objectSize = putObjectRequest.GetBody()->tellp(); - putObjectRequest.SetContentLength(static_cast(objectSize)); - putObjectRequest.SetContentMD5(HashingUtils::Base64Encode(HashingUtils::CalculateMD5(*putObjectRequest.GetBody()))); - putObjectRequest.SetContentType("text/csv"); - - PutObjectOutcome putObjectOutcome = Client->PutObject(putObjectRequest); - AWS_ASSERT_SUCCESS(putObjectOutcome); - - ASSERT_TRUE(WaitForObjectToPropagate(fullBucketName, TEST_EVENT_STREAM_OBJ_KEY)); - - SelectObjectContentRequest selectObjectContentRequest; - selectObjectContentRequest.SetBucket(fullBucketName); - selectObjectContentRequest.SetKey(TEST_EVENT_STREAM_OBJ_KEY); - - selectObjectContentRequest.SetExpressionType(ExpressionType::SQL); - - selectObjectContentRequest.SetExpression("select * from S3Object where cast(number as int) < 1"); - - CSVInput csvInput; - csvInput.SetFileHeaderInfo(FileHeaderInfo::USE); - InputSerialization inputSerialization; - inputSerialization.SetCSV(csvInput); - selectObjectContentRequest.SetInputSerialization(inputSerialization); - - CSVOutput csvOutput; - OutputSerialization outputSerialization; - outputSerialization.SetCSV(csvOutput); - selectObjectContentRequest.SetOutputSerialization(outputSerialization); - - bool isErrorEventReceived = false; - - SelectObjectContentHandler handler; - handler.SetOnErrorCallback([&](const AWSError& s3Error) - { - isErrorEventReceived = true; - ASSERT_EQ(CoreErrors::UNKNOWN, static_cast(s3Error.GetErrorType())); - ASSERT_STREQ("CastFailed", s3Error.GetExceptionName().c_str()); - }); - - selectObjectContentRequest.SetEventStreamHandler(handler); - - Client->SelectObjectContent(selectObjectContentRequest); - - ASSERT_TRUE(isErrorEventReceived); - } - TEST_F(BucketAndObjectOperationTest, TestFlexibleChecksums) { const Aws::String fullBucketName = CalculateBucketName(BASE_CHECKSUMS_BUCKET_NAME.c_str()); From e667c8cdd705a9140596fb7713b6f6be8ae0ad58 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Mon, 9 Jun 2025 15:46:44 -0400 Subject: [PATCH 05/77] fix again --- .../BucketAndObjectOperationTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp b/tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp index 1031f97915f..e1a07c640ba 100644 --- a/tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp +++ b/tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp @@ -96,7 +96,7 @@ namespace static const char* TEST_NOT_MODIFIED_OBJ_KEY = "TestNotModifiedObjectKey"; static const char* TEST_OBJECT_LOCK_OBJ_KEY = "TestObjectLock"; static const char* TEST_DNS_UNFRIENDLY_OBJ_KEY = "WhySoHostile"; - static const char* TEST_EVENT_STREAM_OBJ_KEY = "TestEventStream.csv"; + // static const char* TEST_EVENT_STREAM_OBJ_KEY = "TestEventStream.csv"; //windows won't let you hard code unicode strings in a source file and assign them to a char*. Every other compiler does and I need to test this. //to get around this, this string is url encoded version of "TestUnicode中国Key". At test time, we'll convert it to the unicode string static const char* URLENCODED_UNICODE_KEY = "TestUnicode%E4%B8%AD%E5%9B%BDKey"; From 177c3f6f3d323a1926d177b3733d4ff63bbf5345 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Mon, 9 Jun 2025 17:19:25 -0400 Subject: [PATCH 06/77] performance test draft prototype --- CMakeLists.txt | 7 + tests/performance_tests/CMakeLists.txt | 55 +++++++ .../service/JsonReportingMetrics.cpp | 154 ++++++++++++++++++ .../service/JsonReportingMetrics.h | 69 ++++++++ .../performance_tests/service/S3GetObject.cpp | 79 +++++++++ .../performance_tests/service/S3PutObject.cpp | 72 ++++++++ 6 files changed, 436 insertions(+) create mode 100644 tests/performance_tests/CMakeLists.txt create mode 100644 tests/performance_tests/service/JsonReportingMetrics.cpp create mode 100644 tests/performance_tests/service/JsonReportingMetrics.h create mode 100644 tests/performance_tests/service/S3GetObject.cpp create mode 100644 tests/performance_tests/service/S3PutObject.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 164f1ad479e..b1baeada078 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -341,6 +341,13 @@ if (LEGACY_BUILD) add_sdks() include(tests) + #Performance tests (under tests/performance_tests) + option(BUILD_PERFORMANCE_TESTS "Build AWS C++ performance tests" OFF) + if(BUILD_PERFORMANCE_TESTS) + add_subdirectory(tests/performance_tests) + endif() + + # for user friendly cmake usage include(setup_cmake_find_module) diff --git a/tests/performance_tests/CMakeLists.txt b/tests/performance_tests/CMakeLists.txt new file mode 100644 index 00000000000..1750a5bd347 --- /dev/null +++ b/tests/performance_tests/CMakeLists.txt @@ -0,0 +1,55 @@ +cmake_minimum_required(VERSION 3.13) + +include(FetchContent) + +FetchContent_Declare( + nlohmann_json + URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz +) +FetchContent_MakeAvailable(nlohmann_json) + +add_project(performance_tests + "A suite of simple AWS C++ SDK performance tests" + aws-cpp-sdk-core + aws-cpp-sdk-s3 +) + +add_library(json_metrics STATIC + service/JsonReportingMetrics.cpp + service/JsonReportingMetrics.h +) + +target_include_directories(json_metrics PUBLIC + "${PROJECT_SOURCE_DIR}/aws-cpp-sdk-core/include" +) + +target_include_directories(json_metrics PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/service) +target_link_libraries(json_metrics + PUBLIC + aws-cpp-sdk-core + nlohmann_json::nlohmann_json +) + +# PutObject Performance Test +add_executable(s3_put_object_perf + service/S3PutObject.cpp +) +set_compiler_flags(s3_put_object_perf) +set_compiler_warnings(s3_put_object_perf) +target_link_libraries(s3_put_object_perf + PRIVATE + ${PROJECT_LIBS} + json_metrics +) + +# GetObject Performance Test +add_executable(s3_get_object_perf + service/S3GetObject.cpp +) +set_compiler_flags(s3_get_object_perf) +set_compiler_warnings(s3_get_object_perf) +target_link_libraries(s3_get_object_perf + PRIVATE + ${PROJECT_LIBS} + json_metrics +) \ No newline at end of file diff --git a/tests/performance_tests/service/JsonReportingMetrics.cpp b/tests/performance_tests/service/JsonReportingMetrics.cpp new file mode 100644 index 00000000000..b5901dc47d5 --- /dev/null +++ b/tests/performance_tests/service/JsonReportingMetrics.cpp @@ -0,0 +1,154 @@ +#include "JsonReportingMetrics.h" +#include +#include +#include +#include + +JsonReportingMetrics::JsonReportingMetrics() {} + +JsonReportingMetrics::~JsonReportingMetrics() { + DumpJson(); +} + +JsonReportingMetricsFactory::~JsonReportingMetricsFactory() {} + +// And the factory method +Aws::UniquePtr JsonReportingMetricsFactory::CreateMonitoringInstance() const { + return Aws::MakeUnique("JsonReportingMetrics"); +} + +void JsonReportingMetrics::AddMetric(const Aws::String& serviceName, const Aws::String& requestName, + const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, bool success) const { + std::lock_guard lock(m_mutex); + + double durationMs = 0.0; + Aws::String latencyKey = Aws::Monitoring::GetHttpClientMetricNameByType(Aws::Monitoring::HttpClientMetricsType::RequestLatency); + + auto it = metricsFromCore.httpClientMetrics.find(latencyKey); + if (it != metricsFromCore.httpClientMetrics.end()) { + durationMs = static_cast(it->second); + } + + RequestMetric metric; + metric.name = Aws::Utils::StringUtils::ToLower(serviceName.c_str()) + + Aws::String(".") + + Aws::Utils::StringUtils::ToLower(requestName.c_str()); + metric.description = Aws::String("Time to complete ") + metric.name + Aws::String(" operation"); + metric.unit = "Milliseconds"; + metric.date = Aws::Utils::DateTime::CurrentTimeMillis() / 1000; + metric.measurements.push_back(durationMs); + + metric.dimensions.push_back(std::make_pair(Aws::String("Service"), serviceName)); + metric.dimensions.push_back(std::make_pair(Aws::String("Operation"), requestName)); + metric.publishToCloudWatch = true; + + m_metrics.push_back(metric); +} + +void JsonReportingMetrics::AggregateMetrics() const { + // Create finalized metrics from the aggregated data + for (const auto& pair : m_aggregatedMetrics) { + RequestMetric metric; + metric.name = pair.first; + metric.description = Aws::String("Time to complete ") + pair.first + Aws::String(" operation"); + metric.unit = "Milliseconds"; + metric.date = Aws::Utils::DateTime::CurrentTimeMillis() / 1000; + metric.measurements = pair.second; + metric.publishToCloudWatch = true; + + // Add dimensions (e.g., AWS service name) + size_t dotPos = pair.first.find('.'); + if (dotPos != Aws::String::npos) { + Aws::String service = pair.first.substr(0, dotPos); + metric.dimensions.push_back(std::make_pair(Aws::String("Service"), service)); + } + + m_metrics.push_back(metric); + } +} + +// Interface Overrides +void* JsonReportingMetrics::OnRequestStarted(const Aws::String&, const Aws::String&, + const std::shared_ptr&) const { + return nullptr; +} + +void JsonReportingMetrics::OnRequestSucceeded(const Aws::String& serviceName, const Aws::String& requestName, + const std::shared_ptr&, + const Aws::Client::HttpResponseOutcome& outcome, + const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void*) const { + AddMetric(serviceName, requestName, metricsFromCore, outcome.IsSuccess()); +} + +void JsonReportingMetrics::OnRequestFailed(const Aws::String& serviceName, const Aws::String& requestName, + const std::shared_ptr&, + const Aws::Client::HttpResponseOutcome& outcome, + const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void*) const { + AddMetric(serviceName, requestName, metricsFromCore, outcome.IsSuccess()); +} + +void JsonReportingMetrics::OnFinish(const Aws::String&, const Aws::String&, const std::shared_ptr&, + void*) const { +} + +void JsonReportingMetrics::OnRequestRetry(const Aws::String&, const Aws::String&, const std::shared_ptr&, + void*) const { +} + +void JsonReportingMetrics::DumpJson() const { + std::lock_guard lock(m_mutex); + + if (m_metrics.empty()) { + return; + } + + Aws::Utils::Json::JsonValue root; + + // Add required top-level fields + root.WithString("productId", "AWS SDK for C++"); + root.WithString("sdkVersion", "1.0.0"); + root.WithString("commitId", "unknown"); // Consider getting this from CI/CD env variable + + Aws::Utils::Array results(m_metrics.size()); + + for (size_t i = 0; i < m_metrics.size(); ++i) { + Aws::Utils::Json::JsonValue metric; + metric.WithString("name", m_metrics[i].name); + metric.WithString("description", m_metrics[i].description); + metric.WithString("unit", m_metrics[i].unit); + metric.WithInt64("date", m_metrics[i].date); + + // Add dimensions if present + if (!m_metrics[i].dimensions.empty()) { + Aws::Utils::Array dimensionsArray(m_metrics[i].dimensions.size()); + for (size_t j = 0; j < m_metrics[i].dimensions.size(); ++j) { + Aws::Utils::Json::JsonValue dimension; + dimension.WithString("name", m_metrics[i].dimensions[j].first); + dimension.WithString("value", m_metrics[i].dimensions[j].second); + dimensionsArray[j] = std::move(dimension); + } + metric.WithArray("dimensions", std::move(dimensionsArray)); + } + + // Create a JSON array for measurements + Aws::Utils::Array measurementsArray(m_metrics[i].measurements.size()); + for (size_t j = 0; j < m_metrics[i].measurements.size(); ++j) { + Aws::Utils::Json::JsonValue measurementValue; + measurementValue.AsDouble(m_metrics[i].measurements[j]); + measurementsArray[j] = std::move(measurementValue); + } + metric.WithArray("measurements", std::move(measurementsArray)); + + results[i] = std::move(metric); + } + root.WithArray("results", std::move(results)); + + // Write to stdout so the performance test runner can capture it + std::cout << root.View().WriteReadable() << std::endl; + + // Save to file + std::ofstream outFile("perf-results.json"); + if (outFile.is_open()) { + outFile << root.View().WriteReadable(); + } +} \ No newline at end of file diff --git a/tests/performance_tests/service/JsonReportingMetrics.h b/tests/performance_tests/service/JsonReportingMetrics.h new file mode 100644 index 00000000000..dfe427daa37 --- /dev/null +++ b/tests/performance_tests/service/JsonReportingMetrics.h @@ -0,0 +1,69 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +struct RequestMetric { + Aws::String name; + Aws::String description; + Aws::String unit; + int64_t date; + Aws::Vector measurements; + Aws::Vector> dimensions; + bool publishToCloudWatch; +}; + +class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { +public: + JsonReportingMetrics(); + ~JsonReportingMetrics() override; + + void* OnRequestStarted(const Aws::String& serviceName, const Aws::String& requestName, + const std::shared_ptr& request) const override; + + void OnRequestSucceeded(const Aws::String& serviceName, const Aws::String& requestName, + const std::shared_ptr& request, const Aws::Client::HttpResponseOutcome& outcome, + const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void* context) const override; + + void OnRequestFailed(const Aws::String& serviceName, const Aws::String& requestName, + const std::shared_ptr& request, const Aws::Client::HttpResponseOutcome& outcome, + const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void* context) const override; + + void OnRequestRetry(const Aws::String& serviceName, const Aws::String& requestName, + const std::shared_ptr& request, void* context) const override; + + void OnFinish(const Aws::String& serviceName, const Aws::String& requestName, + const std::shared_ptr& request, void* context) const override; + +private: + void AddMetric(const Aws::String& serviceName, const Aws::String& requestName, + const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, bool success) const; + void DumpJson() const; + + void AggregateMetrics() const; + + mutable std::mutex m_mutex; + mutable Aws::Vector m_metrics; + mutable Aws::Map> m_aggregatedMetrics; +}; + +class JsonReportingMetricsFactory : public Aws::Monitoring::MonitoringFactory { +public: + JsonReportingMetricsFactory() {} + ~JsonReportingMetricsFactory() override; + Aws::UniquePtr CreateMonitoringInstance() const override; +}; \ No newline at end of file diff --git a/tests/performance_tests/service/S3GetObject.cpp b/tests/performance_tests/service/S3GetObject.cpp new file mode 100644 index 00000000000..4400afc38c7 --- /dev/null +++ b/tests/performance_tests/service/S3GetObject.cpp @@ -0,0 +1,79 @@ +/** + * Simple perf test: create bucket -> put 64 KiB -> get it once -> cleanup + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "JsonReportingMetrics.h" + +int main(int argc, char** argv) { + Aws::SDKOptions options; + + options.monitoringOptions.customizedMonitoringFactory_create_fn.push_back( + []() { return Aws::MakeUnique("jsonFactory"); }); + + Aws::InitAPI(options); + { + Aws::Client::ClientConfiguration cfg; + if (argc > 1) cfg.region = argv[1]; + + cfg.enableHttpClientTrace = true; + + Aws::S3::S3Client s3(cfg); + + // 1) bucket name + Aws::String raw = static_cast(Aws::Utils::UUID::RandomUUID()); + Aws::String id = Aws::Utils::StringUtils::ToLower(raw.c_str()).substr(10); + Aws::String bucket = Aws::String("get-bucket-benchmark-") + id; + + // 2) create bucket + Aws::S3::Model::CreateBucketRequest cbr; + cbr.WithBucket(bucket); + if (!s3.CreateBucket(cbr).IsSuccess()) { + std::cerr << "[ERROR] CreateBucket\n"; + return 1; + } + + // 3) put a 64KiB test object + std::string payload(64 * 1024, 'x'); + auto stream = Aws::MakeShared("PerfStream"); + *stream << payload; + + Aws::S3::Model::PutObjectRequest por; + por.WithBucket(bucket).WithKey("test-object").SetBody(stream); + if (!s3.PutObject(por).IsSuccess()) { + std::cerr << "[ERROR] PutObject\n"; + return 1; + } + std::cout << "Uploaded 64 KiB to " << bucket << "/test-object\n"; + + // 4) get object + Aws::S3::Model::GetObjectRequest gor; + gor.WithBucket(bucket).WithKey("test-object"); + + auto goOutcome = s3.GetObject(gor); + if (!goOutcome.IsSuccess()) { + std::cerr << "[ERROR] GetObject: " << goOutcome.GetError().GetMessage() << "\n"; + return 1; + } + std::cout << "Downloaded " << goOutcome.GetResult().GetContentLength() << " bytes\n"; + + // 5) cleanup + s3.DeleteObject(Aws::S3::Model::DeleteObjectRequest().WithBucket(bucket).WithKey("test-object")); + s3.DeleteBucket(Aws::S3::Model::DeleteBucketRequest().WithBucket(bucket)); + std::cout << "Cleaned up\n"; + } + Aws::ShutdownAPI(options); + return 0; +} \ No newline at end of file diff --git a/tests/performance_tests/service/S3PutObject.cpp b/tests/performance_tests/service/S3PutObject.cpp new file mode 100644 index 00000000000..f2fb73562bf --- /dev/null +++ b/tests/performance_tests/service/S3PutObject.cpp @@ -0,0 +1,72 @@ +/** + * Simple perf test: create bucket -> put 64 KiB object -> delete object + bucket + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "JsonReportingMetrics.h" + +int main(int argc, char** argv) { + Aws::SDKOptions options; + + options.monitoringOptions.customizedMonitoringFactory_create_fn.push_back( + []() { return Aws::MakeUnique("jsonFactory"); }); + + Aws::InitAPI(options); + { + Aws::Client::ClientConfiguration cfg; + if (argc > 1) cfg.region = argv[1]; + + cfg.enableHttpClientTrace = true; + + Aws::S3::S3Client s3(cfg); + + // 1) bucket name + Aws::String raw = static_cast(Aws::Utils::UUID::RandomUUID()); + Aws::String id = Aws::Utils::StringUtils::ToLower(raw.c_str()).substr(10); + Aws::String bucket = Aws::String("put-bucket-benchmark-") + id; + + // 2) create bucket + Aws::S3::Model::CreateBucketRequest cbr; + cbr.WithBucket(bucket); + auto cbOutcome = s3.CreateBucket(cbr); + if (!cbOutcome.IsSuccess()) { + std::cerr << "[ERROR] CreateBucket: " << cbOutcome.GetError().GetMessage() << "\n"; + return 1; + } + + // 3) put a 64KiB test object + std::string payload(64 * 1024, 'x'); + auto stream = Aws::MakeShared("PerfStream"); + *stream << payload; + + // 4) PutObject + Aws::S3::Model::PutObjectRequest por; + por.WithBucket(bucket).WithKey("test-object").SetBody(stream); + + auto poOutcome = s3.PutObject(por); + if (!poOutcome.IsSuccess()) { + std::cerr << "[ERROR] PutObject: " << poOutcome.GetError().GetMessage() << "\n"; + return 1; + } + std::cout << "Uploaded 64 KiB to " << bucket << "/test-object\n"; + + // 5) cleanup + s3.DeleteObject(Aws::S3::Model::DeleteObjectRequest().WithBucket(bucket).WithKey("test-object")); + s3.DeleteBucket(Aws::S3::Model::DeleteBucketRequest().WithBucket(bucket)); + std::cout << "Cleaned up\n"; + } + Aws::ShutdownAPI(options); + return 0; +} \ No newline at end of file From 92e8c16eddacfb916b3e17f26e8d99ff322169a9 Mon Sep 17 00:00:00 2001 From: Yuxuan Date: Mon, 9 Jun 2025 23:56:52 -0400 Subject: [PATCH 07/77] add more dimensions for s3 performance test, and reorganize the folder structure --- tests/performance_tests/CMakeLists.txt | 53 +++--- .../reporting/JsonReportingMetrics.cpp | 141 ++++++++++++++++ .../reporting/JsonReportingMetrics.h | 81 +++++++++ .../s3/S3PerformanceTest.cpp | 139 ++++++++++++++++ .../service/JsonReportingMetrics.cpp | 154 ------------------ .../service/JsonReportingMetrics.h | 69 -------- .../performance_tests/service/S3GetObject.cpp | 79 --------- .../performance_tests/service/S3PutObject.cpp | 72 -------- 8 files changed, 382 insertions(+), 406 deletions(-) create mode 100644 tests/performance_tests/reporting/JsonReportingMetrics.cpp create mode 100644 tests/performance_tests/reporting/JsonReportingMetrics.h create mode 100644 tests/performance_tests/s3/S3PerformanceTest.cpp delete mode 100644 tests/performance_tests/service/JsonReportingMetrics.cpp delete mode 100644 tests/performance_tests/service/JsonReportingMetrics.h delete mode 100644 tests/performance_tests/service/S3GetObject.cpp delete mode 100644 tests/performance_tests/service/S3PutObject.cpp diff --git a/tests/performance_tests/CMakeLists.txt b/tests/performance_tests/CMakeLists.txt index 1750a5bd347..4a7eef69319 100644 --- a/tests/performance_tests/CMakeLists.txt +++ b/tests/performance_tests/CMakeLists.txt @@ -3,53 +3,42 @@ cmake_minimum_required(VERSION 3.13) include(FetchContent) FetchContent_Declare( - nlohmann_json - URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz + nlohmann_json + URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz ) FetchContent_MakeAvailable(nlohmann_json) add_project(performance_tests - "A suite of simple AWS C++ SDK performance tests" - aws-cpp-sdk-core - aws-cpp-sdk-s3 + "A suite of simple AWS C++ SDK performance tests" + aws-cpp-sdk-core + aws-cpp-sdk-s3 ) add_library(json_metrics STATIC - service/JsonReportingMetrics.cpp - service/JsonReportingMetrics.h + reporting/JsonReportingMetrics.cpp + reporting/JsonReportingMetrics.h ) target_include_directories(json_metrics PUBLIC - "${PROJECT_SOURCE_DIR}/aws-cpp-sdk-core/include" + "${CMAKE_CURRENT_SOURCE_DIR}/reporting" ) -target_include_directories(json_metrics PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/service) target_link_libraries(json_metrics - PUBLIC - aws-cpp-sdk-core - nlohmann_json::nlohmann_json + PUBLIC + aws-cpp-sdk-core + nlohmann_json::nlohmann_json ) -# PutObject Performance Test -add_executable(s3_put_object_perf - service/S3PutObject.cpp -) -set_compiler_flags(s3_put_object_perf) -set_compiler_warnings(s3_put_object_perf) -target_link_libraries(s3_put_object_perf - PRIVATE - ${PROJECT_LIBS} - json_metrics +# Define the S3 performance test executable +add_executable(s3_performance_test + s3/S3PerformanceTest.cpp ) -# GetObject Performance Test -add_executable(s3_get_object_perf - service/S3GetObject.cpp -) -set_compiler_flags(s3_get_object_perf) -set_compiler_warnings(s3_get_object_perf) -target_link_libraries(s3_get_object_perf - PRIVATE - ${PROJECT_LIBS} - json_metrics +set_compiler_flags(s3_performance_test) +set_compiler_warnings(s3_performance_test) + +target_link_libraries(s3_performance_test + PRIVATE + ${PROJECT_LIBS} + json_metrics ) \ No newline at end of file diff --git a/tests/performance_tests/reporting/JsonReportingMetrics.cpp b/tests/performance_tests/reporting/JsonReportingMetrics.cpp new file mode 100644 index 00000000000..7fa59ad448e --- /dev/null +++ b/tests/performance_tests/reporting/JsonReportingMetrics.cpp @@ -0,0 +1,141 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include "JsonReportingMetrics.h" + +#include +#include +#include + +#include +#include + +Aws::String JsonReportingMetrics::m_testSize = ""; +Aws::String JsonReportingMetrics::m_testBucketType = ""; + +void JsonReportingMetrics::SetTestContext(const Aws::String& size, const Aws::String& bucketType) { + m_testSize = size; + m_testBucketType = bucketType; +} + +JsonReportingMetrics::JsonReportingMetrics() {} +JsonReportingMetrics::~JsonReportingMetrics() { DumpJson(); } + +JsonReportingMetricsFactory::~JsonReportingMetricsFactory() {} + +Aws::UniquePtr JsonReportingMetricsFactory::CreateMonitoringInstance() const { + return Aws::MakeUnique("JsonReportingMetrics"); +} + +void JsonReportingMetrics::AddMetric(const Aws::String& serviceName, const Aws::String& requestName, + const Aws::Monitoring::CoreMetricsCollection& metricsFromCore) const { + if (requestName != "PutObject" && requestName != "GetObject") { + return; + } + + std::lock_guard lock(m_mutex); + + double durationMs = 0.0; + Aws::String latencyKey = Aws::Monitoring::GetHttpClientMetricNameByType(Aws::Monitoring::HttpClientMetricsType::RequestLatency); + + auto it = metricsFromCore.httpClientMetrics.find(latencyKey); + if (it != metricsFromCore.httpClientMetrics.end()) { + durationMs = static_cast(it->second); + } + + RequestMetric metric; + metric.name = + Aws::Utils::StringUtils::ToLower(serviceName.c_str()) + "." + Aws::Utils::StringUtils::ToLower(requestName.c_str()) + ".latency"; + metric.description = "Time to complete " + requestName + " operation"; + metric.unit = "Milliseconds"; + metric.date = Aws::Utils::DateTime::CurrentTimeMillis() / 1000; + metric.measurements.push_back(durationMs); + + if (!m_testSize.empty()) { + metric.dimensions.push_back(std::make_pair("Size", m_testSize)); + } + if (!m_testBucketType.empty()) { + metric.dimensions.push_back(std::make_pair("BucketType", m_testBucketType)); + } + + metric.publishToCloudWatch = true; + m_metrics.push_back(metric); +} + +void* JsonReportingMetrics::OnRequestStarted(const Aws::String&, const Aws::String&, + const std::shared_ptr&) const { + return nullptr; +} + +void JsonReportingMetrics::OnRequestSucceeded(const Aws::String& serviceName, const Aws::String& requestName, + const std::shared_ptr&, const Aws::Client::HttpResponseOutcome&, + const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void*) const { + AddMetric(serviceName, requestName, metricsFromCore); +} + +void JsonReportingMetrics::OnRequestFailed(const Aws::String& serviceName, const Aws::String& requestName, + const std::shared_ptr&, const Aws::Client::HttpResponseOutcome&, + const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void*) const { + AddMetric(serviceName, requestName, metricsFromCore); +} + +void JsonReportingMetrics::OnRequestRetry(const Aws::String&, const Aws::String&, const std::shared_ptr&, + void*) const {} + +void JsonReportingMetrics::OnFinish(const Aws::String&, const Aws::String&, const std::shared_ptr&, + void*) const {} + +void JsonReportingMetrics::AggregateMetrics() const {} + +void JsonReportingMetrics::DumpJson() const { + std::lock_guard lock(m_mutex); + + if (m_metrics.empty()) { + return; + } + + Aws::Utils::Json::JsonValue root; + root.WithString("productId", "AWS SDK for C++"); + root.WithString("sdkVersion", "1.0.0"); + root.WithString("commitId", "unknown"); + + Aws::Utils::Array results(m_metrics.size()); + for (size_t i = 0; i < m_metrics.size(); ++i) { + Aws::Utils::Json::JsonValue metric; + metric.WithString("name", m_metrics[i].name); + metric.WithString("description", m_metrics[i].description); + metric.WithString("unit", m_metrics[i].unit); + metric.WithInt64("date", m_metrics[i].date); + + if (!m_metrics[i].dimensions.empty()) { + Aws::Utils::Array dimensionsArray(m_metrics[i].dimensions.size()); + for (size_t j = 0; j < m_metrics[i].dimensions.size(); ++j) { + Aws::Utils::Json::JsonValue dimension; + dimension.WithString("name", m_metrics[i].dimensions[j].first); + dimension.WithString("value", m_metrics[i].dimensions[j].second); + dimensionsArray[j] = std::move(dimension); + } + metric.WithArray("dimensions", std::move(dimensionsArray)); + } + + Aws::Utils::Array measurementsArray(m_metrics[i].measurements.size()); + for (size_t j = 0; j < m_metrics[i].measurements.size(); ++j) { + Aws::Utils::Json::JsonValue measurementValue; + measurementValue.AsDouble(m_metrics[i].measurements[j]); + measurementsArray[j] = std::move(measurementValue); + } + metric.WithArray("measurements", std::move(measurementsArray)); + + results[i] = std::move(metric); + } + root.WithArray("results", std::move(results)); + + std::cout << root.View().WriteReadable() << std::endl; + + std::ofstream outFile("perf-results.json"); + if (outFile.is_open()) { + outFile << root.View().WriteReadable(); + } +} \ No newline at end of file diff --git a/tests/performance_tests/reporting/JsonReportingMetrics.h b/tests/performance_tests/reporting/JsonReportingMetrics.h new file mode 100644 index 00000000000..767c0f8ba43 --- /dev/null +++ b/tests/performance_tests/reporting/JsonReportingMetrics.h @@ -0,0 +1,81 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/** + * @brief A data structure to hold the details of a single performance metric. + */ +struct RequestMetric { + Aws::String name; + Aws::String description; + Aws::String unit; + int64_t date; + Aws::Vector measurements; + Aws::Vector> dimensions; + bool publishToCloudWatch; +}; + +/** + * @brief An implementation of the MonitoringInterface that collects performance metrics + * and reports them in a JSON format. + */ +class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { + public: + JsonReportingMetrics(); + ~JsonReportingMetrics() override; + + void* OnRequestStarted(const Aws::String&, const Aws::String&, const std::shared_ptr&) const override; + void OnRequestSucceeded(const Aws::String&, const Aws::String&, const std::shared_ptr&, + const Aws::Client::HttpResponseOutcome&, const Aws::Monitoring::CoreMetricsCollection&, void*) const override; + void OnRequestFailed(const Aws::String&, const Aws::String&, const std::shared_ptr&, + const Aws::Client::HttpResponseOutcome&, const Aws::Monitoring::CoreMetricsCollection&, void*) const override; + void OnRequestRetry(const Aws::String&, const Aws::String&, const std::shared_ptr&, void*) const override; + void OnFinish(const Aws::String&, const Aws::String&, const std::shared_ptr&, void*) const override; + + /** + * @brief Sets the test-wide context to be added as dimensions to subsequently collected metrics. + * This serves as a communication channel between the main test runner and the monitoring instance. + * @param size A string label for the object size being tested (e.g., "64KB"). + * @param bucketType A string label for the bucket type being tested (e.g., "s3-standard"). + */ + static void SetTestContext(const Aws::String& size, const Aws::String& bucketType); + + private: + void AddMetric(const Aws::String& serviceName, const Aws::String& requestName, + const Aws::Monitoring::CoreMetricsCollection& metricsFromCore) const; + void DumpJson() const; + void AggregateMetrics() const; + + mutable std::mutex m_mutex; + mutable Aws::Vector m_metrics; + mutable Aws::Map> m_aggregatedMetrics; + + static Aws::String m_testSize; + static Aws::String m_testBucketType; +}; + +/** + * @brief A factory for creating instances of JsonReportingMetrics. + */ +class JsonReportingMetricsFactory : public Aws::Monitoring::MonitoringFactory { + public: + JsonReportingMetricsFactory() {} + ~JsonReportingMetricsFactory() override; + Aws::UniquePtr CreateMonitoringInstance() const override; +}; \ No newline at end of file diff --git a/tests/performance_tests/s3/S3PerformanceTest.cpp b/tests/performance_tests/s3/S3PerformanceTest.cpp new file mode 100644 index 00000000000..4c524323247 --- /dev/null +++ b/tests/performance_tests/s3/S3PerformanceTest.cpp @@ -0,0 +1,139 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "JsonReportingMetrics.h" + +// Defines the configuration for a single S3 performance test case. +struct TestConfig { + Aws::String sizeLabel; + size_t sizeBytes; + Aws::String bucketTypeLabel; +}; + +// Executes a single end-to-end S3 performance test scenario, including resource creation and cleanup. +// @param s3 An initialized S3Client instance. +// @param config The configuration for the test run, including object size and bucket type. +// @param availabilityZoneId The specific AZ required for S3 Express One Zone buckets. +// @return True if the test scenario completes successfully, false otherwise. +bool RunSingleTest(Aws::S3::S3Client& s3, const TestConfig& config, const Aws::String& availabilityZoneId) { + std::cout << "\n--- Running Test: Size=" << config.sizeLabel << ", BucketType=" << config.bucketTypeLabel << " ---\n"; + JsonReportingMetrics::SetTestContext(config.sizeLabel, config.bucketTypeLabel); + + Aws::String bucketName; + Aws::S3::Model::CreateBucketRequest cbr; + Aws::String raw_uuid = static_cast(Aws::Utils::UUID::RandomUUID()); + Aws::String id = Aws::Utils::StringUtils::ToLower(raw_uuid.c_str()).substr(0, 8); + + if (config.bucketTypeLabel == "s3-express") { + bucketName = "perf-express-" + id + "--" + availabilityZoneId + "--x-s3"; + cbr.SetBucket(bucketName); + Aws::S3::Model::CreateBucketConfiguration bucketConfig; + bucketConfig.SetLocation( + Aws::S3::Model::LocationInfo().WithType(Aws::S3::Model::LocationType::AvailabilityZone).WithName(availabilityZoneId)); + + bucketConfig.SetBucket(Aws::S3::Model::BucketInfo() + .WithType(Aws::S3::Model::BucketType::Directory) + .WithDataRedundancy(Aws::S3::Model::DataRedundancy::SingleAvailabilityZone)); + + cbr.SetCreateBucketConfiguration(bucketConfig); + } else { + bucketName = "perf-standard-" + id; + cbr.SetBucket(bucketName); + } + + auto createOutcome = s3.CreateBucket(cbr); + if (!createOutcome.IsSuccess()) { + std::cerr << "[ERROR] CreateBucket failed for " << bucketName << ": " << createOutcome.GetError().GetMessage() << std::endl; + return false; + } + std::cout << "Bucket created: " << bucketName << std::endl; + + Aws::String payload(config.sizeBytes, 'x'); + auto stream = Aws::MakeShared("PerfStream"); + *stream << payload; + + Aws::S3::Model::PutObjectRequest por; + por.WithBucket(bucketName).WithKey("test-object").SetBody(stream); + if (!s3.PutObject(por).IsSuccess()) { + std::cerr << "[ERROR] PutObject failed!" << std::endl; + } else { + std::cout << "Uploaded " << config.sizeLabel << std::endl; + } + + Aws::S3::Model::GetObjectRequest gor; + gor.WithBucket(bucketName).WithKey("test-object"); + if (!s3.GetObject(gor).IsSuccess()) { + std::cerr << "[ERROR] GetObject failed!" << std::endl; + } else { + std::cout << "Downloaded " << config.sizeLabel << std::endl; + } + + s3.DeleteObject(Aws::S3::Model::DeleteObjectRequest().WithBucket(bucketName).WithKey("test-object")); + s3.DeleteBucket(Aws::S3::Model::DeleteBucketRequest().WithBucket(bucketName)); + std::cout << "Cleaned up." << std::endl; + + return true; +} + +// The program runs a matrix of tests and outputs performance metrics to a JSON file. +int main(int argc, char** argv) { + Aws::String region = "us-east-1"; + Aws::String availabilityZoneId = "use1-az4"; + + for (int i = 1; i < argc; ++i) { + Aws::String arg = argv[i]; + if (arg == "--region" && i + 1 < argc) { + region = argv[++i]; + } + if (arg == "--az-id" && i + 1 < argc) { + availabilityZoneId = argv[++i]; + } + } + + Aws::Vector testMatrix = {{"8KB", 8 * 1024, "s3-standard"}, {"64KB", 64 * 1024, "s3-standard"}, + {"1MB", 1024 * 1024, "s3-standard"}, {"8KB", 8 * 1024, "s3-express"}, + {"64KB", 64 * 1024, "s3-express"}, {"1MB", 1024 * 1024, "s3-express"}}; + + Aws::SDKOptions options; + + options.monitoringOptions.customizedMonitoringFactory_create_fn.push_back( + []() { return Aws::MakeUnique("JsonReportingMetricsFactory"); }); + + Aws::InitAPI(options); + + { + Aws::Client::ClientConfiguration cfg; + cfg.region = region; + Aws::S3::S3Client s3(cfg); + + for (const auto& config : testMatrix) { + RunSingleTest(s3, config, availabilityZoneId); + } + } + + Aws::ShutdownAPI(options); + std::cout << "\nAll tests completed. Results saved to perf-results.json" << std::endl; + return 0; +} \ No newline at end of file diff --git a/tests/performance_tests/service/JsonReportingMetrics.cpp b/tests/performance_tests/service/JsonReportingMetrics.cpp deleted file mode 100644 index b5901dc47d5..00000000000 --- a/tests/performance_tests/service/JsonReportingMetrics.cpp +++ /dev/null @@ -1,154 +0,0 @@ -#include "JsonReportingMetrics.h" -#include -#include -#include -#include - -JsonReportingMetrics::JsonReportingMetrics() {} - -JsonReportingMetrics::~JsonReportingMetrics() { - DumpJson(); -} - -JsonReportingMetricsFactory::~JsonReportingMetricsFactory() {} - -// And the factory method -Aws::UniquePtr JsonReportingMetricsFactory::CreateMonitoringInstance() const { - return Aws::MakeUnique("JsonReportingMetrics"); -} - -void JsonReportingMetrics::AddMetric(const Aws::String& serviceName, const Aws::String& requestName, - const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, bool success) const { - std::lock_guard lock(m_mutex); - - double durationMs = 0.0; - Aws::String latencyKey = Aws::Monitoring::GetHttpClientMetricNameByType(Aws::Monitoring::HttpClientMetricsType::RequestLatency); - - auto it = metricsFromCore.httpClientMetrics.find(latencyKey); - if (it != metricsFromCore.httpClientMetrics.end()) { - durationMs = static_cast(it->second); - } - - RequestMetric metric; - metric.name = Aws::Utils::StringUtils::ToLower(serviceName.c_str()) + - Aws::String(".") + - Aws::Utils::StringUtils::ToLower(requestName.c_str()); - metric.description = Aws::String("Time to complete ") + metric.name + Aws::String(" operation"); - metric.unit = "Milliseconds"; - metric.date = Aws::Utils::DateTime::CurrentTimeMillis() / 1000; - metric.measurements.push_back(durationMs); - - metric.dimensions.push_back(std::make_pair(Aws::String("Service"), serviceName)); - metric.dimensions.push_back(std::make_pair(Aws::String("Operation"), requestName)); - metric.publishToCloudWatch = true; - - m_metrics.push_back(metric); -} - -void JsonReportingMetrics::AggregateMetrics() const { - // Create finalized metrics from the aggregated data - for (const auto& pair : m_aggregatedMetrics) { - RequestMetric metric; - metric.name = pair.first; - metric.description = Aws::String("Time to complete ") + pair.first + Aws::String(" operation"); - metric.unit = "Milliseconds"; - metric.date = Aws::Utils::DateTime::CurrentTimeMillis() / 1000; - metric.measurements = pair.second; - metric.publishToCloudWatch = true; - - // Add dimensions (e.g., AWS service name) - size_t dotPos = pair.first.find('.'); - if (dotPos != Aws::String::npos) { - Aws::String service = pair.first.substr(0, dotPos); - metric.dimensions.push_back(std::make_pair(Aws::String("Service"), service)); - } - - m_metrics.push_back(metric); - } -} - -// Interface Overrides -void* JsonReportingMetrics::OnRequestStarted(const Aws::String&, const Aws::String&, - const std::shared_ptr&) const { - return nullptr; -} - -void JsonReportingMetrics::OnRequestSucceeded(const Aws::String& serviceName, const Aws::String& requestName, - const std::shared_ptr&, - const Aws::Client::HttpResponseOutcome& outcome, - const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void*) const { - AddMetric(serviceName, requestName, metricsFromCore, outcome.IsSuccess()); -} - -void JsonReportingMetrics::OnRequestFailed(const Aws::String& serviceName, const Aws::String& requestName, - const std::shared_ptr&, - const Aws::Client::HttpResponseOutcome& outcome, - const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void*) const { - AddMetric(serviceName, requestName, metricsFromCore, outcome.IsSuccess()); -} - -void JsonReportingMetrics::OnFinish(const Aws::String&, const Aws::String&, const std::shared_ptr&, - void*) const { -} - -void JsonReportingMetrics::OnRequestRetry(const Aws::String&, const Aws::String&, const std::shared_ptr&, - void*) const { -} - -void JsonReportingMetrics::DumpJson() const { - std::lock_guard lock(m_mutex); - - if (m_metrics.empty()) { - return; - } - - Aws::Utils::Json::JsonValue root; - - // Add required top-level fields - root.WithString("productId", "AWS SDK for C++"); - root.WithString("sdkVersion", "1.0.0"); - root.WithString("commitId", "unknown"); // Consider getting this from CI/CD env variable - - Aws::Utils::Array results(m_metrics.size()); - - for (size_t i = 0; i < m_metrics.size(); ++i) { - Aws::Utils::Json::JsonValue metric; - metric.WithString("name", m_metrics[i].name); - metric.WithString("description", m_metrics[i].description); - metric.WithString("unit", m_metrics[i].unit); - metric.WithInt64("date", m_metrics[i].date); - - // Add dimensions if present - if (!m_metrics[i].dimensions.empty()) { - Aws::Utils::Array dimensionsArray(m_metrics[i].dimensions.size()); - for (size_t j = 0; j < m_metrics[i].dimensions.size(); ++j) { - Aws::Utils::Json::JsonValue dimension; - dimension.WithString("name", m_metrics[i].dimensions[j].first); - dimension.WithString("value", m_metrics[i].dimensions[j].second); - dimensionsArray[j] = std::move(dimension); - } - metric.WithArray("dimensions", std::move(dimensionsArray)); - } - - // Create a JSON array for measurements - Aws::Utils::Array measurementsArray(m_metrics[i].measurements.size()); - for (size_t j = 0; j < m_metrics[i].measurements.size(); ++j) { - Aws::Utils::Json::JsonValue measurementValue; - measurementValue.AsDouble(m_metrics[i].measurements[j]); - measurementsArray[j] = std::move(measurementValue); - } - metric.WithArray("measurements", std::move(measurementsArray)); - - results[i] = std::move(metric); - } - root.WithArray("results", std::move(results)); - - // Write to stdout so the performance test runner can capture it - std::cout << root.View().WriteReadable() << std::endl; - - // Save to file - std::ofstream outFile("perf-results.json"); - if (outFile.is_open()) { - outFile << root.View().WriteReadable(); - } -} \ No newline at end of file diff --git a/tests/performance_tests/service/JsonReportingMetrics.h b/tests/performance_tests/service/JsonReportingMetrics.h deleted file mode 100644 index dfe427daa37..00000000000 --- a/tests/performance_tests/service/JsonReportingMetrics.h +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -struct RequestMetric { - Aws::String name; - Aws::String description; - Aws::String unit; - int64_t date; - Aws::Vector measurements; - Aws::Vector> dimensions; - bool publishToCloudWatch; -}; - -class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { -public: - JsonReportingMetrics(); - ~JsonReportingMetrics() override; - - void* OnRequestStarted(const Aws::String& serviceName, const Aws::String& requestName, - const std::shared_ptr& request) const override; - - void OnRequestSucceeded(const Aws::String& serviceName, const Aws::String& requestName, - const std::shared_ptr& request, const Aws::Client::HttpResponseOutcome& outcome, - const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void* context) const override; - - void OnRequestFailed(const Aws::String& serviceName, const Aws::String& requestName, - const std::shared_ptr& request, const Aws::Client::HttpResponseOutcome& outcome, - const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void* context) const override; - - void OnRequestRetry(const Aws::String& serviceName, const Aws::String& requestName, - const std::shared_ptr& request, void* context) const override; - - void OnFinish(const Aws::String& serviceName, const Aws::String& requestName, - const std::shared_ptr& request, void* context) const override; - -private: - void AddMetric(const Aws::String& serviceName, const Aws::String& requestName, - const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, bool success) const; - void DumpJson() const; - - void AggregateMetrics() const; - - mutable std::mutex m_mutex; - mutable Aws::Vector m_metrics; - mutable Aws::Map> m_aggregatedMetrics; -}; - -class JsonReportingMetricsFactory : public Aws::Monitoring::MonitoringFactory { -public: - JsonReportingMetricsFactory() {} - ~JsonReportingMetricsFactory() override; - Aws::UniquePtr CreateMonitoringInstance() const override; -}; \ No newline at end of file diff --git a/tests/performance_tests/service/S3GetObject.cpp b/tests/performance_tests/service/S3GetObject.cpp deleted file mode 100644 index 4400afc38c7..00000000000 --- a/tests/performance_tests/service/S3GetObject.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Simple perf test: create bucket -> put 64 KiB -> get it once -> cleanup - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "JsonReportingMetrics.h" - -int main(int argc, char** argv) { - Aws::SDKOptions options; - - options.monitoringOptions.customizedMonitoringFactory_create_fn.push_back( - []() { return Aws::MakeUnique("jsonFactory"); }); - - Aws::InitAPI(options); - { - Aws::Client::ClientConfiguration cfg; - if (argc > 1) cfg.region = argv[1]; - - cfg.enableHttpClientTrace = true; - - Aws::S3::S3Client s3(cfg); - - // 1) bucket name - Aws::String raw = static_cast(Aws::Utils::UUID::RandomUUID()); - Aws::String id = Aws::Utils::StringUtils::ToLower(raw.c_str()).substr(10); - Aws::String bucket = Aws::String("get-bucket-benchmark-") + id; - - // 2) create bucket - Aws::S3::Model::CreateBucketRequest cbr; - cbr.WithBucket(bucket); - if (!s3.CreateBucket(cbr).IsSuccess()) { - std::cerr << "[ERROR] CreateBucket\n"; - return 1; - } - - // 3) put a 64KiB test object - std::string payload(64 * 1024, 'x'); - auto stream = Aws::MakeShared("PerfStream"); - *stream << payload; - - Aws::S3::Model::PutObjectRequest por; - por.WithBucket(bucket).WithKey("test-object").SetBody(stream); - if (!s3.PutObject(por).IsSuccess()) { - std::cerr << "[ERROR] PutObject\n"; - return 1; - } - std::cout << "Uploaded 64 KiB to " << bucket << "/test-object\n"; - - // 4) get object - Aws::S3::Model::GetObjectRequest gor; - gor.WithBucket(bucket).WithKey("test-object"); - - auto goOutcome = s3.GetObject(gor); - if (!goOutcome.IsSuccess()) { - std::cerr << "[ERROR] GetObject: " << goOutcome.GetError().GetMessage() << "\n"; - return 1; - } - std::cout << "Downloaded " << goOutcome.GetResult().GetContentLength() << " bytes\n"; - - // 5) cleanup - s3.DeleteObject(Aws::S3::Model::DeleteObjectRequest().WithBucket(bucket).WithKey("test-object")); - s3.DeleteBucket(Aws::S3::Model::DeleteBucketRequest().WithBucket(bucket)); - std::cout << "Cleaned up\n"; - } - Aws::ShutdownAPI(options); - return 0; -} \ No newline at end of file diff --git a/tests/performance_tests/service/S3PutObject.cpp b/tests/performance_tests/service/S3PutObject.cpp deleted file mode 100644 index f2fb73562bf..00000000000 --- a/tests/performance_tests/service/S3PutObject.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Simple perf test: create bucket -> put 64 KiB object -> delete object + bucket - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "JsonReportingMetrics.h" - -int main(int argc, char** argv) { - Aws::SDKOptions options; - - options.monitoringOptions.customizedMonitoringFactory_create_fn.push_back( - []() { return Aws::MakeUnique("jsonFactory"); }); - - Aws::InitAPI(options); - { - Aws::Client::ClientConfiguration cfg; - if (argc > 1) cfg.region = argv[1]; - - cfg.enableHttpClientTrace = true; - - Aws::S3::S3Client s3(cfg); - - // 1) bucket name - Aws::String raw = static_cast(Aws::Utils::UUID::RandomUUID()); - Aws::String id = Aws::Utils::StringUtils::ToLower(raw.c_str()).substr(10); - Aws::String bucket = Aws::String("put-bucket-benchmark-") + id; - - // 2) create bucket - Aws::S3::Model::CreateBucketRequest cbr; - cbr.WithBucket(bucket); - auto cbOutcome = s3.CreateBucket(cbr); - if (!cbOutcome.IsSuccess()) { - std::cerr << "[ERROR] CreateBucket: " << cbOutcome.GetError().GetMessage() << "\n"; - return 1; - } - - // 3) put a 64KiB test object - std::string payload(64 * 1024, 'x'); - auto stream = Aws::MakeShared("PerfStream"); - *stream << payload; - - // 4) PutObject - Aws::S3::Model::PutObjectRequest por; - por.WithBucket(bucket).WithKey("test-object").SetBody(stream); - - auto poOutcome = s3.PutObject(por); - if (!poOutcome.IsSuccess()) { - std::cerr << "[ERROR] PutObject: " << poOutcome.GetError().GetMessage() << "\n"; - return 1; - } - std::cout << "Uploaded 64 KiB to " << bucket << "/test-object\n"; - - // 5) cleanup - s3.DeleteObject(Aws::S3::Model::DeleteObjectRequest().WithBucket(bucket).WithKey("test-object")); - s3.DeleteBucket(Aws::S3::Model::DeleteBucketRequest().WithBucket(bucket)); - std::cout << "Cleaned up\n"; - } - Aws::ShutdownAPI(options); - return 0; -} \ No newline at end of file From ca4a78f4875a5f01095fff255fea6b5c2c88353e Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Tue, 10 Jun 2025 12:26:06 -0400 Subject: [PATCH 08/77] remove redundant code --- tests/performance_tests/reporting/JsonReportingMetrics.cpp | 2 -- tests/performance_tests/reporting/JsonReportingMetrics.h | 4 ---- 2 files changed, 6 deletions(-) diff --git a/tests/performance_tests/reporting/JsonReportingMetrics.cpp b/tests/performance_tests/reporting/JsonReportingMetrics.cpp index 7fa59ad448e..42a5484e985 100644 --- a/tests/performance_tests/reporting/JsonReportingMetrics.cpp +++ b/tests/performance_tests/reporting/JsonReportingMetrics.cpp @@ -20,7 +20,6 @@ void JsonReportingMetrics::SetTestContext(const Aws::String& size, const Aws::St m_testBucketType = bucketType; } -JsonReportingMetrics::JsonReportingMetrics() {} JsonReportingMetrics::~JsonReportingMetrics() { DumpJson(); } JsonReportingMetricsFactory::~JsonReportingMetricsFactory() {} @@ -87,7 +86,6 @@ void JsonReportingMetrics::OnRequestRetry(const Aws::String&, const Aws::String& void JsonReportingMetrics::OnFinish(const Aws::String&, const Aws::String&, const std::shared_ptr&, void*) const {} -void JsonReportingMetrics::AggregateMetrics() const {} void JsonReportingMetrics::DumpJson() const { std::lock_guard lock(m_mutex); diff --git a/tests/performance_tests/reporting/JsonReportingMetrics.h b/tests/performance_tests/reporting/JsonReportingMetrics.h index 767c0f8ba43..7a335567a26 100644 --- a/tests/performance_tests/reporting/JsonReportingMetrics.h +++ b/tests/performance_tests/reporting/JsonReportingMetrics.h @@ -37,7 +37,6 @@ struct RequestMetric { */ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { public: - JsonReportingMetrics(); ~JsonReportingMetrics() override; void* OnRequestStarted(const Aws::String&, const Aws::String&, const std::shared_ptr&) const override; @@ -60,11 +59,9 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { void AddMetric(const Aws::String& serviceName, const Aws::String& requestName, const Aws::Monitoring::CoreMetricsCollection& metricsFromCore) const; void DumpJson() const; - void AggregateMetrics() const; mutable std::mutex m_mutex; mutable Aws::Vector m_metrics; - mutable Aws::Map> m_aggregatedMetrics; static Aws::String m_testSize; static Aws::String m_testBucketType; @@ -75,7 +72,6 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { */ class JsonReportingMetricsFactory : public Aws::Monitoring::MonitoringFactory { public: - JsonReportingMetricsFactory() {} ~JsonReportingMetricsFactory() override; Aws::UniquePtr CreateMonitoringInstance() const override; }; \ No newline at end of file From 251263d9586846bfd3ec7204060f49721681c92a Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Sun, 22 Jun 2025 20:52:48 -0400 Subject: [PATCH 09/77] multiple executables for each service --- tests/performance-tests/CMakeLists.txt | 25 +++ .../reporting/JsonReportingMetrics.h | 83 ++++++++ .../dynamodb/DynamoDBPerformanceTest.h | 24 +++ .../services/dynamodb/DynamoDBTestConfig.h | 23 +++ .../services/s3/S3PerformanceTest.h | 25 +++ .../services/s3/S3TestConfig.h | 25 +++ .../src/reporting/JsonReportingMetrics.cpp | 177 ++++++++++++++++++ .../dynamodb/DynamoDBPerformanceTest.cpp | 98 ++++++++++ .../src/services/dynamodb/main.cpp | 61 ++++++ .../src/services/s3/S3PerformanceTest.cpp | 93 +++++++++ .../src/services/s3/main.cpp | 63 +++++++ tests/performance_tests/CMakeLists.txt | 44 ----- .../reporting/JsonReportingMetrics.cpp | 139 -------------- .../reporting/JsonReportingMetrics.h | 77 -------- .../s3/S3PerformanceTest.cpp | 139 -------------- 15 files changed, 697 insertions(+), 399 deletions(-) create mode 100644 tests/performance-tests/CMakeLists.txt create mode 100644 tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h create mode 100644 tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBPerformanceTest.h create mode 100644 tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBTestConfig.h create mode 100644 tests/performance-tests/include/performance_tests/services/s3/S3PerformanceTest.h create mode 100644 tests/performance-tests/include/performance_tests/services/s3/S3TestConfig.h create mode 100644 tests/performance-tests/src/reporting/JsonReportingMetrics.cpp create mode 100644 tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp create mode 100644 tests/performance-tests/src/services/dynamodb/main.cpp create mode 100644 tests/performance-tests/src/services/s3/S3PerformanceTest.cpp create mode 100644 tests/performance-tests/src/services/s3/main.cpp delete mode 100644 tests/performance_tests/CMakeLists.txt delete mode 100644 tests/performance_tests/reporting/JsonReportingMetrics.cpp delete mode 100644 tests/performance_tests/reporting/JsonReportingMetrics.h delete mode 100644 tests/performance_tests/s3/S3PerformanceTest.cpp diff --git a/tests/performance-tests/CMakeLists.txt b/tests/performance-tests/CMakeLists.txt new file mode 100644 index 00000000000..668abfc5e36 --- /dev/null +++ b/tests/performance-tests/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0. +# + +add_project(performance-tests + "A suite of AWS C++ SDK performance tests" + aws-cpp-sdk-core + aws-cpp-sdk-s3 + aws-cpp-sdk-dynamodb +) + +function(add_service_test SERVICE SDK_LIB) + add_executable(${SERVICE}-performance-test + src/services/${SERVICE}/main.cpp + src/reporting/JsonReportingMetrics.cpp + src/services/${SERVICE}/${SERVICE}PerformanceTest.cpp + ) + set_compiler_flags(${SERVICE}-performance-test) + set_compiler_warnings(${SERVICE}-performance-test) + target_include_directories(${SERVICE}-performance-test PRIVATE include) + target_link_libraries(${SERVICE}-performance-test PRIVATE aws-cpp-sdk-core ${SDK_LIB}) +endfunction() + +add_service_test(s3 aws-cpp-sdk-s3) +add_service_test(dynamodb aws-cpp-sdk-dynamodb) diff --git a/tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h b/tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h new file mode 100644 index 00000000000..5fbb2ae1b24 --- /dev/null +++ b/tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h @@ -0,0 +1,83 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace PerformanceTest { +namespace Reporting { +/** + * @brief Container for a single performance metric record that stores measurement data and associated metadata. + */ +struct PerformanceMetricRecord { + Aws::String name; + Aws::String description; + Aws::String unit; + int64_t date; + Aws::Vector measurements; + Aws::Vector> dimensions; + +}; + +/** + * @brief An implementation of the MonitoringInterface that collects performance metrics + * and reports them in a JSON format. + */ +class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { + public: + ~JsonReportingMetrics() override; + + void* OnRequestStarted(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request) const override; + void OnRequestSucceeded(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request, + const Aws::Client::HttpResponseOutcome& outcome, const Aws::Monitoring::CoreMetricsCollection& metrics, void* context) const override; + void OnRequestFailed(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request, + const Aws::Client::HttpResponseOutcome& outcome, const Aws::Monitoring::CoreMetricsCollection& metrics, void* context) const override; + void OnRequestRetry(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request, void* context) const override; + void OnFinish(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request, void* context) const override; + + static void SetTestContext(const Aws::Vector>& dimensions); + + static void RegisterOperationsToMonitor(const Aws::Vector& operations); + + static void SetProductInfo(const Aws::String& productId, const Aws::String& sdkVersion, const Aws::String& commitId); + + static void SetOutputFilename(const Aws::String& filename); + + private: + void AddPerformanceRecord(const Aws::String& serviceName, const Aws::String& requestName, + const Aws::Monitoring::CoreMetricsCollection& metricsFromCore) const; + void DumpJson() const; + + mutable Aws::Vector m_performanceRecords; + + static Aws::Vector> m_testDimensions; + static Aws::Set m_monitoredOperations; + static Aws::String m_productId; + static Aws::String m_sdkVersion; + static Aws::String m_commitId; + static Aws::String m_outputFilename; +}; + +/** + * @brief A factory for creating instances of JsonReportingMetrics. + */ +class JsonReportingMetricsFactory : public Aws::Monitoring::MonitoringFactory { + public: + ~JsonReportingMetricsFactory() override; + auto CreateMonitoringInstance() const -> Aws::UniquePtr override; +}; +} // namespace Reporting +} // namespace PerformanceTest \ No newline at end of file diff --git a/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBPerformanceTest.h b/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBPerformanceTest.h new file mode 100644 index 00000000000..95c68557e0f --- /dev/null +++ b/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBPerformanceTest.h @@ -0,0 +1,24 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once + +#include +#include + +#include + +namespace PerformanceTest { +namespace Services { +namespace DynamoDB { +struct TestCase { + Aws::String sizeLabel; + size_t sizeBytes; +}; + +bool RunTest(Aws::DynamoDB::DynamoDBClient& dynamodb, const TestCase& config, int iterations = 3); +} // namespace DynamoDB +} // namespace Services +} // namespace PerformanceTest \ No newline at end of file diff --git a/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBTestConfig.h b/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBTestConfig.h new file mode 100644 index 00000000000..80260fef580 --- /dev/null +++ b/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBTestConfig.h @@ -0,0 +1,23 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once + +#include +#include + +#include "performance_tests/services/dynamodb/DynamoDBPerformanceTest.h" + +namespace PerformanceTest { +namespace Services { +namespace DynamoDB { +namespace TestConfig { +const Aws::Vector OPERATIONS = {"PutItem", "GetItem"}; + +const Aws::Vector TEST_MATRIX = {{"8KB", 8 * 1024}, {"64KB", 64 * 1024}, {"392KB", 392 * 1024}}; +} // namespace TestConfig +} // namespace DynamoDB +} // namespace Services +} // namespace PerformanceTest \ No newline at end of file diff --git a/tests/performance-tests/include/performance_tests/services/s3/S3PerformanceTest.h b/tests/performance-tests/include/performance_tests/services/s3/S3PerformanceTest.h new file mode 100644 index 00000000000..256983ce6c4 --- /dev/null +++ b/tests/performance-tests/include/performance_tests/services/s3/S3PerformanceTest.h @@ -0,0 +1,25 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once + +#include +#include + +#include + +namespace PerformanceTest { +namespace Services { +namespace S3 { +struct TestCase { + Aws::String sizeLabel; + size_t sizeBytes; + Aws::String bucketTypeLabel; +}; + +bool RunTest(Aws::S3::S3Client& s3, const TestCase& config, const Aws::String& availabilityZoneId, int iterations = 3); +} // namespace S3 +} // namespace Services +} // namespace PerformanceTest \ No newline at end of file diff --git a/tests/performance-tests/include/performance_tests/services/s3/S3TestConfig.h b/tests/performance-tests/include/performance_tests/services/s3/S3TestConfig.h new file mode 100644 index 00000000000..fa58b009937 --- /dev/null +++ b/tests/performance-tests/include/performance_tests/services/s3/S3TestConfig.h @@ -0,0 +1,25 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once + +#include +#include + +#include "performance_tests/services/s3/S3PerformanceTest.h" + +namespace PerformanceTest { +namespace Services { +namespace S3 { +namespace TestConfig { +const Aws::Vector OPERATIONS = {"PutObject", "GetObject"}; + +const Aws::Vector TEST_MATRIX = {{"8KB", 8 * 1024, "s3-standard"}, {"64KB", 64 * 1024, "s3-standard"}, + {"1MB", 1024 * 1024, "s3-standard"}, {"8KB", 8 * 1024, "s3-express"}, + {"64KB", 64 * 1024, "s3-express"}, {"1MB", 1024 * 1024, "s3-express"}}; +} // namespace TestConfig +} // namespace S3 +} // namespace Services +} // namespace PerformanceTest \ No newline at end of file diff --git a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp new file mode 100644 index 00000000000..988a49c548a --- /dev/null +++ b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp @@ -0,0 +1,177 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include "performance_tests/reporting/JsonReportingMetrics.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace PerformanceTest::Reporting; + +Aws::Vector> JsonReportingMetrics::m_testDimensions; +Aws::Set JsonReportingMetrics::m_monitoredOperations; +Aws::String JsonReportingMetrics::m_productId = "unknown"; +Aws::String JsonReportingMetrics::m_sdkVersion = "unknown"; +Aws::String JsonReportingMetrics::m_commitId = "unknown"; +Aws::String JsonReportingMetrics::m_outputFilename = "perf-results.json"; + +void JsonReportingMetrics::SetTestContext(const Aws::Vector>& dimensions) { + m_testDimensions = dimensions; +} + +void JsonReportingMetrics::RegisterOperationsToMonitor(const Aws::Vector& operations) { + m_monitoredOperations.clear(); + for (const auto& op : operations) { + m_monitoredOperations.insert(op); + } +} + +void JsonReportingMetrics::SetProductInfo(const Aws::String& productId, const Aws::String& sdkVersion, const Aws::String& commitId) { + m_productId = productId; + m_sdkVersion = sdkVersion; + m_commitId = commitId; +} + +void JsonReportingMetrics::SetOutputFilename(const Aws::String& filename) { m_outputFilename = filename; } + +JsonReportingMetrics::~JsonReportingMetrics() { DumpJson(); } + +JsonReportingMetricsFactory::~JsonReportingMetricsFactory() {} + +auto JsonReportingMetricsFactory::CreateMonitoringInstance() const -> Aws::UniquePtr { + return Aws::MakeUnique("JsonReportingMetrics"); +} + +void JsonReportingMetrics::AddPerformanceRecord(const Aws::String& serviceName, const Aws::String& requestName, + const Aws::Monitoring::CoreMetricsCollection& metricsFromCore) const { + // If no operations are registered, monitor all operations + // Otherwise, only monitor registered operations + if (!m_monitoredOperations.empty() && m_monitoredOperations.find(requestName) == m_monitoredOperations.end()) { + return; + } + + double durationMs = 0.0; + Aws::String latencyKey = Aws::Monitoring::GetHttpClientMetricNameByType(Aws::Monitoring::HttpClientMetricsType::RequestLatency); + + auto it = metricsFromCore.httpClientMetrics.find(latencyKey); + if (it != metricsFromCore.httpClientMetrics.end()) { + durationMs = static_cast(it->second); + } + + PerformanceMetricRecord record; + record.name = + Aws::Utils::StringUtils::ToLower(serviceName.c_str()) + "." + Aws::Utils::StringUtils::ToLower(requestName.c_str()) + ".latency"; + record.description = "Time to complete " + requestName + " operation"; + record.unit = "Milliseconds"; + record.date = Aws::Utils::DateTime::CurrentTimeMillis() / 1000; + record.measurements.push_back(durationMs); + record.dimensions = m_testDimensions; + + m_performanceRecords.push_back(record); +} + +void* JsonReportingMetrics::OnRequestStarted(const Aws::String& serviceName, const Aws::String& requestName, + const std::shared_ptr& request) const { + return nullptr; +} + +void JsonReportingMetrics::OnRequestSucceeded(const Aws::String& serviceName, const Aws::String& requestName, + const std::shared_ptr&, const Aws::Client::HttpResponseOutcome&, + const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void*) const { + AddPerformanceRecord(serviceName, requestName, metricsFromCore); +} + +void JsonReportingMetrics::OnRequestFailed(const Aws::String& serviceName, const Aws::String& requestName, + const std::shared_ptr&, const Aws::Client::HttpResponseOutcome&, + const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void*) const { + AddPerformanceRecord(serviceName, requestName, metricsFromCore); +} + +void JsonReportingMetrics::OnRequestRetry(const Aws::String&, const Aws::String&, const std::shared_ptr&, + void*) const {} + +void JsonReportingMetrics::OnFinish(const Aws::String&, const Aws::String&, const std::shared_ptr&, + void*) const {} + +void JsonReportingMetrics::DumpJson() const { + if (m_performanceRecords.empty()) { + return; + } + + // Group performance records by name and dimensions + std::map aggregatedRecords; + + for (const auto& record : m_performanceRecords) { + std::string key = record.name.c_str(); + for (const auto& dim : record.dimensions) { + key += ":" + std::string(dim.first.c_str()) + "=" + std::string(dim.second.c_str()); + } + + if (aggregatedRecords.find(key) == aggregatedRecords.end()) { + aggregatedRecords[key] = record; + } else { + for (const auto& measurement : record.measurements) { + aggregatedRecords[key].measurements.push_back(measurement); + } + } + } + + // Create the JSON output + Aws::Utils::Json::JsonValue root; + root.WithString("productId", m_productId); + root.WithString("sdkVersion", m_sdkVersion); + root.WithString("commitId", m_commitId); + + Aws::Utils::Array results(aggregatedRecords.size()); + size_t index = 0; + + for (const auto& pair : aggregatedRecords) { + const auto& record = pair.second; + Aws::Utils::Json::JsonValue jsonMetric; + jsonMetric.WithString("name", record.name); + jsonMetric.WithString("description", record.description); + jsonMetric.WithString("unit", record.unit); + jsonMetric.WithInt64("date", record.date); + + if (!record.dimensions.empty()) { + Aws::Utils::Array dimensionsArray(record.dimensions.size()); + for (size_t j = 0; j < record.dimensions.size(); ++j) { + Aws::Utils::Json::JsonValue dimension; + dimension.WithString("name", record.dimensions[j].first); + dimension.WithString("value", record.dimensions[j].second); + dimensionsArray[j] = std::move(dimension); + } + jsonMetric.WithArray("dimensions", std::move(dimensionsArray)); + } + + Aws::Utils::Array measurementsArray(record.measurements.size()); + for (size_t j = 0; j < record.measurements.size(); ++j) { + Aws::Utils::Json::JsonValue measurementValue; + measurementValue.AsDouble(record.measurements[j]); + measurementsArray[j] = std::move(measurementValue); + } + jsonMetric.WithArray("measurements", std::move(measurementsArray)); + + results[index++] = std::move(jsonMetric); + } + + root.WithArray("results", std::move(results)); + + std::ofstream outFile(m_outputFilename.c_str()); + if (outFile.is_open()) { + outFile << root.View().WriteReadable(); + } +} \ No newline at end of file diff --git a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp new file mode 100644 index 00000000000..a025039bf4c --- /dev/null +++ b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp @@ -0,0 +1,98 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include "performance_tests/services/dynamodb/DynamoDBPerformanceTest.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "performance_tests/reporting/JsonReportingMetrics.h" + +bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& dynamodb, const TestCase& config, int iterations) { + Aws::Vector> dimensions; + dimensions.push_back(std::make_pair("Size", config.sizeLabel)); + PerformanceTest::Reporting::JsonReportingMetrics::SetTestContext(dimensions); + + Aws::String tableName; + Aws::String raw_uuid = static_cast(Aws::Utils::UUID::RandomUUID()); + Aws::String id = Aws::Utils::StringUtils::ToLower(raw_uuid.c_str()).substr(0, 8); + tableName = "perf-table-" + id; + + Aws::DynamoDB::Model::CreateTableRequest createTableRequest; + createTableRequest.SetTableName(tableName); + + Aws::DynamoDB::Model::AttributeDefinition hashKey; + hashKey.SetAttributeName("id"); + hashKey.SetAttributeType(Aws::DynamoDB::Model::ScalarAttributeType::S); + createTableRequest.AddAttributeDefinitions(hashKey); + + Aws::DynamoDB::Model::KeySchemaElement keySchema; + keySchema.WithAttributeName("id").WithKeyType(Aws::DynamoDB::Model::KeyType::HASH); + createTableRequest.AddKeySchema(keySchema); + + Aws::DynamoDB::Model::BillingMode billingMode = Aws::DynamoDB::Model::BillingMode::PAY_PER_REQUEST; + createTableRequest.SetBillingMode(billingMode); + + auto createTableOutcome = dynamodb.CreateTable(createTableRequest); + if (!createTableOutcome.IsSuccess()) { + std::cerr << "[ERROR] CreateTable failed: " << createTableOutcome.GetError().GetMessage() << std::endl; + return false; + } + + // Wait for table to become active + std::this_thread::sleep_for(std::chrono::seconds(10)); + Aws::String payload(config.sizeBytes, 'x'); + + // Run PutItem multiple times + for (int i = 0; i < iterations; i++) { + Aws::DynamoDB::Model::PutItemRequest putItemRequest; + putItemRequest.SetTableName(tableName); + + Aws::Map item; + item["id"].SetS("test-key-" + std::to_string(i)); + item["data"].SetS(payload); + putItemRequest.SetItem(item); + + auto putItemOutcome = dynamodb.PutItem(putItemRequest); + if (!putItemOutcome.IsSuccess()) { + std::cerr << "[ERROR] PutItem failed: " << putItemOutcome.GetError().GetMessage() << std::endl; + } + } + + // Run GetItem multiple times + for (int i = 0; i < iterations; i++) { + Aws::DynamoDB::Model::GetItemRequest getItemRequest; + getItemRequest.SetTableName(tableName); + + Aws::Map key; + key["id"].SetS("test-key-" + std::to_string(i)); + getItemRequest.SetKey(key); + + auto getItemOutcome = dynamodb.GetItem(getItemRequest); + if (!getItemOutcome.IsSuccess()) { + std::cerr << "[ERROR] GetItem failed: " << getItemOutcome.GetError().GetMessage() << std::endl; + } + } + + Aws::DynamoDB::Model::DeleteTableRequest deleteTableRequest; + deleteTableRequest.SetTableName(tableName); + dynamodb.DeleteTable(deleteTableRequest); + + return true; +} \ No newline at end of file diff --git a/tests/performance-tests/src/services/dynamodb/main.cpp b/tests/performance-tests/src/services/dynamodb/main.cpp new file mode 100644 index 00000000000..f320186aa3e --- /dev/null +++ b/tests/performance-tests/src/services/dynamodb/main.cpp @@ -0,0 +1,61 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "performance_tests/reporting/JsonReportingMetrics.h" +#include "performance_tests/services/dynamodb/DynamoDBPerformanceTest.h" +#include "performance_tests/services/dynamodb/DynamoDBTestConfig.h" + +int main(int argc, char** argv) { + Aws::String region = "us-east-1"; + Aws::String commitId = "unknown"; + int iterations = 3; + + for (int i = 1; i < argc; ++i) { + Aws::String arg = argv[i]; + if (arg == "--region" && i + 1 < argc) { + region = argv[++i]; + } else if (arg == "--iterations" && i + 1 < argc) { + iterations = std::stoi(argv[++i]); + } else if (arg == "--commit-id" && i + 1 < argc) { + commitId = argv[++i]; + } + } + + Aws::SDKOptions options; + options.monitoringOptions.customizedMonitoringFactory_create_fn.push_back( + []() { return Aws::MakeUnique("JsonReportingMetricsFactory"); }); + + Aws::InitAPI(options); + + PerformanceTest::Reporting::JsonReportingMetrics::RegisterOperationsToMonitor( + PerformanceTest::Services::DynamoDB::TestConfig::OPERATIONS); + + Aws::SDKOptions::SDKVersion version; + Aws::String versionStr = std::to_string(version.major) + "." + std::to_string(version.minor) + "." + std::to_string(version.patch); + PerformanceTest::Reporting::JsonReportingMetrics::SetProductInfo("cpp1", versionStr, commitId); + PerformanceTest::Reporting::JsonReportingMetrics::SetOutputFilename("dynamodb-perf-results.json"); + + { + Aws::Client::ClientConfiguration cfg; + cfg.region = region; + + Aws::DynamoDB::DynamoDBClient dynamodb(cfg); + for (const auto& config : PerformanceTest::Services::DynamoDB::TestConfig::TEST_MATRIX) { + PerformanceTest::Services::DynamoDB::RunTest(dynamodb, config, iterations); + } + } + + Aws::ShutdownAPI(options); + return 0; +} \ No newline at end of file diff --git a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp new file mode 100644 index 00000000000..d0ffa54b8e5 --- /dev/null +++ b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp @@ -0,0 +1,93 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include "performance_tests/services/s3/S3PerformanceTest.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "performance_tests/reporting/JsonReportingMetrics.h" + +bool PerformanceTest::Services::S3::RunTest(Aws::S3::S3Client& s3, const TestCase& config, const Aws::String& availabilityZoneId, + int iterations) { + Aws::Vector> dimensions; + dimensions.push_back(std::make_pair("Size", config.sizeLabel)); + dimensions.push_back(std::make_pair("BucketType", config.bucketTypeLabel)); + PerformanceTest::Reporting::JsonReportingMetrics::SetTestContext(dimensions); + + Aws::String bucketName; + Aws::S3::Model::CreateBucketRequest cbr; + Aws::String raw_uuid = static_cast(Aws::Utils::UUID::RandomUUID()); + Aws::String id = Aws::Utils::StringUtils::ToLower(raw_uuid.c_str()).substr(0, 8); + + if (config.bucketTypeLabel == "s3-express") { + bucketName = "perf-express-" + id + "--" + availabilityZoneId + "--x-s3"; + cbr.SetBucket(bucketName); + Aws::S3::Model::CreateBucketConfiguration bucketConfig; + bucketConfig.SetLocation( + Aws::S3::Model::LocationInfo().WithType(Aws::S3::Model::LocationType::AvailabilityZone).WithName(availabilityZoneId)); + + bucketConfig.SetBucket(Aws::S3::Model::BucketInfo() + .WithType(Aws::S3::Model::BucketType::Directory) + .WithDataRedundancy(Aws::S3::Model::DataRedundancy::SingleAvailabilityZone)); + + cbr.SetCreateBucketConfiguration(bucketConfig); + } else { + bucketName = "perf-standard-" + id; + cbr.SetBucket(bucketName); + } + + auto createOutcome = s3.CreateBucket(cbr); + if (!createOutcome.IsSuccess()) { + std::cerr << "[ERROR] CreateBucket failed for " << bucketName << ": " << createOutcome.GetError().GetMessage() << std::endl; + return false; + } + + Aws::String payload(config.sizeBytes, 'x'); + + // Run PutObject multiple times + for (int i = 0; i < iterations; i++) { + auto stream = Aws::MakeShared("PerfStream"); + *stream << payload; + + Aws::S3::Model::PutObjectRequest por; + por.WithBucket(bucketName).WithKey("test-object-" + std::to_string(i)).SetBody(stream); + if (!s3.PutObject(por).IsSuccess()) { + std::cerr << "[ERROR] PutObject failed!" << std::endl; + } + } + + // Run GetObject multiple times + for (int i = 0; i < iterations; i++) { + Aws::S3::Model::GetObjectRequest gor; + gor.WithBucket(bucketName).WithKey("test-object-" + std::to_string(i)); + if (!s3.GetObject(gor).IsSuccess()) { + std::cerr << "[ERROR] GetObject failed!" << std::endl; + } + } + + for (int i = 0; i < iterations; i++) { + s3.DeleteObject(Aws::S3::Model::DeleteObjectRequest().WithBucket(bucketName).WithKey("test-object-" + std::to_string(i))); + } + s3.DeleteBucket(Aws::S3::Model::DeleteBucketRequest().WithBucket(bucketName)); + + return true; +} \ No newline at end of file diff --git a/tests/performance-tests/src/services/s3/main.cpp b/tests/performance-tests/src/services/s3/main.cpp new file mode 100644 index 00000000000..57c3f7584e2 --- /dev/null +++ b/tests/performance-tests/src/services/s3/main.cpp @@ -0,0 +1,63 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "performance_tests/reporting/JsonReportingMetrics.h" +#include "performance_tests/services/s3/S3PerformanceTest.h" +#include "performance_tests/services/s3/S3TestConfig.h" + +int main(int argc, char** argv) { + Aws::String region = "us-east-1"; + Aws::String availabilityZoneId = "use1-az4"; + Aws::String commitId = "unknown"; + int iterations = 3; + + for (int i = 1; i < argc; ++i) { + Aws::String arg = argv[i]; + if (arg == "--region" && i + 1 < argc) { + region = argv[++i]; + } else if (arg == "--az-id" && i + 1 < argc) { + availabilityZoneId = argv[++i]; + } else if (arg == "--iterations" && i + 1 < argc) { + iterations = std::stoi(argv[++i]); + } else if (arg == "--commit-id" && i + 1 < argc) { + commitId = argv[++i]; + } + } + + Aws::SDKOptions options; + options.monitoringOptions.customizedMonitoringFactory_create_fn.push_back( + []() { return Aws::MakeUnique("JsonReportingMetricsFactory"); }); + + Aws::InitAPI(options); + + PerformanceTest::Reporting::JsonReportingMetrics::RegisterOperationsToMonitor(PerformanceTest::Services::S3::TestConfig::OPERATIONS); + + Aws::SDKOptions::SDKVersion version; + Aws::String versionStr = std::to_string(version.major) + "." + std::to_string(version.minor) + "." + std::to_string(version.patch); + PerformanceTest::Reporting::JsonReportingMetrics::SetProductInfo("cpp1", versionStr, commitId); + PerformanceTest::Reporting::JsonReportingMetrics::SetOutputFilename("s3-perf-results.json"); + + { + Aws::Client::ClientConfiguration cfg; + cfg.region = region; + + Aws::S3::S3Client s3(cfg); + for (const auto& config : PerformanceTest::Services::S3::TestConfig::TEST_MATRIX) { + PerformanceTest::Services::S3::RunTest(s3, config, availabilityZoneId, iterations); + } + } + + Aws::ShutdownAPI(options); + return 0; +} \ No newline at end of file diff --git a/tests/performance_tests/CMakeLists.txt b/tests/performance_tests/CMakeLists.txt deleted file mode 100644 index 4a7eef69319..00000000000 --- a/tests/performance_tests/CMakeLists.txt +++ /dev/null @@ -1,44 +0,0 @@ -cmake_minimum_required(VERSION 3.13) - -include(FetchContent) - -FetchContent_Declare( - nlohmann_json - URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz -) -FetchContent_MakeAvailable(nlohmann_json) - -add_project(performance_tests - "A suite of simple AWS C++ SDK performance tests" - aws-cpp-sdk-core - aws-cpp-sdk-s3 -) - -add_library(json_metrics STATIC - reporting/JsonReportingMetrics.cpp - reporting/JsonReportingMetrics.h -) - -target_include_directories(json_metrics PUBLIC - "${CMAKE_CURRENT_SOURCE_DIR}/reporting" -) - -target_link_libraries(json_metrics - PUBLIC - aws-cpp-sdk-core - nlohmann_json::nlohmann_json -) - -# Define the S3 performance test executable -add_executable(s3_performance_test - s3/S3PerformanceTest.cpp -) - -set_compiler_flags(s3_performance_test) -set_compiler_warnings(s3_performance_test) - -target_link_libraries(s3_performance_test - PRIVATE - ${PROJECT_LIBS} - json_metrics -) \ No newline at end of file diff --git a/tests/performance_tests/reporting/JsonReportingMetrics.cpp b/tests/performance_tests/reporting/JsonReportingMetrics.cpp deleted file mode 100644 index 42a5484e985..00000000000 --- a/tests/performance_tests/reporting/JsonReportingMetrics.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ - -#include "JsonReportingMetrics.h" - -#include -#include -#include - -#include -#include - -Aws::String JsonReportingMetrics::m_testSize = ""; -Aws::String JsonReportingMetrics::m_testBucketType = ""; - -void JsonReportingMetrics::SetTestContext(const Aws::String& size, const Aws::String& bucketType) { - m_testSize = size; - m_testBucketType = bucketType; -} - -JsonReportingMetrics::~JsonReportingMetrics() { DumpJson(); } - -JsonReportingMetricsFactory::~JsonReportingMetricsFactory() {} - -Aws::UniquePtr JsonReportingMetricsFactory::CreateMonitoringInstance() const { - return Aws::MakeUnique("JsonReportingMetrics"); -} - -void JsonReportingMetrics::AddMetric(const Aws::String& serviceName, const Aws::String& requestName, - const Aws::Monitoring::CoreMetricsCollection& metricsFromCore) const { - if (requestName != "PutObject" && requestName != "GetObject") { - return; - } - - std::lock_guard lock(m_mutex); - - double durationMs = 0.0; - Aws::String latencyKey = Aws::Monitoring::GetHttpClientMetricNameByType(Aws::Monitoring::HttpClientMetricsType::RequestLatency); - - auto it = metricsFromCore.httpClientMetrics.find(latencyKey); - if (it != metricsFromCore.httpClientMetrics.end()) { - durationMs = static_cast(it->second); - } - - RequestMetric metric; - metric.name = - Aws::Utils::StringUtils::ToLower(serviceName.c_str()) + "." + Aws::Utils::StringUtils::ToLower(requestName.c_str()) + ".latency"; - metric.description = "Time to complete " + requestName + " operation"; - metric.unit = "Milliseconds"; - metric.date = Aws::Utils::DateTime::CurrentTimeMillis() / 1000; - metric.measurements.push_back(durationMs); - - if (!m_testSize.empty()) { - metric.dimensions.push_back(std::make_pair("Size", m_testSize)); - } - if (!m_testBucketType.empty()) { - metric.dimensions.push_back(std::make_pair("BucketType", m_testBucketType)); - } - - metric.publishToCloudWatch = true; - m_metrics.push_back(metric); -} - -void* JsonReportingMetrics::OnRequestStarted(const Aws::String&, const Aws::String&, - const std::shared_ptr&) const { - return nullptr; -} - -void JsonReportingMetrics::OnRequestSucceeded(const Aws::String& serviceName, const Aws::String& requestName, - const std::shared_ptr&, const Aws::Client::HttpResponseOutcome&, - const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void*) const { - AddMetric(serviceName, requestName, metricsFromCore); -} - -void JsonReportingMetrics::OnRequestFailed(const Aws::String& serviceName, const Aws::String& requestName, - const std::shared_ptr&, const Aws::Client::HttpResponseOutcome&, - const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void*) const { - AddMetric(serviceName, requestName, metricsFromCore); -} - -void JsonReportingMetrics::OnRequestRetry(const Aws::String&, const Aws::String&, const std::shared_ptr&, - void*) const {} - -void JsonReportingMetrics::OnFinish(const Aws::String&, const Aws::String&, const std::shared_ptr&, - void*) const {} - - -void JsonReportingMetrics::DumpJson() const { - std::lock_guard lock(m_mutex); - - if (m_metrics.empty()) { - return; - } - - Aws::Utils::Json::JsonValue root; - root.WithString("productId", "AWS SDK for C++"); - root.WithString("sdkVersion", "1.0.0"); - root.WithString("commitId", "unknown"); - - Aws::Utils::Array results(m_metrics.size()); - for (size_t i = 0; i < m_metrics.size(); ++i) { - Aws::Utils::Json::JsonValue metric; - metric.WithString("name", m_metrics[i].name); - metric.WithString("description", m_metrics[i].description); - metric.WithString("unit", m_metrics[i].unit); - metric.WithInt64("date", m_metrics[i].date); - - if (!m_metrics[i].dimensions.empty()) { - Aws::Utils::Array dimensionsArray(m_metrics[i].dimensions.size()); - for (size_t j = 0; j < m_metrics[i].dimensions.size(); ++j) { - Aws::Utils::Json::JsonValue dimension; - dimension.WithString("name", m_metrics[i].dimensions[j].first); - dimension.WithString("value", m_metrics[i].dimensions[j].second); - dimensionsArray[j] = std::move(dimension); - } - metric.WithArray("dimensions", std::move(dimensionsArray)); - } - - Aws::Utils::Array measurementsArray(m_metrics[i].measurements.size()); - for (size_t j = 0; j < m_metrics[i].measurements.size(); ++j) { - Aws::Utils::Json::JsonValue measurementValue; - measurementValue.AsDouble(m_metrics[i].measurements[j]); - measurementsArray[j] = std::move(measurementValue); - } - metric.WithArray("measurements", std::move(measurementsArray)); - - results[i] = std::move(metric); - } - root.WithArray("results", std::move(results)); - - std::cout << root.View().WriteReadable() << std::endl; - - std::ofstream outFile("perf-results.json"); - if (outFile.is_open()) { - outFile << root.View().WriteReadable(); - } -} \ No newline at end of file diff --git a/tests/performance_tests/reporting/JsonReportingMetrics.h b/tests/performance_tests/reporting/JsonReportingMetrics.h deleted file mode 100644 index 7a335567a26..00000000000 --- a/tests/performance_tests/reporting/JsonReportingMetrics.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/** - * @brief A data structure to hold the details of a single performance metric. - */ -struct RequestMetric { - Aws::String name; - Aws::String description; - Aws::String unit; - int64_t date; - Aws::Vector measurements; - Aws::Vector> dimensions; - bool publishToCloudWatch; -}; - -/** - * @brief An implementation of the MonitoringInterface that collects performance metrics - * and reports them in a JSON format. - */ -class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { - public: - ~JsonReportingMetrics() override; - - void* OnRequestStarted(const Aws::String&, const Aws::String&, const std::shared_ptr&) const override; - void OnRequestSucceeded(const Aws::String&, const Aws::String&, const std::shared_ptr&, - const Aws::Client::HttpResponseOutcome&, const Aws::Monitoring::CoreMetricsCollection&, void*) const override; - void OnRequestFailed(const Aws::String&, const Aws::String&, const std::shared_ptr&, - const Aws::Client::HttpResponseOutcome&, const Aws::Monitoring::CoreMetricsCollection&, void*) const override; - void OnRequestRetry(const Aws::String&, const Aws::String&, const std::shared_ptr&, void*) const override; - void OnFinish(const Aws::String&, const Aws::String&, const std::shared_ptr&, void*) const override; - - /** - * @brief Sets the test-wide context to be added as dimensions to subsequently collected metrics. - * This serves as a communication channel between the main test runner and the monitoring instance. - * @param size A string label for the object size being tested (e.g., "64KB"). - * @param bucketType A string label for the bucket type being tested (e.g., "s3-standard"). - */ - static void SetTestContext(const Aws::String& size, const Aws::String& bucketType); - - private: - void AddMetric(const Aws::String& serviceName, const Aws::String& requestName, - const Aws::Monitoring::CoreMetricsCollection& metricsFromCore) const; - void DumpJson() const; - - mutable std::mutex m_mutex; - mutable Aws::Vector m_metrics; - - static Aws::String m_testSize; - static Aws::String m_testBucketType; -}; - -/** - * @brief A factory for creating instances of JsonReportingMetrics. - */ -class JsonReportingMetricsFactory : public Aws::Monitoring::MonitoringFactory { - public: - ~JsonReportingMetricsFactory() override; - Aws::UniquePtr CreateMonitoringInstance() const override; -}; \ No newline at end of file diff --git a/tests/performance_tests/s3/S3PerformanceTest.cpp b/tests/performance_tests/s3/S3PerformanceTest.cpp deleted file mode 100644 index 4c524323247..00000000000 --- a/tests/performance_tests/s3/S3PerformanceTest.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "JsonReportingMetrics.h" - -// Defines the configuration for a single S3 performance test case. -struct TestConfig { - Aws::String sizeLabel; - size_t sizeBytes; - Aws::String bucketTypeLabel; -}; - -// Executes a single end-to-end S3 performance test scenario, including resource creation and cleanup. -// @param s3 An initialized S3Client instance. -// @param config The configuration for the test run, including object size and bucket type. -// @param availabilityZoneId The specific AZ required for S3 Express One Zone buckets. -// @return True if the test scenario completes successfully, false otherwise. -bool RunSingleTest(Aws::S3::S3Client& s3, const TestConfig& config, const Aws::String& availabilityZoneId) { - std::cout << "\n--- Running Test: Size=" << config.sizeLabel << ", BucketType=" << config.bucketTypeLabel << " ---\n"; - JsonReportingMetrics::SetTestContext(config.sizeLabel, config.bucketTypeLabel); - - Aws::String bucketName; - Aws::S3::Model::CreateBucketRequest cbr; - Aws::String raw_uuid = static_cast(Aws::Utils::UUID::RandomUUID()); - Aws::String id = Aws::Utils::StringUtils::ToLower(raw_uuid.c_str()).substr(0, 8); - - if (config.bucketTypeLabel == "s3-express") { - bucketName = "perf-express-" + id + "--" + availabilityZoneId + "--x-s3"; - cbr.SetBucket(bucketName); - Aws::S3::Model::CreateBucketConfiguration bucketConfig; - bucketConfig.SetLocation( - Aws::S3::Model::LocationInfo().WithType(Aws::S3::Model::LocationType::AvailabilityZone).WithName(availabilityZoneId)); - - bucketConfig.SetBucket(Aws::S3::Model::BucketInfo() - .WithType(Aws::S3::Model::BucketType::Directory) - .WithDataRedundancy(Aws::S3::Model::DataRedundancy::SingleAvailabilityZone)); - - cbr.SetCreateBucketConfiguration(bucketConfig); - } else { - bucketName = "perf-standard-" + id; - cbr.SetBucket(bucketName); - } - - auto createOutcome = s3.CreateBucket(cbr); - if (!createOutcome.IsSuccess()) { - std::cerr << "[ERROR] CreateBucket failed for " << bucketName << ": " << createOutcome.GetError().GetMessage() << std::endl; - return false; - } - std::cout << "Bucket created: " << bucketName << std::endl; - - Aws::String payload(config.sizeBytes, 'x'); - auto stream = Aws::MakeShared("PerfStream"); - *stream << payload; - - Aws::S3::Model::PutObjectRequest por; - por.WithBucket(bucketName).WithKey("test-object").SetBody(stream); - if (!s3.PutObject(por).IsSuccess()) { - std::cerr << "[ERROR] PutObject failed!" << std::endl; - } else { - std::cout << "Uploaded " << config.sizeLabel << std::endl; - } - - Aws::S3::Model::GetObjectRequest gor; - gor.WithBucket(bucketName).WithKey("test-object"); - if (!s3.GetObject(gor).IsSuccess()) { - std::cerr << "[ERROR] GetObject failed!" << std::endl; - } else { - std::cout << "Downloaded " << config.sizeLabel << std::endl; - } - - s3.DeleteObject(Aws::S3::Model::DeleteObjectRequest().WithBucket(bucketName).WithKey("test-object")); - s3.DeleteBucket(Aws::S3::Model::DeleteBucketRequest().WithBucket(bucketName)); - std::cout << "Cleaned up." << std::endl; - - return true; -} - -// The program runs a matrix of tests and outputs performance metrics to a JSON file. -int main(int argc, char** argv) { - Aws::String region = "us-east-1"; - Aws::String availabilityZoneId = "use1-az4"; - - for (int i = 1; i < argc; ++i) { - Aws::String arg = argv[i]; - if (arg == "--region" && i + 1 < argc) { - region = argv[++i]; - } - if (arg == "--az-id" && i + 1 < argc) { - availabilityZoneId = argv[++i]; - } - } - - Aws::Vector testMatrix = {{"8KB", 8 * 1024, "s3-standard"}, {"64KB", 64 * 1024, "s3-standard"}, - {"1MB", 1024 * 1024, "s3-standard"}, {"8KB", 8 * 1024, "s3-express"}, - {"64KB", 64 * 1024, "s3-express"}, {"1MB", 1024 * 1024, "s3-express"}}; - - Aws::SDKOptions options; - - options.monitoringOptions.customizedMonitoringFactory_create_fn.push_back( - []() { return Aws::MakeUnique("JsonReportingMetricsFactory"); }); - - Aws::InitAPI(options); - - { - Aws::Client::ClientConfiguration cfg; - cfg.region = region; - Aws::S3::S3Client s3(cfg); - - for (const auto& config : testMatrix) { - RunSingleTest(s3, config, availabilityZoneId); - } - } - - Aws::ShutdownAPI(options); - std::cout << "\nAll tests completed. Results saved to perf-results.json" << std::endl; - return 0; -} \ No newline at end of file From 12796979b9d44af103cf2ed18ba4bfeff6511482 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Sun, 22 Jun 2025 20:53:46 -0400 Subject: [PATCH 10/77] root cmakelist modification --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b1baeada078..e22f1aa9d9f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -344,7 +344,7 @@ if (LEGACY_BUILD) #Performance tests (under tests/performance_tests) option(BUILD_PERFORMANCE_TESTS "Build AWS C++ performance tests" OFF) if(BUILD_PERFORMANCE_TESTS) - add_subdirectory(tests/performance_tests) + add_subdirectory(tests/performance-tests) endif() From a608cfa2513f07c9297e901b33548f8269ce660c Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Mon, 23 Jun 2025 00:47:43 -0400 Subject: [PATCH 11/77] code formatting --- .../reporting/JsonReportingMetrics.h | 22 +++++---- .../services/dynamodb/DynamoDBTestConfig.h | 2 - .../services/s3/S3TestConfig.h | 2 - .../src/reporting/JsonReportingMetrics.cpp | 36 ++++++++------- .../dynamodb/DynamoDBPerformanceTest.cpp | 46 +++++++++++++------ .../src/services/dynamodb/main.cpp | 16 +++---- .../src/services/s3/S3PerformanceTest.cpp | 28 +++++------ .../src/services/s3/main.cpp | 16 +++---- 8 files changed, 95 insertions(+), 73 deletions(-) diff --git a/tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h b/tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h index 5fbb2ae1b24..49f71df0fab 100644 --- a/tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h +++ b/tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h @@ -5,6 +5,7 @@ #pragma once +#include #include #include #include @@ -15,6 +16,7 @@ #include #include +#include #include namespace PerformanceTest { @@ -29,7 +31,6 @@ struct PerformanceMetricRecord { int64_t date; Aws::Vector measurements; Aws::Vector> dimensions; - }; /** @@ -40,13 +41,18 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { public: ~JsonReportingMetrics() override; - void* OnRequestStarted(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request) const override; - void OnRequestSucceeded(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request, - const Aws::Client::HttpResponseOutcome& outcome, const Aws::Monitoring::CoreMetricsCollection& metrics, void* context) const override; - void OnRequestFailed(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request, - const Aws::Client::HttpResponseOutcome& outcome, const Aws::Monitoring::CoreMetricsCollection& metrics, void* context) const override; - void OnRequestRetry(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request, void* context) const override; - void OnFinish(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request, void* context) const override; + void* OnRequestStarted(const Aws::String& serviceName, const Aws::String& requestName, + const std::shared_ptr& request) const override; + void OnRequestSucceeded(const Aws::String& serviceName, const Aws::String& requestName, + const std::shared_ptr& request, const Aws::Client::HttpResponseOutcome& outcome, + const Aws::Monitoring::CoreMetricsCollection& metrics, void* context) const override; + void OnRequestFailed(const Aws::String& serviceName, const Aws::String& requestName, + const std::shared_ptr& request, const Aws::Client::HttpResponseOutcome& outcome, + const Aws::Monitoring::CoreMetricsCollection& metrics, void* context) const override; + void OnRequestRetry(const Aws::String& serviceName, const Aws::String& requestName, + const std::shared_ptr& request, void* context) const override; + void OnFinish(const Aws::String& serviceName, const Aws::String& requestName, + const std::shared_ptr& request, void* context) const override; static void SetTestContext(const Aws::Vector>& dimensions); diff --git a/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBTestConfig.h b/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBTestConfig.h index 80260fef580..3ed51e50127 100644 --- a/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBTestConfig.h +++ b/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBTestConfig.h @@ -8,8 +8,6 @@ #include #include -#include "performance_tests/services/dynamodb/DynamoDBPerformanceTest.h" - namespace PerformanceTest { namespace Services { namespace DynamoDB { diff --git a/tests/performance-tests/include/performance_tests/services/s3/S3TestConfig.h b/tests/performance-tests/include/performance_tests/services/s3/S3TestConfig.h index fa58b009937..9823758dde6 100644 --- a/tests/performance-tests/include/performance_tests/services/s3/S3TestConfig.h +++ b/tests/performance-tests/include/performance_tests/services/s3/S3TestConfig.h @@ -8,8 +8,6 @@ #include #include -#include "performance_tests/services/s3/S3PerformanceTest.h" - namespace PerformanceTest { namespace Services { namespace S3 { diff --git a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp index 988a49c548a..2e8609aad40 100644 --- a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp +++ b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp @@ -3,20 +3,24 @@ * SPDX-License-Identifier: Apache-2.0. */ -#include "performance_tests/reporting/JsonReportingMetrics.h" - +#include +#include +#include +#include +#include #include #include #include #include +#include #include #include #include +#include #include #include -#include -#include +#include #include using namespace PerformanceTest::Reporting; @@ -34,8 +38,8 @@ void JsonReportingMetrics::SetTestContext(const Aws::Vector& operations) { m_monitoredOperations.clear(); - for (const auto& op : operations) { - m_monitoredOperations.insert(op); + for (const auto& operation : operations) { + m_monitoredOperations.insert(operation); } } @@ -49,7 +53,7 @@ void JsonReportingMetrics::SetOutputFilename(const Aws::String& filename) { m_ou JsonReportingMetrics::~JsonReportingMetrics() { DumpJson(); } -JsonReportingMetricsFactory::~JsonReportingMetricsFactory() {} +JsonReportingMetricsFactory::~JsonReportingMetricsFactory() = default; auto JsonReportingMetricsFactory::CreateMonitoringInstance() const -> Aws::UniquePtr { return Aws::MakeUnique("JsonReportingMetrics"); @@ -64,11 +68,11 @@ void JsonReportingMetrics::AddPerformanceRecord(const Aws::String& serviceName, } double durationMs = 0.0; - Aws::String latencyKey = Aws::Monitoring::GetHttpClientMetricNameByType(Aws::Monitoring::HttpClientMetricsType::RequestLatency); + Aws::String const latencyKey = Aws::Monitoring::GetHttpClientMetricNameByType(Aws::Monitoring::HttpClientMetricsType::RequestLatency); - auto it = metricsFromCore.httpClientMetrics.find(latencyKey); - if (it != metricsFromCore.httpClientMetrics.end()) { - durationMs = static_cast(it->second); + auto iterator = metricsFromCore.httpClientMetrics.find(latencyKey); + if (iterator != metricsFromCore.httpClientMetrics.end()) { + durationMs = static_cast(iterator->second); } PerformanceMetricRecord record; @@ -83,8 +87,8 @@ void JsonReportingMetrics::AddPerformanceRecord(const Aws::String& serviceName, m_performanceRecords.push_back(record); } -void* JsonReportingMetrics::OnRequestStarted(const Aws::String& serviceName, const Aws::String& requestName, - const std::shared_ptr& request) const { +void* JsonReportingMetrics::OnRequestStarted(const Aws::String&, const Aws::String&, + const std::shared_ptr&) const { return nullptr; } @@ -112,12 +116,12 @@ void JsonReportingMetrics::DumpJson() const { } // Group performance records by name and dimensions - std::map aggregatedRecords; + Aws::Map aggregatedRecords; for (const auto& record : m_performanceRecords) { - std::string key = record.name.c_str(); + Aws::String key = record.name; for (const auto& dim : record.dimensions) { - key += ":" + std::string(dim.first.c_str()) + "=" + std::string(dim.second.c_str()); + key += ":" + Aws::String(dim.first) + "=" + Aws::String(dim.second); } if (aggregatedRecords.find(key) == aggregatedRecords.end()) { diff --git a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp index a025039bf4c..9177d114317 100644 --- a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp +++ b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp @@ -3,18 +3,26 @@ * SPDX-License-Identifier: Apache-2.0. */ -#include "performance_tests/services/dynamodb/DynamoDBPerformanceTest.h" - #include #include #include #include #include #include +#include +#include +#include #include #include +#include +#include #include +#include +#include #include +#include +#include +#include #include #include @@ -22,17 +30,15 @@ #include #include -#include "performance_tests/reporting/JsonReportingMetrics.h" - bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& dynamodb, const TestCase& config, int iterations) { Aws::Vector> dimensions; - dimensions.push_back(std::make_pair("Size", config.sizeLabel)); + dimensions.emplace_back("Size", config.sizeLabel); PerformanceTest::Reporting::JsonReportingMetrics::SetTestContext(dimensions); Aws::String tableName; - Aws::String raw_uuid = static_cast(Aws::Utils::UUID::RandomUUID()); - Aws::String id = Aws::Utils::StringUtils::ToLower(raw_uuid.c_str()).substr(0, 8); - tableName = "perf-table-" + id; + Aws::String const rawUUID = static_cast(Aws::Utils::UUID::RandomUUID()); + Aws::String const tableId = Aws::Utils::StringUtils::ToLower(rawUUID.c_str()).substr(0, 8); + tableName = "perf-table-" + tableId; Aws::DynamoDB::Model::CreateTableRequest createTableRequest; createTableRequest.SetTableName(tableName); @@ -46,18 +52,30 @@ bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& keySchema.WithAttributeName("id").WithKeyType(Aws::DynamoDB::Model::KeyType::HASH); createTableRequest.AddKeySchema(keySchema); - Aws::DynamoDB::Model::BillingMode billingMode = Aws::DynamoDB::Model::BillingMode::PAY_PER_REQUEST; + Aws::DynamoDB::Model::BillingMode const billingMode = Aws::DynamoDB::Model::BillingMode::PAY_PER_REQUEST; createTableRequest.SetBillingMode(billingMode); auto createTableOutcome = dynamodb.CreateTable(createTableRequest); if (!createTableOutcome.IsSuccess()) { - std::cerr << "[ERROR] CreateTable failed: " << createTableOutcome.GetError().GetMessage() << std::endl; + std::cerr << "[ERROR] CreateTable failed: " << createTableOutcome.GetError().GetMessage() << '\n'; return false; } // Wait for table to become active - std::this_thread::sleep_for(std::chrono::seconds(10)); - Aws::String payload(config.sizeBytes, 'x'); + Aws::DynamoDB::Model::DescribeTableRequest describeRequest; + describeRequest.SetTableName(tableName); + + while (true) { + auto describeOutcome = dynamodb.DescribeTable(describeRequest); + if (describeOutcome.IsSuccess()) { + auto status = describeOutcome.GetResult().GetTable().GetTableStatus(); + if (status == Aws::DynamoDB::Model::TableStatus::ACTIVE) { + break; + } + } + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + Aws::String const payload(config.sizeBytes, 'x'); // Run PutItem multiple times for (int i = 0; i < iterations; i++) { @@ -71,7 +89,7 @@ bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& auto putItemOutcome = dynamodb.PutItem(putItemRequest); if (!putItemOutcome.IsSuccess()) { - std::cerr << "[ERROR] PutItem failed: " << putItemOutcome.GetError().GetMessage() << std::endl; + std::cerr << "[ERROR] PutItem failed: " << putItemOutcome.GetError().GetMessage() << '\n'; } } @@ -86,7 +104,7 @@ bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& auto getItemOutcome = dynamodb.GetItem(getItemRequest); if (!getItemOutcome.IsSuccess()) { - std::cerr << "[ERROR] GetItem failed: " << getItemOutcome.GetError().GetMessage() << std::endl; + std::cerr << "[ERROR] GetItem failed: " << getItemOutcome.GetError().GetMessage() << '\n'; } } diff --git a/tests/performance-tests/src/services/dynamodb/main.cpp b/tests/performance-tests/src/services/dynamodb/main.cpp index f320186aa3e..4c52e7ae5cd 100644 --- a/tests/performance-tests/src/services/dynamodb/main.cpp +++ b/tests/performance-tests/src/services/dynamodb/main.cpp @@ -8,21 +8,19 @@ #include #include #include +#include +#include +#include -#include #include -#include "performance_tests/reporting/JsonReportingMetrics.h" -#include "performance_tests/services/dynamodb/DynamoDBPerformanceTest.h" -#include "performance_tests/services/dynamodb/DynamoDBTestConfig.h" - int main(int argc, char** argv) { Aws::String region = "us-east-1"; Aws::String commitId = "unknown"; int iterations = 3; for (int i = 1; i < argc; ++i) { - Aws::String arg = argv[i]; + Aws::String const arg = argv[i]; if (arg == "--region" && i + 1 < argc) { region = argv[++i]; } else if (arg == "--iterations" && i + 1 < argc) { @@ -33,7 +31,7 @@ int main(int argc, char** argv) { } Aws::SDKOptions options; - options.monitoringOptions.customizedMonitoringFactory_create_fn.push_back( + options.monitoringOptions.customizedMonitoringFactory_create_fn.emplace_back( []() { return Aws::MakeUnique("JsonReportingMetricsFactory"); }); Aws::InitAPI(options); @@ -41,8 +39,8 @@ int main(int argc, char** argv) { PerformanceTest::Reporting::JsonReportingMetrics::RegisterOperationsToMonitor( PerformanceTest::Services::DynamoDB::TestConfig::OPERATIONS); - Aws::SDKOptions::SDKVersion version; - Aws::String versionStr = std::to_string(version.major) + "." + std::to_string(version.minor) + "." + std::to_string(version.patch); + Aws::SDKOptions::SDKVersion const version; + Aws::String const versionStr = std::to_string(version.major) + "." + std::to_string(version.minor) + "." + std::to_string(version.patch); PerformanceTest::Reporting::JsonReportingMetrics::SetProductInfo("cpp1", versionStr, commitId); PerformanceTest::Reporting::JsonReportingMetrics::SetOutputFilename("dynamodb-perf-results.json"); diff --git a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp index d0ffa54b8e5..7adbe884e21 100644 --- a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp +++ b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp @@ -7,39 +7,41 @@ #include #include -#include +#include #include #include #include #include #include +#include +#include #include #include #include #include #include +#include #include +#include #include #include #include -#include "performance_tests/reporting/JsonReportingMetrics.h" - bool PerformanceTest::Services::S3::RunTest(Aws::S3::S3Client& s3, const TestCase& config, const Aws::String& availabilityZoneId, int iterations) { Aws::Vector> dimensions; - dimensions.push_back(std::make_pair("Size", config.sizeLabel)); - dimensions.push_back(std::make_pair("BucketType", config.bucketTypeLabel)); + dimensions.emplace_back("Size", config.sizeLabel); + dimensions.emplace_back("BucketType", config.bucketTypeLabel); PerformanceTest::Reporting::JsonReportingMetrics::SetTestContext(dimensions); Aws::String bucketName; Aws::S3::Model::CreateBucketRequest cbr; - Aws::String raw_uuid = static_cast(Aws::Utils::UUID::RandomUUID()); - Aws::String id = Aws::Utils::StringUtils::ToLower(raw_uuid.c_str()).substr(0, 8); + Aws::String const rawUUID = static_cast(Aws::Utils::UUID::RandomUUID()); + Aws::String const bucketId = Aws::Utils::StringUtils::ToLower(rawUUID.c_str()).substr(0, 8); if (config.bucketTypeLabel == "s3-express") { - bucketName = "perf-express-" + id + "--" + availabilityZoneId + "--x-s3"; + bucketName = "perf-express-" + bucketId + "--" + availabilityZoneId + "--x-s3"; cbr.SetBucket(bucketName); Aws::S3::Model::CreateBucketConfiguration bucketConfig; bucketConfig.SetLocation( @@ -51,17 +53,17 @@ bool PerformanceTest::Services::S3::RunTest(Aws::S3::S3Client& s3, const TestCas cbr.SetCreateBucketConfiguration(bucketConfig); } else { - bucketName = "perf-standard-" + id; + bucketName = "perf-standard-" + bucketId; cbr.SetBucket(bucketName); } auto createOutcome = s3.CreateBucket(cbr); if (!createOutcome.IsSuccess()) { - std::cerr << "[ERROR] CreateBucket failed for " << bucketName << ": " << createOutcome.GetError().GetMessage() << std::endl; + std::cerr << "[ERROR] CreateBucket failed for " << bucketName << ": " << createOutcome.GetError().GetMessage() << '\n'; return false; } - Aws::String payload(config.sizeBytes, 'x'); + Aws::String const payload(config.sizeBytes, 'x'); // Run PutObject multiple times for (int i = 0; i < iterations; i++) { @@ -71,7 +73,7 @@ bool PerformanceTest::Services::S3::RunTest(Aws::S3::S3Client& s3, const TestCas Aws::S3::Model::PutObjectRequest por; por.WithBucket(bucketName).WithKey("test-object-" + std::to_string(i)).SetBody(stream); if (!s3.PutObject(por).IsSuccess()) { - std::cerr << "[ERROR] PutObject failed!" << std::endl; + std::cerr << "[ERROR] PutObject failed!" << '\n'; } } @@ -80,7 +82,7 @@ bool PerformanceTest::Services::S3::RunTest(Aws::S3::S3Client& s3, const TestCas Aws::S3::Model::GetObjectRequest gor; gor.WithBucket(bucketName).WithKey("test-object-" + std::to_string(i)); if (!s3.GetObject(gor).IsSuccess()) { - std::cerr << "[ERROR] GetObject failed!" << std::endl; + std::cerr << "[ERROR] GetObject failed!" << '\n'; } } diff --git a/tests/performance-tests/src/services/s3/main.cpp b/tests/performance-tests/src/services/s3/main.cpp index 57c3f7584e2..c134c11bf73 100644 --- a/tests/performance-tests/src/services/s3/main.cpp +++ b/tests/performance-tests/src/services/s3/main.cpp @@ -8,14 +8,12 @@ #include #include #include +#include +#include +#include -#include #include -#include "performance_tests/reporting/JsonReportingMetrics.h" -#include "performance_tests/services/s3/S3PerformanceTest.h" -#include "performance_tests/services/s3/S3TestConfig.h" - int main(int argc, char** argv) { Aws::String region = "us-east-1"; Aws::String availabilityZoneId = "use1-az4"; @@ -23,7 +21,7 @@ int main(int argc, char** argv) { int iterations = 3; for (int i = 1; i < argc; ++i) { - Aws::String arg = argv[i]; + Aws::String const arg = argv[i]; if (arg == "--region" && i + 1 < argc) { region = argv[++i]; } else if (arg == "--az-id" && i + 1 < argc) { @@ -36,15 +34,15 @@ int main(int argc, char** argv) { } Aws::SDKOptions options; - options.monitoringOptions.customizedMonitoringFactory_create_fn.push_back( + options.monitoringOptions.customizedMonitoringFactory_create_fn.emplace_back( []() { return Aws::MakeUnique("JsonReportingMetricsFactory"); }); Aws::InitAPI(options); PerformanceTest::Reporting::JsonReportingMetrics::RegisterOperationsToMonitor(PerformanceTest::Services::S3::TestConfig::OPERATIONS); - Aws::SDKOptions::SDKVersion version; - Aws::String versionStr = std::to_string(version.major) + "." + std::to_string(version.minor) + "." + std::to_string(version.patch); + Aws::SDKOptions::SDKVersion const version; + Aws::String const versionStr = std::to_string(version.major) + "." + std::to_string(version.minor) + "." + std::to_string(version.patch); PerformanceTest::Reporting::JsonReportingMetrics::SetProductInfo("cpp1", versionStr, commitId); PerformanceTest::Reporting::JsonReportingMetrics::SetOutputFilename("s3-perf-results.json"); From 88ee92513ba3f88c69a31f213fcd805982c81876 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Mon, 23 Jun 2025 16:03:37 -0400 Subject: [PATCH 12/77] more code formatting and comments --- .../reporting/JsonReportingMetrics.h | 102 +++++++++++++++--- .../dynamodb/DynamoDBPerformanceTest.h | 11 ++ .../services/dynamodb/DynamoDBTestConfig.h | 6 +- .../services/s3/S3PerformanceTest.h | 12 +++ .../services/s3/S3TestConfig.h | 10 +- .../src/reporting/JsonReportingMetrics.cpp | 54 +++++----- .../dynamodb/DynamoDBPerformanceTest.cpp | 7 +- .../src/services/dynamodb/main.cpp | 14 +-- .../src/services/s3/S3PerformanceTest.cpp | 2 +- .../src/services/s3/main.cpp | 14 +-- 10 files changed, 169 insertions(+), 63 deletions(-) diff --git a/tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h b/tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h index 49f71df0fab..2191c7851a6 100644 --- a/tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h +++ b/tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h @@ -22,68 +22,144 @@ namespace PerformanceTest { namespace Reporting { /** - * @brief Container for a single performance metric record that stores measurement data and associated metadata. + * Container for a single performance metric record that stores measurement data and associated metadata. */ struct PerformanceMetricRecord { Aws::String name; Aws::String description; Aws::String unit; int64_t date; - Aws::Vector measurements; + Aws::Vector measurements; Aws::Vector> dimensions; }; /** - * @brief An implementation of the MonitoringInterface that collects performance metrics + * An implementation of the MonitoringInterface that collects performance metrics * and reports them in a JSON format. */ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { public: ~JsonReportingMetrics() override; + /** + * Called when an AWS request is started. Returns context for tracking. + * @param serviceName Name of the AWS service + * @param requestName Name of the operation + * @param request HTTP request object + * @return Context pointer (always returns nullptr) + */ void* OnRequestStarted(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request) const override; + + /** + * Called when an AWS request succeeds. Records performance metrics. + * @param serviceName Name of the AWS service + * @param requestName Name of the operation + * @param request HTTP request object + * @param outcome HTTP response outcome + * @param metrics Core metrics collection containing latency data + * @param context Request context (unused) + */ void OnRequestSucceeded(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request, const Aws::Client::HttpResponseOutcome& outcome, const Aws::Monitoring::CoreMetricsCollection& metrics, void* context) const override; + + /** + * Called when an AWS request fails. Records performance metrics. + * @param serviceName Name of the AWS service + * @param requestName Name of the operation + * @param request HTTP request object + * @param outcome HTTP response outcome + * @param metrics Core metrics collection containing latency data + * @param context Request context (unused) + */ void OnRequestFailed(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request, const Aws::Client::HttpResponseOutcome& outcome, const Aws::Monitoring::CoreMetricsCollection& metrics, void* context) const override; + + /** + * Called when an AWS request is retried. No action taken. + * @param serviceName Name of the AWS service + * @param requestName Name of the operation + * @param request HTTP request object + * @param context Request context (unused) + */ void OnRequestRetry(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request, void* context) const override; + + /** + * Called when an AWS request finishes. No action taken. + * @param serviceName Name of the AWS service + * @param requestName Name of the operation + * @param request HTTP request object + * @param context Request context (unused) + */ void OnFinish(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request, void* context) const override; + /** + * Sets test dimensions that will be included with all performance records. + * @param dimensions Vector of key-value pairs representing test dimensions (e.g., size, bucket type) + */ static void SetTestContext(const Aws::Vector>& dimensions); + /** + * Registers specific operations to monitor. If empty, all operations are monitored. + * @param operations Vector of operation names to track (e.g., "PutObject", "GetItem") + */ static void RegisterOperationsToMonitor(const Aws::Vector& operations); + /** + * Sets product information to include in the JSON output. + * @param productId Product identifier (e.g., "cpp1") + * @param sdkVersion SDK version string + * @param commitId Git commit identifier + */ static void SetProductInfo(const Aws::String& productId, const Aws::String& sdkVersion, const Aws::String& commitId); + /** + * Sets the output filename for the JSON performance report. + * @param filename Path to output file (e.g., "s3-perf-results.json") + */ static void SetOutputFilename(const Aws::String& filename); private: + /** + * Adds a performance record for a completed AWS service operation. + * @param serviceName Name of the AWS service (e.g., "S3", "DynamoDB") + * @param requestName Name of the operation (e.g., "PutObject", "GetItem") + * @param metricsFromCore Core metrics collection containing latency data + */ void AddPerformanceRecord(const Aws::String& serviceName, const Aws::String& requestName, const Aws::Monitoring::CoreMetricsCollection& metricsFromCore) const; + + /** + * Outputs aggregated performance metrics to JSON file. + * Groups records by name and dimensions, then writes to configured output file. + */ void DumpJson() const; mutable Aws::Vector m_performanceRecords; - - static Aws::Vector> m_testDimensions; - static Aws::Set m_monitoredOperations; - static Aws::String m_productId; - static Aws::String m_sdkVersion; - static Aws::String m_commitId; - static Aws::String m_outputFilename; + static Aws::Vector> TestDimensions; + static Aws::Set MonitoredOperations; + static Aws::String ProductId; + static Aws::String SdkVersion; + static Aws::String CommitId; + static Aws::String OutputFilename; }; /** - * @brief A factory for creating instances of JsonReportingMetrics. + * A factory for creating instances of JsonReportingMetrics. + * Used by the AWS SDK monitoring system to instantiate performance metrics collectors. */ class JsonReportingMetricsFactory : public Aws::Monitoring::MonitoringFactory { public: - ~JsonReportingMetricsFactory() override; - auto CreateMonitoringInstance() const -> Aws::UniquePtr override; + ~JsonReportingMetricsFactory() override = default; + /** + * Creates a new JsonReportingMetrics instance for performance monitoring. + * @return Unique pointer to monitoring interface implementation + */ + Aws::UniquePtr CreateMonitoringInstance() const override; }; } // namespace Reporting } // namespace PerformanceTest \ No newline at end of file diff --git a/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBPerformanceTest.h b/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBPerformanceTest.h index 95c68557e0f..78b02c19ae4 100644 --- a/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBPerformanceTest.h +++ b/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBPerformanceTest.h @@ -13,11 +13,22 @@ namespace PerformanceTest { namespace Services { namespace DynamoDB { +/** + * Configuration for DynamoDB performance test cases. + */ struct TestCase { Aws::String sizeLabel; size_t sizeBytes; }; +/** + * Runs DynamoDB performance test by creating a table, performing PutItem and GetItem operations, + * then cleaning up resources. + * @param dynamodb DynamoDB client instance to use for operations + * @param config Test configuration containing size parameters + * @param iterations Number of put/get operations to perform + * @return true if test completed successfully, false on error + */ bool RunTest(Aws::DynamoDB::DynamoDBClient& dynamodb, const TestCase& config, int iterations = 3); } // namespace DynamoDB } // namespace Services diff --git a/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBTestConfig.h b/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBTestConfig.h index 3ed51e50127..4ca30ab7250 100644 --- a/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBTestConfig.h +++ b/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBTestConfig.h @@ -12,9 +12,11 @@ namespace PerformanceTest { namespace Services { namespace DynamoDB { namespace TestConfig { -const Aws::Vector OPERATIONS = {"PutItem", "GetItem"}; +const Aws::Vector Operations = {"PutItem", "GetItem"}; -const Aws::Vector TEST_MATRIX = {{"8KB", 8 * 1024}, {"64KB", 64 * 1024}, {"392KB", 392 * 1024}}; +const Aws::Vector TestMatrix = {{"8KB", 8 * 1024}, {"64KB", 64 * 1024}, {"392KB", 392 * 1024}}; + +const Aws::String OutputFilename = "dynamodb-performance-test-results.json"; } // namespace TestConfig } // namespace DynamoDB } // namespace Services diff --git a/tests/performance-tests/include/performance_tests/services/s3/S3PerformanceTest.h b/tests/performance-tests/include/performance_tests/services/s3/S3PerformanceTest.h index 256983ce6c4..08452f004ac 100644 --- a/tests/performance-tests/include/performance_tests/services/s3/S3PerformanceTest.h +++ b/tests/performance-tests/include/performance_tests/services/s3/S3PerformanceTest.h @@ -13,12 +13,24 @@ namespace PerformanceTest { namespace Services { namespace S3 { +/** + * Configuration for S3 performance test cases. + */ struct TestCase { Aws::String sizeLabel; size_t sizeBytes; Aws::String bucketTypeLabel; }; +/** + * Runs S3 performance test by creating a bucket, performing PutObject and GetObject operations, + * then cleaning up resources. + * @param s3 S3 client instance to use for operations + * @param config Test configuration containing size and bucket type parameters + * @param availabilityZoneId Availability zone ID for S3 Express buckets + * @param iterations Number of put/get operations to perform + * @return true if test completed successfully, false on error + */ bool RunTest(Aws::S3::S3Client& s3, const TestCase& config, const Aws::String& availabilityZoneId, int iterations = 3); } // namespace S3 } // namespace Services diff --git a/tests/performance-tests/include/performance_tests/services/s3/S3TestConfig.h b/tests/performance-tests/include/performance_tests/services/s3/S3TestConfig.h index 9823758dde6..3c5ce05d910 100644 --- a/tests/performance-tests/include/performance_tests/services/s3/S3TestConfig.h +++ b/tests/performance-tests/include/performance_tests/services/s3/S3TestConfig.h @@ -12,11 +12,13 @@ namespace PerformanceTest { namespace Services { namespace S3 { namespace TestConfig { -const Aws::Vector OPERATIONS = {"PutObject", "GetObject"}; +const Aws::Vector Operations = {"PutObject", "GetObject"}; -const Aws::Vector TEST_MATRIX = {{"8KB", 8 * 1024, "s3-standard"}, {"64KB", 64 * 1024, "s3-standard"}, - {"1MB", 1024 * 1024, "s3-standard"}, {"8KB", 8 * 1024, "s3-express"}, - {"64KB", 64 * 1024, "s3-express"}, {"1MB", 1024 * 1024, "s3-express"}}; +const Aws::Vector TestMatrix = {{"8KB", 8 * 1024, "s3-standard"}, {"64KB", 64 * 1024, "s3-standard"}, + {"1MB", 1024 * 1024, "s3-standard"}, {"8KB", 8 * 1024, "s3-express"}, + {"64KB", 64 * 1024, "s3-express"}, {"1MB", 1024 * 1024, "s3-express"}}; + +const Aws::String OutputFilename = "s3-performance-test-results.json"; } // namespace TestConfig } // namespace S3 } // namespace Services diff --git a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp index 2e8609aad40..d3c2ed2e191 100644 --- a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp +++ b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp @@ -19,60 +19,58 @@ #include #include +#include #include #include #include using namespace PerformanceTest::Reporting; -Aws::Vector> JsonReportingMetrics::m_testDimensions; -Aws::Set JsonReportingMetrics::m_monitoredOperations; -Aws::String JsonReportingMetrics::m_productId = "unknown"; -Aws::String JsonReportingMetrics::m_sdkVersion = "unknown"; -Aws::String JsonReportingMetrics::m_commitId = "unknown"; -Aws::String JsonReportingMetrics::m_outputFilename = "perf-results.json"; +Aws::Vector> JsonReportingMetrics::TestDimensions; +Aws::Set JsonReportingMetrics::MonitoredOperations; +Aws::String JsonReportingMetrics::ProductId = "unknown"; +Aws::String JsonReportingMetrics::SdkVersion = "unknown"; +Aws::String JsonReportingMetrics::CommitId = "unknown"; +Aws::String JsonReportingMetrics::OutputFilename = "performance-test-results.json"; void JsonReportingMetrics::SetTestContext(const Aws::Vector>& dimensions) { - m_testDimensions = dimensions; + TestDimensions = dimensions; } void JsonReportingMetrics::RegisterOperationsToMonitor(const Aws::Vector& operations) { - m_monitoredOperations.clear(); + MonitoredOperations.clear(); for (const auto& operation : operations) { - m_monitoredOperations.insert(operation); + MonitoredOperations.insert(operation); } } void JsonReportingMetrics::SetProductInfo(const Aws::String& productId, const Aws::String& sdkVersion, const Aws::String& commitId) { - m_productId = productId; - m_sdkVersion = sdkVersion; - m_commitId = commitId; + ProductId = productId; + SdkVersion = sdkVersion; + CommitId = commitId; } -void JsonReportingMetrics::SetOutputFilename(const Aws::String& filename) { m_outputFilename = filename; } +void JsonReportingMetrics::SetOutputFilename(const Aws::String& filename) { OutputFilename = filename; } JsonReportingMetrics::~JsonReportingMetrics() { DumpJson(); } -JsonReportingMetricsFactory::~JsonReportingMetricsFactory() = default; - -auto JsonReportingMetricsFactory::CreateMonitoringInstance() const -> Aws::UniquePtr { +Aws::UniquePtr JsonReportingMetricsFactory::CreateMonitoringInstance() const { return Aws::MakeUnique("JsonReportingMetrics"); } void JsonReportingMetrics::AddPerformanceRecord(const Aws::String& serviceName, const Aws::String& requestName, const Aws::Monitoring::CoreMetricsCollection& metricsFromCore) const { - // If no operations are registered, monitor all operations - // Otherwise, only monitor registered operations - if (!m_monitoredOperations.empty() && m_monitoredOperations.find(requestName) == m_monitoredOperations.end()) { + // If no operations are registered, monitor all operations. Otherwise, only monitor registered operations + if (!MonitoredOperations.empty() && MonitoredOperations.find(requestName) == MonitoredOperations.end()) { return; } - double durationMs = 0.0; + int64_t durationMs = 0; Aws::String const latencyKey = Aws::Monitoring::GetHttpClientMetricNameByType(Aws::Monitoring::HttpClientMetricsType::RequestLatency); auto iterator = metricsFromCore.httpClientMetrics.find(latencyKey); if (iterator != metricsFromCore.httpClientMetrics.end()) { - durationMs = static_cast(iterator->second); + durationMs = iterator->second; } PerformanceMetricRecord record; @@ -80,9 +78,9 @@ void JsonReportingMetrics::AddPerformanceRecord(const Aws::String& serviceName, Aws::Utils::StringUtils::ToLower(serviceName.c_str()) + "." + Aws::Utils::StringUtils::ToLower(requestName.c_str()) + ".latency"; record.description = "Time to complete " + requestName + " operation"; record.unit = "Milliseconds"; - record.date = Aws::Utils::DateTime::CurrentTimeMillis() / 1000; + record.date = Aws::Utils::DateTime::Now().Seconds(); record.measurements.push_back(durationMs); - record.dimensions = m_testDimensions; + record.dimensions = TestDimensions; m_performanceRecords.push_back(record); } @@ -135,9 +133,9 @@ void JsonReportingMetrics::DumpJson() const { // Create the JSON output Aws::Utils::Json::JsonValue root; - root.WithString("productId", m_productId); - root.WithString("sdkVersion", m_sdkVersion); - root.WithString("commitId", m_commitId); + root.WithString("productId", ProductId); + root.WithString("sdkVersion", SdkVersion); + root.WithString("commitId", CommitId); Aws::Utils::Array results(aggregatedRecords.size()); size_t index = 0; @@ -164,7 +162,7 @@ void JsonReportingMetrics::DumpJson() const { Aws::Utils::Array measurementsArray(record.measurements.size()); for (size_t j = 0; j < record.measurements.size(); ++j) { Aws::Utils::Json::JsonValue measurementValue; - measurementValue.AsDouble(record.measurements[j]); + measurementValue.AsInt64(record.measurements[j]); measurementsArray[j] = std::move(measurementValue); } jsonMetric.WithArray("measurements", std::move(measurementsArray)); @@ -174,7 +172,7 @@ void JsonReportingMetrics::DumpJson() const { root.WithArray("results", std::move(results)); - std::ofstream outFile(m_outputFilename.c_str()); + std::ofstream outFile(OutputFilename); if (outFile.is_open()) { outFile << root.View().WriteReadable(); } diff --git a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp index 9177d114317..d99ab7b23f3 100644 --- a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp +++ b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp @@ -15,12 +15,12 @@ #include #include #include -#include #include #include #include #include #include +#include #include #include @@ -36,7 +36,7 @@ bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& PerformanceTest::Reporting::JsonReportingMetrics::SetTestContext(dimensions); Aws::String tableName; - Aws::String const rawUUID = static_cast(Aws::Utils::UUID::RandomUUID()); + Aws::String const rawUUID = Aws::Utils::UUID::RandomUUID(); Aws::String const tableId = Aws::Utils::StringUtils::ToLower(rawUUID.c_str()).substr(0, 8); tableName = "perf-table-" + tableId; @@ -64,7 +64,7 @@ bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& // Wait for table to become active Aws::DynamoDB::Model::DescribeTableRequest describeRequest; describeRequest.SetTableName(tableName); - + while (true) { auto describeOutcome = dynamodb.DescribeTable(describeRequest); if (describeOutcome.IsSuccess()) { @@ -75,6 +75,7 @@ bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& } std::this_thread::sleep_for(std::chrono::seconds(1)); } + Aws::String const payload(config.sizeBytes, 'x'); // Run PutItem multiple times diff --git a/tests/performance-tests/src/services/dynamodb/main.cpp b/tests/performance-tests/src/services/dynamodb/main.cpp index 4c52e7ae5cd..88cf988da92 100644 --- a/tests/performance-tests/src/services/dynamodb/main.cpp +++ b/tests/performance-tests/src/services/dynamodb/main.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -17,7 +18,7 @@ int main(int argc, char** argv) { Aws::String region = "us-east-1"; Aws::String commitId = "unknown"; - int iterations = 3; + int iterations = 10; for (int i = 1; i < argc; ++i) { Aws::String const arg = argv[i]; @@ -31,25 +32,26 @@ int main(int argc, char** argv) { } Aws::SDKOptions options; - options.monitoringOptions.customizedMonitoringFactory_create_fn.emplace_back( - []() { return Aws::MakeUnique("JsonReportingMetricsFactory"); }); + options.monitoringOptions.customizedMonitoringFactory_create_fn = {[]() -> Aws::UniquePtr { + return Aws::MakeUnique("JsonReportingMetricsFactory"); + }}; Aws::InitAPI(options); PerformanceTest::Reporting::JsonReportingMetrics::RegisterOperationsToMonitor( - PerformanceTest::Services::DynamoDB::TestConfig::OPERATIONS); + PerformanceTest::Services::DynamoDB::TestConfig::Operations); Aws::SDKOptions::SDKVersion const version; Aws::String const versionStr = std::to_string(version.major) + "." + std::to_string(version.minor) + "." + std::to_string(version.patch); PerformanceTest::Reporting::JsonReportingMetrics::SetProductInfo("cpp1", versionStr, commitId); - PerformanceTest::Reporting::JsonReportingMetrics::SetOutputFilename("dynamodb-perf-results.json"); + PerformanceTest::Reporting::JsonReportingMetrics::SetOutputFilename(PerformanceTest::Services::DynamoDB::TestConfig::OutputFilename); { Aws::Client::ClientConfiguration cfg; cfg.region = region; Aws::DynamoDB::DynamoDBClient dynamodb(cfg); - for (const auto& config : PerformanceTest::Services::DynamoDB::TestConfig::TEST_MATRIX) { + for (const auto& config : PerformanceTest::Services::DynamoDB::TestConfig::TestMatrix) { PerformanceTest::Services::DynamoDB::RunTest(dynamodb, config, iterations); } } diff --git a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp index 7adbe884e21..5f828aa3210 100644 --- a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp +++ b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp @@ -37,7 +37,7 @@ bool PerformanceTest::Services::S3::RunTest(Aws::S3::S3Client& s3, const TestCas Aws::String bucketName; Aws::S3::Model::CreateBucketRequest cbr; - Aws::String const rawUUID = static_cast(Aws::Utils::UUID::RandomUUID()); + Aws::String const rawUUID = Aws::Utils::UUID::RandomUUID(); Aws::String const bucketId = Aws::Utils::StringUtils::ToLower(rawUUID.c_str()).substr(0, 8); if (config.bucketTypeLabel == "s3-express") { diff --git a/tests/performance-tests/src/services/s3/main.cpp b/tests/performance-tests/src/services/s3/main.cpp index c134c11bf73..becb74e3010 100644 --- a/tests/performance-tests/src/services/s3/main.cpp +++ b/tests/performance-tests/src/services/s3/main.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -18,7 +19,7 @@ int main(int argc, char** argv) { Aws::String region = "us-east-1"; Aws::String availabilityZoneId = "use1-az4"; Aws::String commitId = "unknown"; - int iterations = 3; + int iterations = 10; for (int i = 1; i < argc; ++i) { Aws::String const arg = argv[i]; @@ -34,24 +35,25 @@ int main(int argc, char** argv) { } Aws::SDKOptions options; - options.monitoringOptions.customizedMonitoringFactory_create_fn.emplace_back( - []() { return Aws::MakeUnique("JsonReportingMetricsFactory"); }); + options.monitoringOptions.customizedMonitoringFactory_create_fn = {[]() -> Aws::UniquePtr { + return Aws::MakeUnique("JsonReportingMetricsFactory"); + }}; Aws::InitAPI(options); - PerformanceTest::Reporting::JsonReportingMetrics::RegisterOperationsToMonitor(PerformanceTest::Services::S3::TestConfig::OPERATIONS); + PerformanceTest::Reporting::JsonReportingMetrics::RegisterOperationsToMonitor(PerformanceTest::Services::S3::TestConfig::Operations); Aws::SDKOptions::SDKVersion const version; Aws::String const versionStr = std::to_string(version.major) + "." + std::to_string(version.minor) + "." + std::to_string(version.patch); PerformanceTest::Reporting::JsonReportingMetrics::SetProductInfo("cpp1", versionStr, commitId); - PerformanceTest::Reporting::JsonReportingMetrics::SetOutputFilename("s3-perf-results.json"); + PerformanceTest::Reporting::JsonReportingMetrics::SetOutputFilename(PerformanceTest::Services::S3::TestConfig::OutputFilename); { Aws::Client::ClientConfiguration cfg; cfg.region = region; Aws::S3::S3Client s3(cfg); - for (const auto& config : PerformanceTest::Services::S3::TestConfig::TEST_MATRIX) { + for (const auto& config : PerformanceTest::Services::S3::TestConfig::TestMatrix) { PerformanceTest::Services::S3::RunTest(s3, config, availabilityZoneId, iterations); } } From 5d41578d2e9e01a46938134062ce435affbc0b6d Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Mon, 23 Jun 2025 16:10:47 -0400 Subject: [PATCH 13/77] modify build-al2-debug-default to enable performance tests --- tools/scripts/build-tests/build-al2-debug-default.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/scripts/build-tests/build-al2-debug-default.sh b/tools/scripts/build-tests/build-al2-debug-default.sh index 39c63d0f32f..2c923b9841e 100755 --- a/tools/scripts/build-tests/build-al2-debug-default.sh +++ b/tools/scripts/build-tests/build-al2-debug-default.sh @@ -18,6 +18,6 @@ PREFIX_DIR="$1" mkdir "${PREFIX_DIR}/al2-build" mkdir "${PREFIX_DIR}/al2-install" cd "${PREFIX_DIR}/al2-build" -cmake -GNinja ../aws-sdk-cpp -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-ggdb -fsanitize=address" -DMINIMIZE_SIZE=ON -DCMAKE_INSTALL_PREFIX="${PREFIX_DIR}/al2-install" +cmake -GNinja ../aws-sdk-cpp -DCMAKE_BUILD_TYPE=Debug -DBUILD_PERFORMANCE_TESTS=ON -DCMAKE_CXX_FLAGS="-ggdb -fsanitize=address" -DMINIMIZE_SIZE=ON -DCMAKE_INSTALL_PREFIX="${PREFIX_DIR}/al2-install" ninja-build -j $(grep -c ^processor /proc/cpuinfo) ninja-build install From 0a03a20da746b3f03ff58ebaa3468ed593587c02 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Mon, 23 Jun 2025 16:47:21 -0400 Subject: [PATCH 14/77] Fix performance test CMake filename case mismatch --- tests/performance-tests/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/performance-tests/CMakeLists.txt b/tests/performance-tests/CMakeLists.txt index 668abfc5e36..73fd8f496db 100644 --- a/tests/performance-tests/CMakeLists.txt +++ b/tests/performance-tests/CMakeLists.txt @@ -9,11 +9,11 @@ add_project(performance-tests aws-cpp-sdk-dynamodb ) -function(add_service_test SERVICE SDK_LIB) +function(add_service_test SERVICE SDK_LIB PERF_TEST_FILE) add_executable(${SERVICE}-performance-test src/services/${SERVICE}/main.cpp src/reporting/JsonReportingMetrics.cpp - src/services/${SERVICE}/${SERVICE}PerformanceTest.cpp + src/services/${SERVICE}/${PERF_TEST_FILE} ) set_compiler_flags(${SERVICE}-performance-test) set_compiler_warnings(${SERVICE}-performance-test) @@ -21,5 +21,5 @@ function(add_service_test SERVICE SDK_LIB) target_link_libraries(${SERVICE}-performance-test PRIVATE aws-cpp-sdk-core ${SDK_LIB}) endfunction() -add_service_test(s3 aws-cpp-sdk-s3) -add_service_test(dynamodb aws-cpp-sdk-dynamodb) +add_service_test(s3 aws-cpp-sdk-s3 S3PerformanceTest.cpp) +add_service_test(dynamodb aws-cpp-sdk-dynamodb DynamoDBPerformanceTest.cpp) From 6a8652e46fb3680975a83bdb212c0d2082ac8933 Mon Sep 17 00:00:00 2001 From: Alan4506 <62124408+Alan4506@users.noreply.github.com> Date: Mon, 23 Jun 2025 22:06:24 -0400 Subject: [PATCH 15/77] Update build-al2-debug-default.sh --- tools/scripts/build-tests/build-al2-debug-default.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/scripts/build-tests/build-al2-debug-default.sh b/tools/scripts/build-tests/build-al2-debug-default.sh index 2c923b9841e..39c63d0f32f 100755 --- a/tools/scripts/build-tests/build-al2-debug-default.sh +++ b/tools/scripts/build-tests/build-al2-debug-default.sh @@ -18,6 +18,6 @@ PREFIX_DIR="$1" mkdir "${PREFIX_DIR}/al2-build" mkdir "${PREFIX_DIR}/al2-install" cd "${PREFIX_DIR}/al2-build" -cmake -GNinja ../aws-sdk-cpp -DCMAKE_BUILD_TYPE=Debug -DBUILD_PERFORMANCE_TESTS=ON -DCMAKE_CXX_FLAGS="-ggdb -fsanitize=address" -DMINIMIZE_SIZE=ON -DCMAKE_INSTALL_PREFIX="${PREFIX_DIR}/al2-install" +cmake -GNinja ../aws-sdk-cpp -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-ggdb -fsanitize=address" -DMINIMIZE_SIZE=ON -DCMAKE_INSTALL_PREFIX="${PREFIX_DIR}/al2-install" ninja-build -j $(grep -c ^processor /proc/cpuinfo) ninja-build install From 2579e94763518999e32cacc93be16e12cb798919 Mon Sep 17 00:00:00 2001 From: Alan4506 <62124408+Alan4506@users.noreply.github.com> Date: Mon, 23 Jun 2025 22:29:10 -0400 Subject: [PATCH 16/77] Update build-al2-debug-default.sh to enable performance test --- tools/scripts/build-tests/build-al2-debug-default.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/scripts/build-tests/build-al2-debug-default.sh b/tools/scripts/build-tests/build-al2-debug-default.sh index 39c63d0f32f..f3b6408be94 100755 --- a/tools/scripts/build-tests/build-al2-debug-default.sh +++ b/tools/scripts/build-tests/build-al2-debug-default.sh @@ -18,6 +18,6 @@ PREFIX_DIR="$1" mkdir "${PREFIX_DIR}/al2-build" mkdir "${PREFIX_DIR}/al2-install" cd "${PREFIX_DIR}/al2-build" -cmake -GNinja ../aws-sdk-cpp -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-ggdb -fsanitize=address" -DMINIMIZE_SIZE=ON -DCMAKE_INSTALL_PREFIX="${PREFIX_DIR}/al2-install" +cmake -GNinja ../aws-sdk-cpp -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-ggdb -fsanitize=address" -DMINIMIZE_SIZE=ON -DCMAKE_INSTALL_PREFIX="${PREFIX_DIR}/al2-install" -DBUILD_PERFORMANCE_TESTS=ON ninja-build -j $(grep -c ^processor /proc/cpuinfo) ninja-build install From ade5c8f4cf88f43a27e396e5629c1c0a93a09ce2 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Mon, 23 Jun 2025 23:38:14 -0400 Subject: [PATCH 17/77] fix Aws::String error --- .../src/services/dynamodb/DynamoDBPerformanceTest.cpp | 4 ++-- tests/performance-tests/src/services/dynamodb/main.cpp | 2 +- tests/performance-tests/src/services/s3/main.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp index d99ab7b23f3..ef690e8dfd7 100644 --- a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp +++ b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp @@ -84,7 +84,7 @@ bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& putItemRequest.SetTableName(tableName); Aws::Map item; - item["id"].SetS("test-key-" + std::to_string(i)); + item["id"].SetS(Aws::String("test-key-") + Aws::String(std::to_string(i))); item["data"].SetS(payload); putItemRequest.SetItem(item); @@ -100,7 +100,7 @@ bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& getItemRequest.SetTableName(tableName); Aws::Map key; - key["id"].SetS("test-key-" + std::to_string(i)); + key["id"].SetS(Aws::String("test-key-") + Aws::String(std::to_string(i))); getItemRequest.SetKey(key); auto getItemOutcome = dynamodb.GetItem(getItemRequest); diff --git a/tests/performance-tests/src/services/dynamodb/main.cpp b/tests/performance-tests/src/services/dynamodb/main.cpp index 88cf988da92..3b88613e93c 100644 --- a/tests/performance-tests/src/services/dynamodb/main.cpp +++ b/tests/performance-tests/src/services/dynamodb/main.cpp @@ -42,7 +42,7 @@ int main(int argc, char** argv) { PerformanceTest::Services::DynamoDB::TestConfig::Operations); Aws::SDKOptions::SDKVersion const version; - Aws::String const versionStr = std::to_string(version.major) + "." + std::to_string(version.minor) + "." + std::to_string(version.patch); + Aws::String const versionStr = Aws::String(std::to_string(version.major)) + "." + Aws::String(std::to_string(version.minor)) + "." + Aws::String(std::to_string(version.patch)); PerformanceTest::Reporting::JsonReportingMetrics::SetProductInfo("cpp1", versionStr, commitId); PerformanceTest::Reporting::JsonReportingMetrics::SetOutputFilename(PerformanceTest::Services::DynamoDB::TestConfig::OutputFilename); diff --git a/tests/performance-tests/src/services/s3/main.cpp b/tests/performance-tests/src/services/s3/main.cpp index becb74e3010..631fc73ecfb 100644 --- a/tests/performance-tests/src/services/s3/main.cpp +++ b/tests/performance-tests/src/services/s3/main.cpp @@ -44,7 +44,7 @@ int main(int argc, char** argv) { PerformanceTest::Reporting::JsonReportingMetrics::RegisterOperationsToMonitor(PerformanceTest::Services::S3::TestConfig::Operations); Aws::SDKOptions::SDKVersion const version; - Aws::String const versionStr = std::to_string(version.major) + "." + std::to_string(version.minor) + "." + std::to_string(version.patch); + Aws::String const versionStr = Aws::String(std::to_string(version.major)) + "." + Aws::String(std::to_string(version.minor)) + "." + Aws::String(std::to_string(version.patch)); PerformanceTest::Reporting::JsonReportingMetrics::SetProductInfo("cpp1", versionStr, commitId); PerformanceTest::Reporting::JsonReportingMetrics::SetOutputFilename(PerformanceTest::Services::S3::TestConfig::OutputFilename); From d1d43af8f5686b94cb0b83525f6f1e6bca0c66fd Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Mon, 23 Jun 2025 23:57:38 -0400 Subject: [PATCH 18/77] fix outputfilename issue --- tests/performance-tests/src/reporting/JsonReportingMetrics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp index d3c2ed2e191..a1a46f0035e 100644 --- a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp +++ b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp @@ -172,7 +172,7 @@ void JsonReportingMetrics::DumpJson() const { root.WithArray("results", std::move(results)); - std::ofstream outFile(OutputFilename); + std::ofstream outFile(OutputFilename.c_str()); if (outFile.is_open()) { outFile << root.View().WriteReadable(); } From 01886453d5bfd7fe607371ca165d4f6b38cd8025 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Tue, 24 Jun 2025 00:30:01 -0400 Subject: [PATCH 19/77] fix Aws::String error again --- .../src/services/dynamodb/DynamoDBPerformanceTest.cpp | 4 ++-- tests/performance-tests/src/services/dynamodb/main.cpp | 5 ++++- tests/performance-tests/src/services/s3/main.cpp | 5 ++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp index ef690e8dfd7..ff127f3e1fe 100644 --- a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp +++ b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp @@ -84,7 +84,7 @@ bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& putItemRequest.SetTableName(tableName); Aws::Map item; - item["id"].SetS(Aws::String("test-key-") + Aws::String(std::to_string(i))); + item["id"].SetS(Aws::String("test-key-") + Aws::Utils::StringUtils::to_string(i)); item["data"].SetS(payload); putItemRequest.SetItem(item); @@ -100,7 +100,7 @@ bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& getItemRequest.SetTableName(tableName); Aws::Map key; - key["id"].SetS(Aws::String("test-key-") + Aws::String(std::to_string(i))); + key["id"].SetS(Aws::String("test-key-") + Aws::Utils::StringUtils::to_string(i)); getItemRequest.SetKey(key); auto getItemOutcome = dynamodb.GetItem(getItemRequest); diff --git a/tests/performance-tests/src/services/dynamodb/main.cpp b/tests/performance-tests/src/services/dynamodb/main.cpp index 3b88613e93c..6c438149b85 100644 --- a/tests/performance-tests/src/services/dynamodb/main.cpp +++ b/tests/performance-tests/src/services/dynamodb/main.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -42,7 +43,9 @@ int main(int argc, char** argv) { PerformanceTest::Services::DynamoDB::TestConfig::Operations); Aws::SDKOptions::SDKVersion const version; - Aws::String const versionStr = Aws::String(std::to_string(version.major)) + "." + Aws::String(std::to_string(version.minor)) + "." + Aws::String(std::to_string(version.patch)); + Aws::String const versionStr = Aws::Utils::StringUtils::to_string(version.major) + "." + + Aws::Utils::StringUtils::to_string(version.minor) + "." + + Aws::Utils::StringUtils::to_string(version.patch); PerformanceTest::Reporting::JsonReportingMetrics::SetProductInfo("cpp1", versionStr, commitId); PerformanceTest::Reporting::JsonReportingMetrics::SetOutputFilename(PerformanceTest::Services::DynamoDB::TestConfig::OutputFilename); diff --git a/tests/performance-tests/src/services/s3/main.cpp b/tests/performance-tests/src/services/s3/main.cpp index 631fc73ecfb..cae35882abe 100644 --- a/tests/performance-tests/src/services/s3/main.cpp +++ b/tests/performance-tests/src/services/s3/main.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -44,7 +45,9 @@ int main(int argc, char** argv) { PerformanceTest::Reporting::JsonReportingMetrics::RegisterOperationsToMonitor(PerformanceTest::Services::S3::TestConfig::Operations); Aws::SDKOptions::SDKVersion const version; - Aws::String const versionStr = Aws::String(std::to_string(version.major)) + "." + Aws::String(std::to_string(version.minor)) + "." + Aws::String(std::to_string(version.patch)); + Aws::String const versionStr = Aws::Utils::StringUtils::to_string(version.major) + "." + + Aws::Utils::StringUtils::to_string(version.minor) + "." + + Aws::Utils::StringUtils::to_string(version.patch); PerformanceTest::Reporting::JsonReportingMetrics::SetProductInfo("cpp1", versionStr, commitId); PerformanceTest::Reporting::JsonReportingMetrics::SetOutputFilename(PerformanceTest::Services::S3::TestConfig::OutputFilename); From 5629c36b8418e4a5801306484446b6c38f733ad0 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Tue, 24 Jun 2025 01:02:27 -0400 Subject: [PATCH 20/77] fix to_string in s3 --- .../performance-tests/src/services/s3/S3PerformanceTest.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp index 5f828aa3210..2a2d0736e9d 100644 --- a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp +++ b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp @@ -71,7 +71,7 @@ bool PerformanceTest::Services::S3::RunTest(Aws::S3::S3Client& s3, const TestCas *stream << payload; Aws::S3::Model::PutObjectRequest por; - por.WithBucket(bucketName).WithKey("test-object-" + std::to_string(i)).SetBody(stream); + por.WithBucket(bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i)).SetBody(stream); if (!s3.PutObject(por).IsSuccess()) { std::cerr << "[ERROR] PutObject failed!" << '\n'; } @@ -80,14 +80,14 @@ bool PerformanceTest::Services::S3::RunTest(Aws::S3::S3Client& s3, const TestCas // Run GetObject multiple times for (int i = 0; i < iterations; i++) { Aws::S3::Model::GetObjectRequest gor; - gor.WithBucket(bucketName).WithKey("test-object-" + std::to_string(i)); + gor.WithBucket(bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i)); if (!s3.GetObject(gor).IsSuccess()) { std::cerr << "[ERROR] GetObject failed!" << '\n'; } } for (int i = 0; i < iterations; i++) { - s3.DeleteObject(Aws::S3::Model::DeleteObjectRequest().WithBucket(bucketName).WithKey("test-object-" + std::to_string(i))); + s3.DeleteObject(Aws::S3::Model::DeleteObjectRequest().WithBucket(bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i))); } s3.DeleteBucket(Aws::S3::Model::DeleteBucketRequest().WithBucket(bucketName)); From 3a1c3deab2536c68cc23adf9670db5e59584e6cc Mon Sep 17 00:00:00 2001 From: Alan4506 <62124408+Alan4506@users.noreply.github.com> Date: Tue, 24 Jun 2025 10:51:41 -0400 Subject: [PATCH 21/77] disable lambda in run_integration_tests.py --- tools/scripts/run_integration_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/scripts/run_integration_tests.py b/tools/scripts/run_integration_tests.py index 0c7125e53f8..8c9081615f9 100644 --- a/tools/scripts/run_integration_tests.py +++ b/tools/scripts/run_integration_tests.py @@ -45,7 +45,7 @@ def main(): "aws-cpp-sdk-s3-unit-tests", "aws-cpp-sdk-s3-crt-integration-tests", #"aws-cpp-sdk-s3control-integration-tests", - "aws-cpp-sdk-lambda-integration-tests", + #"aws-cpp-sdk-lambda-integration-tests", "aws-cpp-sdk-cognitoidentity-integration-tests", #"aws-cpp-sdk-transfer-tests", #"aws-cpp-sdk-s3-encryption-integration-tests", From 3e1953d39d10008f4312e79cdd2131c55ccaeef8 Mon Sep 17 00:00:00 2001 From: Alan4506 <62124408+Alan4506@users.noreply.github.com> Date: Tue, 24 Jun 2025 10:53:06 -0400 Subject: [PATCH 22/77] Update run-al2-integ-tests.sh --- tools/scripts/build-tests/run-al2-integ-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/scripts/build-tests/run-al2-integ-tests.sh b/tools/scripts/build-tests/run-al2-integ-tests.sh index ac8ee3af18a..153e87feb45 100755 --- a/tools/scripts/build-tests/run-al2-integ-tests.sh +++ b/tools/scripts/build-tests/run-al2-integ-tests.sh @@ -21,7 +21,7 @@ AWS_ROLE_SESSION_NAME="$3" echo "Setting the run environment" export TEST_ASSUME_ROLE_ARN=arn:aws:iam::${AWS_ACCOUNT}:role/IntegrationTest -export TEST_LAMBDA_CODE_PATH=${PREFIX_DIR}/aws-sdk-cpp/tests/aws-cpp-sdk-lambda-integration-tests/resources +export TEST_LAMBDA_CODE_PATH=${PREFIX_DIR}/aws-sdk-cpp/tools/aws-cpp-sdk-lambda-integration-tests/resources export sts=$(aws sts assume-role --role-arn "$TEST_ASSUME_ROLE_ARN" --role-session-name "${AWS_ROLE_SESSION_NAME}" --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]') export profile=sdk-integ-test aws configure set aws_access_key_id $(echo "$sts" | jq -r '.[0]') --profile "$profile" From 4b22c29e3e6ab47a4fe5a17aa258186ef46e685a Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Tue, 24 Jun 2025 16:05:00 -0400 Subject: [PATCH 23/77] update CMake_Parameters docs to include performance test --- docs/CMake_Parameters.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/CMake_Parameters.md b/docs/CMake_Parameters.md index 146b4affddf..9f99830012c 100644 --- a/docs/CMake_Parameters.md +++ b/docs/CMake_Parameters.md @@ -128,6 +128,9 @@ You can also tell gcc or clang to pass these linker flags by specifying `-Wl,--g ### BUILD_BENCHMARKS (Defaults to OFF) Enables building the benchmark executable +### BUILD_PERFORMANCE_TESTS +(Defaults to OFF) Enables building the performance test executables for S3 and DynamoDB that measure and report operation latencies in JSON format. Requires S3 and DynamoDB clients to be built. + ### BUILD_OPTEL (Defaults to OFF) Enables building the open telemetry implementation of tracing From 2bca31140947326987d77830679edcae4c032618 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Wed, 25 Jun 2025 11:32:21 -0400 Subject: [PATCH 24/77] add shell scripts for al2 to run s3 and dynamodb performance test executables --- .../run-al2-dynamodb-performance-tests.sh | 38 +++++++++++++++++ .../run-al2-s3-performance-tests.sh | 41 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh create mode 100644 tools/scripts/build-tests/run-al2-s3-performance-tests.sh diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh new file mode 100644 index 00000000000..44125b24372 --- /dev/null +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -0,0 +1,38 @@ +#!/bin/bash +set -e + +DEFAULT_REGION="us-east-1" +DEFAULT_ITERATIONS=3 + +if [ "$#" -lt 1 ]; then + echo "Usage: ${0} PREFIX_DIR [--region REGION] [--iterations NUM]" + exit 1 +fi + +PREFIX_DIR="$1" +shift + +REGION="$DEFAULT_REGION" +ITERATIONS="$DEFAULT_ITERATIONS" + +while [[ "$#" -gt 0 ]]; do + case "$1" in + --region) REGION="$2"; shift 2 ;; + --iterations) ITERATIONS="$2"; shift 2 ;; + *) echo "Unknown parameter: $1"; exit 1 ;; + esac +done + +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" + +SDK_REPO_PATH="${PREFIX_DIR}/aws-sdk-cpp" +if [ -d "$SDK_REPO_PATH" ]; then + cd "$SDK_REPO_PATH" + COMMIT_ID=$(git rev-parse HEAD) + cd - +else + COMMIT_ID="unknown" +fi + +./dynamodb-performance-test --region "$REGION" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" +cat dynamodb-performance-test-results.json \ No newline at end of file diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh new file mode 100644 index 00000000000..a2c737d1e1f --- /dev/null +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -0,0 +1,41 @@ +#!/bin/bash +set -e + +DEFAULT_REGION="us-east-1" +DEFAULT_AZ_ID="use1-az4" +DEFAULT_ITERATIONS=3 + +if [ "$#" -lt 1 ]; then + echo "Usage: ${0} PREFIX_DIR [--region REGION] [--az-id AZ_ID] [--iterations NUM]" + exit 1 +fi + +PREFIX_DIR="$1" +shift + +REGION="$DEFAULT_REGION" +AZ_ID="$DEFAULT_AZ_ID" +ITERATIONS="$DEFAULT_ITERATIONS" + +while [[ "$#" -gt 0 ]]; do + case "$1" in + --region) REGION="$2"; shift 2 ;; + --az-id) AZ_ID="$2"; shift 2 ;; + --iterations) ITERATIONS="$2"; shift 2 ;; + *) echo "Unknown parameter: $1"; exit 1 ;; + esac +done + +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" + +SDK_REPO_PATH="${PREFIX_DIR}/aws-sdk-cpp" +if [ -d "$SDK_REPO_PATH" ]; then + cd "$SDK_REPO_PATH" + COMMIT_ID=$(git rev-parse HEAD) + cd - +else + COMMIT_ID="unknown" +fi + +./s3-performance-test --region "$REGION" --az-id "$AZ_ID" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" +cat s3-performance-test-results.json \ No newline at end of file From 991e012f443e4de13403640877836617141fcf34 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Thu, 26 Jun 2025 01:39:59 -0400 Subject: [PATCH 25/77] Apply map, dateutil, measurement --- .../reporting/JsonReportingMetrics.h | 35 +++++++++++++++---- .../src/reporting/JsonReportingMetrics.cpp | 31 ++++++++-------- .../dynamodb/DynamoDBPerformanceTest.cpp | 6 ++-- .../src/services/s3/S3PerformanceTest.cpp | 12 +++---- 4 files changed, 54 insertions(+), 30 deletions(-) diff --git a/tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h b/tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h index 2191c7851a6..d8976789c37 100644 --- a/tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h +++ b/tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h @@ -10,17 +10,40 @@ #include #include #include +#include #include +#include #include #include #include #include #include -#include namespace PerformanceTest { namespace Reporting { +/** + * A measurement value that supports different numeric types. + */ +class Measurement { + public: + enum Type { INTEGER, DOUBLE }; + + Measurement(int64_t value) : m_type(INTEGER) { m_data.i = value; } + Measurement(double value) : m_type(DOUBLE) { m_data.d = value; } + bool IsInt64() const { return m_type == INTEGER; } + bool IsDouble() const { return m_type == DOUBLE; } + int64_t AsInt64() const { return m_type == INTEGER ? m_data.i : static_cast(m_data.d); } + double AsDouble() const { return m_type == DOUBLE ? m_data.d : static_cast(m_data.i); } + + private: + Type m_type; + union { + int64_t i; + double d; + } m_data; +}; + /** * Container for a single performance metric record that stores measurement data and associated metadata. */ @@ -28,9 +51,9 @@ struct PerformanceMetricRecord { Aws::String name; Aws::String description; Aws::String unit; - int64_t date; - Aws::Vector measurements; - Aws::Vector> dimensions; + Aws::Utils::DateTime date; + Aws::Vector measurements; + Aws::Map dimensions; }; /** @@ -101,7 +124,7 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { * Sets test dimensions that will be included with all performance records. * @param dimensions Vector of key-value pairs representing test dimensions (e.g., size, bucket type) */ - static void SetTestContext(const Aws::Vector>& dimensions); + static void SetTestContext(const Aws::Map& dimensions); /** * Registers specific operations to monitor. If empty, all operations are monitored. @@ -140,7 +163,7 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { void DumpJson() const; mutable Aws::Vector m_performanceRecords; - static Aws::Vector> TestDimensions; + static Aws::Map TestDimensions; static Aws::Set MonitoredOperations; static Aws::String ProductId; static Aws::String SdkVersion; diff --git a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp index a1a46f0035e..5481400fa1b 100644 --- a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp +++ b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp @@ -26,16 +26,14 @@ using namespace PerformanceTest::Reporting; -Aws::Vector> JsonReportingMetrics::TestDimensions; +Aws::Map JsonReportingMetrics::TestDimensions; Aws::Set JsonReportingMetrics::MonitoredOperations; Aws::String JsonReportingMetrics::ProductId = "unknown"; Aws::String JsonReportingMetrics::SdkVersion = "unknown"; Aws::String JsonReportingMetrics::CommitId = "unknown"; Aws::String JsonReportingMetrics::OutputFilename = "performance-test-results.json"; -void JsonReportingMetrics::SetTestContext(const Aws::Vector>& dimensions) { - TestDimensions = dimensions; -} +void JsonReportingMetrics::SetTestContext(const Aws::Map& dimensions) { TestDimensions = dimensions; } void JsonReportingMetrics::RegisterOperationsToMonitor(const Aws::Vector& operations) { MonitoredOperations.clear(); @@ -78,8 +76,8 @@ void JsonReportingMetrics::AddPerformanceRecord(const Aws::String& serviceName, Aws::Utils::StringUtils::ToLower(serviceName.c_str()) + "." + Aws::Utils::StringUtils::ToLower(requestName.c_str()) + ".latency"; record.description = "Time to complete " + requestName + " operation"; record.unit = "Milliseconds"; - record.date = Aws::Utils::DateTime::Now().Seconds(); - record.measurements.push_back(durationMs); + record.date = Aws::Utils::DateTime::Now(); + record.measurements.emplace_back(durationMs); record.dimensions = TestDimensions; m_performanceRecords.push_back(record); @@ -146,24 +144,29 @@ void JsonReportingMetrics::DumpJson() const { jsonMetric.WithString("name", record.name); jsonMetric.WithString("description", record.description); jsonMetric.WithString("unit", record.unit); - jsonMetric.WithInt64("date", record.date); + jsonMetric.WithInt64("date", record.date.Seconds()); if (!record.dimensions.empty()) { Aws::Utils::Array dimensionsArray(record.dimensions.size()); - for (size_t j = 0; j < record.dimensions.size(); ++j) { + size_t dimensionIndex = 0; + for (const auto& dim : record.dimensions) { Aws::Utils::Json::JsonValue dimension; - dimension.WithString("name", record.dimensions[j].first); - dimension.WithString("value", record.dimensions[j].second); - dimensionsArray[j] = std::move(dimension); + dimension.WithString("name", dim.first); + dimension.WithString("value", dim.second); + dimensionsArray[dimensionIndex++] = std::move(dimension); } jsonMetric.WithArray("dimensions", std::move(dimensionsArray)); } Aws::Utils::Array measurementsArray(record.measurements.size()); - for (size_t j = 0; j < record.measurements.size(); ++j) { + for (size_t measurementIndex = 0; measurementIndex < record.measurements.size(); ++measurementIndex) { Aws::Utils::Json::JsonValue measurementValue; - measurementValue.AsInt64(record.measurements[j]); - measurementsArray[j] = std::move(measurementValue); + if (record.measurements[measurementIndex].IsDouble()) { + measurementValue.AsDouble(record.measurements[measurementIndex].AsDouble()); + } else { + measurementValue.AsInt64(record.measurements[measurementIndex].AsInt64()); + } + measurementsArray[measurementIndex] = std::move(measurementValue); } jsonMetric.WithArray("measurements", std::move(measurementsArray)); diff --git a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp index ff127f3e1fe..0682d8b7637 100644 --- a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp +++ b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -28,11 +27,10 @@ #include #include #include -#include bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& dynamodb, const TestCase& config, int iterations) { - Aws::Vector> dimensions; - dimensions.emplace_back("Size", config.sizeLabel); + Aws::Map dimensions; + dimensions["Size"] = config.sizeLabel; PerformanceTest::Reporting::JsonReportingMetrics::SetTestContext(dimensions); Aws::String tableName; diff --git a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp index 2a2d0736e9d..e243c5509b8 100644 --- a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp +++ b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp @@ -8,9 +8,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -26,13 +26,12 @@ #include #include -#include bool PerformanceTest::Services::S3::RunTest(Aws::S3::S3Client& s3, const TestCase& config, const Aws::String& availabilityZoneId, int iterations) { - Aws::Vector> dimensions; - dimensions.emplace_back("Size", config.sizeLabel); - dimensions.emplace_back("BucketType", config.bucketTypeLabel); + Aws::Map dimensions; + dimensions["Size"] = config.sizeLabel; + dimensions["BucketType"] = config.bucketTypeLabel; PerformanceTest::Reporting::JsonReportingMetrics::SetTestContext(dimensions); Aws::String bucketName; @@ -87,7 +86,8 @@ bool PerformanceTest::Services::S3::RunTest(Aws::S3::S3Client& s3, const TestCas } for (int i = 0; i < iterations; i++) { - s3.DeleteObject(Aws::S3::Model::DeleteObjectRequest().WithBucket(bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i))); + s3.DeleteObject( + Aws::S3::Model::DeleteObjectRequest().WithBucket(bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i))); } s3.DeleteBucket(Aws::S3::Model::DeleteBucketRequest().WithBucket(bucketName)); From bf39964c62e7fa9208e35f68fff0586667e5405b Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Thu, 26 Jun 2025 14:52:24 -0400 Subject: [PATCH 26/77] reporting refinement based on PR comments --- .../reporting/JsonReportingMetrics.h | 76 +++++++------ .../services/dynamodb/DynamoDBTestConfig.h | 3 +- .../services/s3/S3TestConfig.h | 3 +- .../src/reporting/JsonReportingMetrics.cpp | 105 ++++++++++-------- .../dynamodb/DynamoDBPerformanceTest.cpp | 6 +- .../src/services/dynamodb/main.cpp | 21 ++-- .../src/services/s3/S3PerformanceTest.cpp | 9 +- .../src/services/s3/main.cpp | 20 ++-- 8 files changed, 128 insertions(+), 115 deletions(-) diff --git a/tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h b/tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h index d8976789c37..b3903e19c9a 100644 --- a/tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h +++ b/tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h @@ -62,6 +62,18 @@ struct PerformanceMetricRecord { */ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { public: + /** + * Constructor that initializes the metrics collector with configuration parameters. + * @param monitoredOperations Set of operations to monitor (empty means monitor all) + * @param productId Product identifier (e.g., "cpp1") + * @param sdkVersion SDK version string + * @param commitId Git commit identifier + * @param outputFilename Path to output file (e.g., "s3-perf-results.json") + */ + JsonReportingMetrics(const Aws::Set& monitoredOperations = Aws::Set(), const Aws::String& productId = "unknown", + const Aws::String& sdkVersion = "unknown", const Aws::String& commitId = "unknown", + const Aws::String& outputFilename = "performance-test-results.json"); + ~JsonReportingMetrics() override; /** @@ -120,41 +132,18 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { void OnFinish(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request, void* context) const override; - /** - * Sets test dimensions that will be included with all performance records. - * @param dimensions Vector of key-value pairs representing test dimensions (e.g., size, bucket type) - */ - static void SetTestContext(const Aws::Map& dimensions); - - /** - * Registers specific operations to monitor. If empty, all operations are monitored. - * @param operations Vector of operation names to track (e.g., "PutObject", "GetItem") - */ - static void RegisterOperationsToMonitor(const Aws::Vector& operations); - - /** - * Sets product information to include in the JSON output. - * @param productId Product identifier (e.g., "cpp1") - * @param sdkVersion SDK version string - * @param commitId Git commit identifier - */ - static void SetProductInfo(const Aws::String& productId, const Aws::String& sdkVersion, const Aws::String& commitId); - - /** - * Sets the output filename for the JSON performance report. - * @param filename Path to output file (e.g., "s3-perf-results.json") - */ - static void SetOutputFilename(const Aws::String& filename); - private: /** - * Adds a performance record for a completed AWS service operation. + * Adds a performance record with a specified duration. * @param serviceName Name of the AWS service (e.g., "S3", "DynamoDB") * @param requestName Name of the operation (e.g., "PutObject", "GetItem") * @param metricsFromCore Core metrics collection containing latency data + * @param request HTTP request object (optional, for extracting test metadata) + * @param durationMs Duration of the request in milliseconds (default: 0) */ void AddPerformanceRecord(const Aws::String& serviceName, const Aws::String& requestName, - const Aws::Monitoring::CoreMetricsCollection& metricsFromCore) const; + const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, + const std::shared_ptr& request = nullptr, int64_t durationMs = 0) const; /** * Outputs aggregated performance metrics to JSON file. @@ -163,12 +152,11 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { void DumpJson() const; mutable Aws::Vector m_performanceRecords; - static Aws::Map TestDimensions; - static Aws::Set MonitoredOperations; - static Aws::String ProductId; - static Aws::String SdkVersion; - static Aws::String CommitId; - static Aws::String OutputFilename; + Aws::Set m_monitoredOperations; + Aws::String m_productId; + Aws::String m_sdkVersion; + Aws::String m_commitId; + Aws::String m_outputFilename; }; /** @@ -177,12 +165,32 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { */ class JsonReportingMetricsFactory : public Aws::Monitoring::MonitoringFactory { public: + /** + * Constructor that initializes the factory with configuration parameters. + * @param monitoredOperations Set of operations to monitor (empty means monitor all) + * @param productId Product identifier (e.g., "cpp1") + * @param sdkVersion SDK version string + * @param commitId Git commit identifier + * @param outputFilename Path to output file (e.g., "s3-perf-results.json") + */ + JsonReportingMetricsFactory(const Aws::Set& monitoredOperations = Aws::Set(), + const Aws::String& productId = "unknown", const Aws::String& sdkVersion = "unknown", + const Aws::String& commitId = "unknown", const Aws::String& outputFilename = "performance-test-results.json"); + ~JsonReportingMetricsFactory() override = default; + /** * Creates a new JsonReportingMetrics instance for performance monitoring. * @return Unique pointer to monitoring interface implementation */ Aws::UniquePtr CreateMonitoringInstance() const override; + + private: + Aws::Set m_monitoredOperations; + Aws::String m_productId; + Aws::String m_sdkVersion; + Aws::String m_commitId; + Aws::String m_outputFilename; }; } // namespace Reporting } // namespace PerformanceTest \ No newline at end of file diff --git a/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBTestConfig.h b/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBTestConfig.h index 4ca30ab7250..f8f13910c92 100644 --- a/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBTestConfig.h +++ b/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBTestConfig.h @@ -5,6 +5,7 @@ #pragma once +#include #include #include @@ -12,7 +13,7 @@ namespace PerformanceTest { namespace Services { namespace DynamoDB { namespace TestConfig { -const Aws::Vector Operations = {"PutItem", "GetItem"}; +const Aws::Set Operations = {"PutItem", "GetItem"}; const Aws::Vector TestMatrix = {{"8KB", 8 * 1024}, {"64KB", 64 * 1024}, {"392KB", 392 * 1024}}; diff --git a/tests/performance-tests/include/performance_tests/services/s3/S3TestConfig.h b/tests/performance-tests/include/performance_tests/services/s3/S3TestConfig.h index 3c5ce05d910..256a493cbbe 100644 --- a/tests/performance-tests/include/performance_tests/services/s3/S3TestConfig.h +++ b/tests/performance-tests/include/performance_tests/services/s3/S3TestConfig.h @@ -5,6 +5,7 @@ #pragma once +#include #include #include @@ -12,7 +13,7 @@ namespace PerformanceTest { namespace Services { namespace S3 { namespace TestConfig { -const Aws::Vector Operations = {"PutObject", "GetObject"}; +const Aws::Set Operations = {"PutObject", "GetObject"}; const Aws::Vector TestMatrix = {{"8KB", 8 * 1024, "s3-standard"}, {"64KB", 64 * 1024, "s3-standard"}, {"1MB", 1024 * 1024, "s3-standard"}, {"8KB", 8 * 1024, "s3-express"}, diff --git a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp index 5481400fa1b..194271b433a 100644 --- a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp +++ b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp @@ -26,51 +26,42 @@ using namespace PerformanceTest::Reporting; -Aws::Map JsonReportingMetrics::TestDimensions; -Aws::Set JsonReportingMetrics::MonitoredOperations; -Aws::String JsonReportingMetrics::ProductId = "unknown"; -Aws::String JsonReportingMetrics::SdkVersion = "unknown"; -Aws::String JsonReportingMetrics::CommitId = "unknown"; -Aws::String JsonReportingMetrics::OutputFilename = "performance-test-results.json"; - -void JsonReportingMetrics::SetTestContext(const Aws::Map& dimensions) { TestDimensions = dimensions; } - -void JsonReportingMetrics::RegisterOperationsToMonitor(const Aws::Vector& operations) { - MonitoredOperations.clear(); - for (const auto& operation : operations) { - MonitoredOperations.insert(operation); - } -} - -void JsonReportingMetrics::SetProductInfo(const Aws::String& productId, const Aws::String& sdkVersion, const Aws::String& commitId) { - ProductId = productId; - SdkVersion = sdkVersion; - CommitId = commitId; -} - -void JsonReportingMetrics::SetOutputFilename(const Aws::String& filename) { OutputFilename = filename; } +struct RequestContext { + Aws::Utils::DateTime requestStartTime; +}; + +JsonReportingMetrics::JsonReportingMetrics(const Aws::Set& monitoredOperations, const Aws::String& productId, + const Aws::String& sdkVersion, const Aws::String& commitId, const Aws::String& outputFilename) + : m_monitoredOperations(monitoredOperations), + m_productId(productId), + m_sdkVersion(sdkVersion), + m_commitId(commitId), + m_outputFilename(outputFilename) {} + +JsonReportingMetricsFactory::JsonReportingMetricsFactory(const Aws::Set& monitoredOperations, const Aws::String& productId, + const Aws::String& sdkVersion, const Aws::String& commitId, + const Aws::String& outputFilename) + : m_monitoredOperations(monitoredOperations), + m_productId(productId), + m_sdkVersion(sdkVersion), + m_commitId(commitId), + m_outputFilename(outputFilename) {} JsonReportingMetrics::~JsonReportingMetrics() { DumpJson(); } Aws::UniquePtr JsonReportingMetricsFactory::CreateMonitoringInstance() const { - return Aws::MakeUnique("JsonReportingMetrics"); + return Aws::MakeUnique("JsonReportingMetrics", m_monitoredOperations, m_productId, m_sdkVersion, m_commitId, + m_outputFilename); } void JsonReportingMetrics::AddPerformanceRecord(const Aws::String& serviceName, const Aws::String& requestName, - const Aws::Monitoring::CoreMetricsCollection& metricsFromCore) const { + const Aws::Monitoring::CoreMetricsCollection&, + const std::shared_ptr& request, int64_t durationMs) const { // If no operations are registered, monitor all operations. Otherwise, only monitor registered operations - if (!MonitoredOperations.empty() && MonitoredOperations.find(requestName) == MonitoredOperations.end()) { + if (!m_monitoredOperations.empty() && m_monitoredOperations.find(requestName) == m_monitoredOperations.end()) { return; } - int64_t durationMs = 0; - Aws::String const latencyKey = Aws::Monitoring::GetHttpClientMetricNameByType(Aws::Monitoring::HttpClientMetricsType::RequestLatency); - - auto iterator = metricsFromCore.httpClientMetrics.find(latencyKey); - if (iterator != metricsFromCore.httpClientMetrics.end()) { - durationMs = iterator->second; - } - PerformanceMetricRecord record; record.name = Aws::Utils::StringUtils::ToLower(serviceName.c_str()) + "." + Aws::Utils::StringUtils::ToLower(requestName.c_str()) + ".latency"; @@ -78,33 +69,53 @@ void JsonReportingMetrics::AddPerformanceRecord(const Aws::String& serviceName, record.unit = "Milliseconds"; record.date = Aws::Utils::DateTime::Now(); record.measurements.emplace_back(durationMs); - record.dimensions = TestDimensions; + + if (request) { + auto headers = request->GetHeaders(); + for (const auto& header : headers) { + if (header.first.find("test-dimension-") == 0) { + Aws::String const key = header.first.substr(15); + record.dimensions[key] = header.second; + } + } + } m_performanceRecords.push_back(record); } void* JsonReportingMetrics::OnRequestStarted(const Aws::String&, const Aws::String&, const std::shared_ptr&) const { - return nullptr; + auto context = Aws::New("JsonReportingMetrics"); + context->requestStartTime = Aws::Utils::DateTime::Now(); + return context; } void JsonReportingMetrics::OnRequestSucceeded(const Aws::String& serviceName, const Aws::String& requestName, - const std::shared_ptr&, const Aws::Client::HttpResponseOutcome&, - const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void*) const { - AddPerformanceRecord(serviceName, requestName, metricsFromCore); + const std::shared_ptr& request, + const Aws::Client::HttpResponseOutcome&, + const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void* context) const { + RequestContext* requestContext = static_cast(context); + int64_t durationMs = (Aws::Utils::DateTime::Now() - requestContext->requestStartTime).count(); + AddPerformanceRecord(serviceName, requestName, metricsFromCore, request, durationMs); } void JsonReportingMetrics::OnRequestFailed(const Aws::String& serviceName, const Aws::String& requestName, - const std::shared_ptr&, const Aws::Client::HttpResponseOutcome&, - const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void*) const { - AddPerformanceRecord(serviceName, requestName, metricsFromCore); + const std::shared_ptr& request, + const Aws::Client::HttpResponseOutcome&, + const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void* context) const { + RequestContext* requestContext = static_cast(context); + int64_t durationMs = (Aws::Utils::DateTime::Now() - requestContext->requestStartTime).count(); + AddPerformanceRecord(serviceName, requestName, metricsFromCore, request, durationMs); } void JsonReportingMetrics::OnRequestRetry(const Aws::String&, const Aws::String&, const std::shared_ptr&, void*) const {} void JsonReportingMetrics::OnFinish(const Aws::String&, const Aws::String&, const std::shared_ptr&, - void*) const {} + void* context) const { + RequestContext* requestContext = static_cast(context); + Aws::Delete(requestContext); +} void JsonReportingMetrics::DumpJson() const { if (m_performanceRecords.empty()) { @@ -131,9 +142,9 @@ void JsonReportingMetrics::DumpJson() const { // Create the JSON output Aws::Utils::Json::JsonValue root; - root.WithString("productId", ProductId); - root.WithString("sdkVersion", SdkVersion); - root.WithString("commitId", CommitId); + root.WithString("productId", m_productId); + root.WithString("sdkVersion", m_sdkVersion); + root.WithString("commitId", m_commitId); Aws::Utils::Array results(aggregatedRecords.size()); size_t index = 0; @@ -175,7 +186,7 @@ void JsonReportingMetrics::DumpJson() const { root.WithArray("results", std::move(results)); - std::ofstream outFile(OutputFilename.c_str()); + std::ofstream outFile(m_outputFilename.c_str()); if (outFile.is_open()) { outFile << root.View().WriteReadable(); } diff --git a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp index 0682d8b7637..db08e118203 100644 --- a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp +++ b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp @@ -29,10 +29,6 @@ #include bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& dynamodb, const TestCase& config, int iterations) { - Aws::Map dimensions; - dimensions["Size"] = config.sizeLabel; - PerformanceTest::Reporting::JsonReportingMetrics::SetTestContext(dimensions); - Aws::String tableName; Aws::String const rawUUID = Aws::Utils::UUID::RandomUUID(); Aws::String const tableId = Aws::Utils::StringUtils::ToLower(rawUUID.c_str()).substr(0, 8); @@ -80,6 +76,7 @@ bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& for (int i = 0; i < iterations; i++) { Aws::DynamoDB::Model::PutItemRequest putItemRequest; putItemRequest.SetTableName(tableName); + putItemRequest.SetAdditionalCustomHeaderValue("test-dimension-size", config.sizeLabel); Aws::Map item; item["id"].SetS(Aws::String("test-key-") + Aws::Utils::StringUtils::to_string(i)); @@ -96,6 +93,7 @@ bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& for (int i = 0; i < iterations; i++) { Aws::DynamoDB::Model::GetItemRequest getItemRequest; getItemRequest.SetTableName(tableName); + getItemRequest.SetAdditionalCustomHeaderValue("test-dimension-size", config.sizeLabel); Aws::Map key; key["id"].SetS(Aws::String("test-key-") + Aws::Utils::StringUtils::to_string(i)); diff --git a/tests/performance-tests/src/services/dynamodb/main.cpp b/tests/performance-tests/src/services/dynamodb/main.cpp index 6c438149b85..82bff0ba82b 100644 --- a/tests/performance-tests/src/services/dynamodb/main.cpp +++ b/tests/performance-tests/src/services/dynamodb/main.cpp @@ -33,22 +33,19 @@ int main(int argc, char** argv) { } Aws::SDKOptions options; - options.monitoringOptions.customizedMonitoringFactory_create_fn = {[]() -> Aws::UniquePtr { - return Aws::MakeUnique("JsonReportingMetricsFactory"); + Aws::SDKOptions::SDKVersion const version; + Aws::String const versionStr = Aws::Utils::StringUtils::to_string(static_cast(version.major)) + "." + + Aws::Utils::StringUtils::to_string(static_cast(version.minor)) + "." + + Aws::Utils::StringUtils::to_string(static_cast(version.patch)); + + options.monitoringOptions.customizedMonitoringFactory_create_fn = {[&]() -> Aws::UniquePtr { + return Aws::MakeUnique( + "JsonReportingMetricsFactory", PerformanceTest::Services::DynamoDB::TestConfig::Operations, "cpp1", versionStr, commitId, + PerformanceTest::Services::DynamoDB::TestConfig::OutputFilename); }}; Aws::InitAPI(options); - PerformanceTest::Reporting::JsonReportingMetrics::RegisterOperationsToMonitor( - PerformanceTest::Services::DynamoDB::TestConfig::Operations); - - Aws::SDKOptions::SDKVersion const version; - Aws::String const versionStr = Aws::Utils::StringUtils::to_string(version.major) + "." + - Aws::Utils::StringUtils::to_string(version.minor) + "." + - Aws::Utils::StringUtils::to_string(version.patch); - PerformanceTest::Reporting::JsonReportingMetrics::SetProductInfo("cpp1", versionStr, commitId); - PerformanceTest::Reporting::JsonReportingMetrics::SetOutputFilename(PerformanceTest::Services::DynamoDB::TestConfig::OutputFilename); - { Aws::Client::ClientConfiguration cfg; cfg.region = region; diff --git a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp index e243c5509b8..ebb041380f5 100644 --- a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp +++ b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp @@ -29,11 +29,6 @@ bool PerformanceTest::Services::S3::RunTest(Aws::S3::S3Client& s3, const TestCase& config, const Aws::String& availabilityZoneId, int iterations) { - Aws::Map dimensions; - dimensions["Size"] = config.sizeLabel; - dimensions["BucketType"] = config.bucketTypeLabel; - PerformanceTest::Reporting::JsonReportingMetrics::SetTestContext(dimensions); - Aws::String bucketName; Aws::S3::Model::CreateBucketRequest cbr; Aws::String const rawUUID = Aws::Utils::UUID::RandomUUID(); @@ -71,6 +66,8 @@ bool PerformanceTest::Services::S3::RunTest(Aws::S3::S3Client& s3, const TestCas Aws::S3::Model::PutObjectRequest por; por.WithBucket(bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i)).SetBody(stream); + por.SetAdditionalCustomHeaderValue("test-dimension-size", config.sizeLabel); + por.SetAdditionalCustomHeaderValue("test-dimension-bucket-type", config.bucketTypeLabel); if (!s3.PutObject(por).IsSuccess()) { std::cerr << "[ERROR] PutObject failed!" << '\n'; } @@ -80,6 +77,8 @@ bool PerformanceTest::Services::S3::RunTest(Aws::S3::S3Client& s3, const TestCas for (int i = 0; i < iterations; i++) { Aws::S3::Model::GetObjectRequest gor; gor.WithBucket(bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i)); + gor.SetAdditionalCustomHeaderValue("test-dimension-size", config.sizeLabel); + gor.SetAdditionalCustomHeaderValue("test-dimension-bucket-type", config.bucketTypeLabel); if (!s3.GetObject(gor).IsSuccess()) { std::cerr << "[ERROR] GetObject failed!" << '\n'; } diff --git a/tests/performance-tests/src/services/s3/main.cpp b/tests/performance-tests/src/services/s3/main.cpp index cae35882abe..c99a7f14ded 100644 --- a/tests/performance-tests/src/services/s3/main.cpp +++ b/tests/performance-tests/src/services/s3/main.cpp @@ -36,21 +36,19 @@ int main(int argc, char** argv) { } Aws::SDKOptions options; - options.monitoringOptions.customizedMonitoringFactory_create_fn = {[]() -> Aws::UniquePtr { - return Aws::MakeUnique("JsonReportingMetricsFactory"); + Aws::SDKOptions::SDKVersion const version; + Aws::String const versionStr = Aws::Utils::StringUtils::to_string(static_cast(version.major)) + "." + + Aws::Utils::StringUtils::to_string(static_cast(version.minor)) + "." + + Aws::Utils::StringUtils::to_string(static_cast(version.patch)); + + options.monitoringOptions.customizedMonitoringFactory_create_fn = {[&]() -> Aws::UniquePtr { + return Aws::MakeUnique( + "JsonReportingMetricsFactory", PerformanceTest::Services::S3::TestConfig::Operations, "cpp1", versionStr, commitId, + PerformanceTest::Services::S3::TestConfig::OutputFilename); }}; Aws::InitAPI(options); - PerformanceTest::Reporting::JsonReportingMetrics::RegisterOperationsToMonitor(PerformanceTest::Services::S3::TestConfig::Operations); - - Aws::SDKOptions::SDKVersion const version; - Aws::String const versionStr = Aws::Utils::StringUtils::to_string(version.major) + "." + - Aws::Utils::StringUtils::to_string(version.minor) + "." + - Aws::Utils::StringUtils::to_string(version.patch); - PerformanceTest::Reporting::JsonReportingMetrics::SetProductInfo("cpp1", versionStr, commitId); - PerformanceTest::Reporting::JsonReportingMetrics::SetOutputFilename(PerformanceTest::Services::S3::TestConfig::OutputFilename); - { Aws::Client::ClientConfiguration cfg; cfg.region = region; From a2e7847ca69fa13ec7b9fb7d4a56a60ff2ecf7be Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Thu, 26 Jun 2025 15:05:21 -0400 Subject: [PATCH 27/77] fix folder naming in performance test --- CMakeLists.txt | 2 +- .../reporting/JsonReportingMetrics.h | 0 .../services/dynamodb/DynamoDBPerformanceTest.h | 0 .../services/dynamodb/DynamoDBTestConfig.h | 0 .../services/s3/S3PerformanceTest.h | 0 .../services/s3/S3TestConfig.h | 0 6 files changed, 1 insertion(+), 1 deletion(-) rename tests/performance-tests/include/{performance_tests => performance-tests}/reporting/JsonReportingMetrics.h (100%) rename tests/performance-tests/include/{performance_tests => performance-tests}/services/dynamodb/DynamoDBPerformanceTest.h (100%) rename tests/performance-tests/include/{performance_tests => performance-tests}/services/dynamodb/DynamoDBTestConfig.h (100%) rename tests/performance-tests/include/{performance_tests => performance-tests}/services/s3/S3PerformanceTest.h (100%) rename tests/performance-tests/include/{performance_tests => performance-tests}/services/s3/S3TestConfig.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index e22f1aa9d9f..e961c50ff6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -341,7 +341,7 @@ if (LEGACY_BUILD) add_sdks() include(tests) - #Performance tests (under tests/performance_tests) + #Performance tests (under tests/performance-tests) option(BUILD_PERFORMANCE_TESTS "Build AWS C++ performance tests" OFF) if(BUILD_PERFORMANCE_TESTS) add_subdirectory(tests/performance-tests) diff --git a/tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h b/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h similarity index 100% rename from tests/performance-tests/include/performance_tests/reporting/JsonReportingMetrics.h rename to tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h diff --git a/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBPerformanceTest.h b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h similarity index 100% rename from tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBPerformanceTest.h rename to tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h diff --git a/tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBTestConfig.h b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h similarity index 100% rename from tests/performance-tests/include/performance_tests/services/dynamodb/DynamoDBTestConfig.h rename to tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h diff --git a/tests/performance-tests/include/performance_tests/services/s3/S3PerformanceTest.h b/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h similarity index 100% rename from tests/performance-tests/include/performance_tests/services/s3/S3PerformanceTest.h rename to tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h diff --git a/tests/performance-tests/include/performance_tests/services/s3/S3TestConfig.h b/tests/performance-tests/include/performance-tests/services/s3/S3TestConfig.h similarity index 100% rename from tests/performance-tests/include/performance_tests/services/s3/S3TestConfig.h rename to tests/performance-tests/include/performance-tests/services/s3/S3TestConfig.h From f994e3a3a6c294bfb6ad2c4633c03017c6f8eb1a Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Thu, 26 Jun 2025 15:11:48 -0400 Subject: [PATCH 28/77] update comments in JsonReportingMetrics --- .../performance-tests/reporting/JsonReportingMetrics.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h b/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h index b3903e19c9a..70eb81051b5 100644 --- a/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h +++ b/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h @@ -93,7 +93,7 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { * @param request HTTP request object * @param outcome HTTP response outcome * @param metrics Core metrics collection containing latency data - * @param context Request context (unused) + * @param context Request context */ void OnRequestSucceeded(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request, const Aws::Client::HttpResponseOutcome& outcome, @@ -106,7 +106,7 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { * @param request HTTP request object * @param outcome HTTP response outcome * @param metrics Core metrics collection containing latency data - * @param context Request context (unused) + * @param context Request context */ void OnRequestFailed(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request, const Aws::Client::HttpResponseOutcome& outcome, @@ -117,7 +117,7 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { * @param serviceName Name of the AWS service * @param requestName Name of the operation * @param request HTTP request object - * @param context Request context (unused) + * @param context Request context */ void OnRequestRetry(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request, void* context) const override; @@ -127,7 +127,7 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { * @param serviceName Name of the AWS service * @param requestName Name of the operation * @param request HTTP request object - * @param context Request context (unused) + * @param context Request context */ void OnFinish(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request, void* context) const override; From a6e80c4f00e168e869e62f53311536fb6d092e69 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Thu, 26 Jun 2025 15:25:20 -0400 Subject: [PATCH 29/77] rename performance-tests --- .../src/reporting/JsonReportingMetrics.cpp | 2 +- .../src/services/dynamodb/DynamoDBPerformanceTest.cpp | 4 ++-- tests/performance-tests/src/services/dynamodb/main.cpp | 6 +++--- .../performance-tests/src/services/s3/S3PerformanceTest.cpp | 4 ++-- tests/performance-tests/src/services/s3/main.cpp | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp index 194271b433a..8f6b6339eaf 100644 --- a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp +++ b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include diff --git a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp index db08e118203..a9ab4c8591a 100644 --- a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp +++ b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp @@ -20,8 +20,8 @@ #include #include #include -#include -#include +#include +#include #include #include diff --git a/tests/performance-tests/src/services/dynamodb/main.cpp b/tests/performance-tests/src/services/dynamodb/main.cpp index 82bff0ba82b..e9e291ef72f 100644 --- a/tests/performance-tests/src/services/dynamodb/main.cpp +++ b/tests/performance-tests/src/services/dynamodb/main.cpp @@ -10,9 +10,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include diff --git a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp index ebb041380f5..bc0cb8aeb66 100644 --- a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp +++ b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0. */ -#include "performance_tests/services/s3/S3PerformanceTest.h" +#include "performance-tests/services/s3/S3PerformanceTest.h" #include #include @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include diff --git a/tests/performance-tests/src/services/s3/main.cpp b/tests/performance-tests/src/services/s3/main.cpp index c99a7f14ded..33cb2efe71b 100644 --- a/tests/performance-tests/src/services/s3/main.cpp +++ b/tests/performance-tests/src/services/s3/main.cpp @@ -10,9 +10,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include From b7eba3a7af7a284e8716f4b78ef011bbe4dc363e Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Fri, 27 Jun 2025 14:50:27 -0400 Subject: [PATCH 30/77] changes based on PR comments --- tests/performance-tests/CMakeLists.txt | 1 + .../reporting/JsonReportingMetrics.h | 56 +++++++------- .../src/reporting/JsonReportingMetrics.cpp | 74 +++++++++++++------ 3 files changed, 78 insertions(+), 53 deletions(-) diff --git a/tests/performance-tests/CMakeLists.txt b/tests/performance-tests/CMakeLists.txt index 73fd8f496db..5660c9e1438 100644 --- a/tests/performance-tests/CMakeLists.txt +++ b/tests/performance-tests/CMakeLists.txt @@ -19,6 +19,7 @@ function(add_service_test SERVICE SDK_LIB PERF_TEST_FILE) set_compiler_warnings(${SERVICE}-performance-test) target_include_directories(${SERVICE}-performance-test PRIVATE include) target_link_libraries(${SERVICE}-performance-test PRIVATE aws-cpp-sdk-core ${SDK_LIB}) + target_compile_options(${SERVICE}-performance-test PRIVATE -std=c++17) endfunction() add_service_test(s3 aws-cpp-sdk-s3 S3PerformanceTest.cpp) diff --git a/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h b/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h index 70eb81051b5..dbd76e60890 100644 --- a/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h +++ b/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -19,30 +20,10 @@ #include #include +#include namespace PerformanceTest { namespace Reporting { -/** - * A measurement value that supports different numeric types. - */ -class Measurement { - public: - enum Type { INTEGER, DOUBLE }; - - Measurement(int64_t value) : m_type(INTEGER) { m_data.i = value; } - Measurement(double value) : m_type(DOUBLE) { m_data.d = value; } - bool IsInt64() const { return m_type == INTEGER; } - bool IsDouble() const { return m_type == DOUBLE; } - int64_t AsInt64() const { return m_type == INTEGER ? m_data.i : static_cast(m_data.d); } - double AsDouble() const { return m_type == DOUBLE ? m_data.d : static_cast(m_data.i); } - - private: - Type m_type; - union { - int64_t i; - double d; - } m_data; -}; /** * Container for a single performance metric record that stores measurement data and associated metadata. @@ -52,7 +33,7 @@ struct PerformanceMetricRecord { Aws::String description; Aws::String unit; Aws::Utils::DateTime date; - Aws::Vector measurements; + Aws::Vector> measurements; Aws::Map dimensions; }; @@ -134,16 +115,26 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { private: /** - * Adds a performance record with a specified duration. - * @param serviceName Name of the AWS service (e.g., "S3", "DynamoDB") - * @param requestName Name of the operation (e.g., "PutObject", "GetItem") + * Helper method to process request metrics and store in context. + * @param serviceName Name of the AWS service + * @param requestName Name of the operation + * @param request HTTP request object * @param metricsFromCore Core metrics collection containing latency data - * @param request HTTP request object (optional, for extracting test metadata) - * @param durationMs Duration of the request in milliseconds (default: 0) + * @param context Request context + */ + void StoreLatencyInContext(const Aws::String& serviceName, const Aws::String& requestName, + const std::shared_ptr& request, + const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void* context) const; + + /** + * Adds a performance record with a specified duration. + * @param serviceName Name of the AWS service + * @param requestName Name of the operation + * @param request HTTP request object + * @param durationMs Duration of the request in milliseconds */ void AddPerformanceRecord(const Aws::String& serviceName, const Aws::String& requestName, - const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, - const std::shared_ptr& request = nullptr, int64_t durationMs = 0) const; + const std::shared_ptr& request, const std::variant& durationMs) const; /** * Outputs aggregated performance metrics to JSON file. @@ -151,12 +142,19 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { */ void DumpJson() const; + /** + * Writes JSON to the output file. + * @param root The JSON root object to write + */ + void WriteJsonToFile(const Aws::Utils::Json::JsonValue& root) const; + mutable Aws::Vector m_performanceRecords; Aws::Set m_monitoredOperations; Aws::String m_productId; Aws::String m_sdkVersion; Aws::String m_commitId; Aws::String m_outputFilename; + mutable bool m_hasInvalidLatency; }; /** diff --git a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp index 8f6b6339eaf..1c07c772a6b 100644 --- a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp +++ b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp @@ -23,11 +23,15 @@ #include #include #include +#include using namespace PerformanceTest::Reporting; struct RequestContext { - Aws::Utils::DateTime requestStartTime; + Aws::String serviceName; + Aws::String requestName; + std::shared_ptr request; + std::variant durationMs = int64_t(0); }; JsonReportingMetrics::JsonReportingMetrics(const Aws::Set& monitoredOperations, const Aws::String& productId, @@ -36,7 +40,10 @@ JsonReportingMetrics::JsonReportingMetrics(const Aws::Set& monitore m_productId(productId), m_sdkVersion(sdkVersion), m_commitId(commitId), - m_outputFilename(outputFilename) {} + m_outputFilename(outputFilename), + m_hasInvalidLatency(false) {} + +JsonReportingMetrics::~JsonReportingMetrics() { DumpJson(); } JsonReportingMetricsFactory::JsonReportingMetricsFactory(const Aws::Set& monitoredOperations, const Aws::String& productId, const Aws::String& sdkVersion, const Aws::String& commitId, @@ -47,16 +54,30 @@ JsonReportingMetricsFactory::JsonReportingMetricsFactory(const Aws::Set JsonReportingMetricsFactory::CreateMonitoringInstance() const { return Aws::MakeUnique("JsonReportingMetrics", m_monitoredOperations, m_productId, m_sdkVersion, m_commitId, m_outputFilename); } +void JsonReportingMetrics::StoreLatencyInContext(const Aws::String& serviceName, const Aws::String& requestName, + const std::shared_ptr& request, + const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void* context) const { + RequestContext* requestContext = static_cast(context); + + Aws::String const latencyKey = Aws::Monitoring::GetHttpClientMetricNameByType(Aws::Monitoring::HttpClientMetricsType::RequestLatency); + auto iterator = metricsFromCore.httpClientMetrics.find(latencyKey); + if (iterator != metricsFromCore.httpClientMetrics.end() && iterator->second > 0) { + requestContext->serviceName = serviceName; + requestContext->requestName = requestName; + requestContext->request = request; + requestContext->durationMs = iterator->second; + } else { + m_hasInvalidLatency = true; + } +} + void JsonReportingMetrics::AddPerformanceRecord(const Aws::String& serviceName, const Aws::String& requestName, - const Aws::Monitoring::CoreMetricsCollection&, - const std::shared_ptr& request, int64_t durationMs) const { + const std::shared_ptr& request, const std::variant& durationMs) const { // If no operations are registered, monitor all operations. Otherwise, only monitor registered operations if (!m_monitoredOperations.empty() && m_monitoredOperations.find(requestName) == m_monitoredOperations.end()) { return; @@ -85,8 +106,7 @@ void JsonReportingMetrics::AddPerformanceRecord(const Aws::String& serviceName, void* JsonReportingMetrics::OnRequestStarted(const Aws::String&, const Aws::String&, const std::shared_ptr&) const { - auto context = Aws::New("JsonReportingMetrics"); - context->requestStartTime = Aws::Utils::DateTime::Now(); + auto context = Aws::New("RequestContext"); return context; } @@ -94,18 +114,14 @@ void JsonReportingMetrics::OnRequestSucceeded(const Aws::String& serviceName, co const std::shared_ptr& request, const Aws::Client::HttpResponseOutcome&, const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void* context) const { - RequestContext* requestContext = static_cast(context); - int64_t durationMs = (Aws::Utils::DateTime::Now() - requestContext->requestStartTime).count(); - AddPerformanceRecord(serviceName, requestName, metricsFromCore, request, durationMs); + StoreLatencyInContext(serviceName, requestName, request, metricsFromCore, context); } void JsonReportingMetrics::OnRequestFailed(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request, const Aws::Client::HttpResponseOutcome&, const Aws::Monitoring::CoreMetricsCollection& metricsFromCore, void* context) const { - RequestContext* requestContext = static_cast(context); - int64_t durationMs = (Aws::Utils::DateTime::Now() - requestContext->requestStartTime).count(); - AddPerformanceRecord(serviceName, requestName, metricsFromCore, request, durationMs); + StoreLatencyInContext(serviceName, requestName, request, metricsFromCore, context); } void JsonReportingMetrics::OnRequestRetry(const Aws::String&, const Aws::String&, const std::shared_ptr&, @@ -114,11 +130,24 @@ void JsonReportingMetrics::OnRequestRetry(const Aws::String&, const Aws::String& void JsonReportingMetrics::OnFinish(const Aws::String&, const Aws::String&, const std::shared_ptr&, void* context) const { RequestContext* requestContext = static_cast(context); + + if (std::visit([](auto&& v) { return v > 0; }, requestContext->durationMs)) { + AddPerformanceRecord(requestContext->serviceName, requestContext->requestName, requestContext->request, requestContext->durationMs); + } + Aws::Delete(requestContext); } void JsonReportingMetrics::DumpJson() const { - if (m_performanceRecords.empty()) { + Aws::Utils::Json::JsonValue root; + root.WithString("productId", m_productId); + root.WithString("sdkVersion", m_sdkVersion); + root.WithString("commitId", m_commitId); + + // If there is an invalid latency or there are no records, then use an empty results array + if (m_hasInvalidLatency || m_performanceRecords.empty()) { + root.WithArray("results", Aws::Utils::Array(0)); + WriteJsonToFile(root); return; } @@ -140,12 +169,6 @@ void JsonReportingMetrics::DumpJson() const { } } - // Create the JSON output - Aws::Utils::Json::JsonValue root; - root.WithString("productId", m_productId); - root.WithString("sdkVersion", m_sdkVersion); - root.WithString("commitId", m_commitId); - Aws::Utils::Array results(aggregatedRecords.size()); size_t index = 0; @@ -172,10 +195,10 @@ void JsonReportingMetrics::DumpJson() const { Aws::Utils::Array measurementsArray(record.measurements.size()); for (size_t measurementIndex = 0; measurementIndex < record.measurements.size(); ++measurementIndex) { Aws::Utils::Json::JsonValue measurementValue; - if (record.measurements[measurementIndex].IsDouble()) { - measurementValue.AsDouble(record.measurements[measurementIndex].AsDouble()); + if (std::holds_alternative(record.measurements[measurementIndex])) { + measurementValue.AsDouble(std::get(record.measurements[measurementIndex])); } else { - measurementValue.AsInt64(record.measurements[measurementIndex].AsInt64()); + measurementValue.AsInt64(std::get(record.measurements[measurementIndex])); } measurementsArray[measurementIndex] = std::move(measurementValue); } @@ -185,7 +208,10 @@ void JsonReportingMetrics::DumpJson() const { } root.WithArray("results", std::move(results)); + WriteJsonToFile(root); +} +void JsonReportingMetrics::WriteJsonToFile(const Aws::Utils::Json::JsonValue& root) const { std::ofstream outFile(m_outputFilename.c_str()); if (outFile.is_open()) { outFile << root.View().WriteReadable(); From 64a18af0fabe76c874a575b614918a56f742e0a8 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Fri, 27 Jun 2025 14:53:06 -0400 Subject: [PATCH 31/77] clang formatting --- tests/performance-tests/src/reporting/JsonReportingMetrics.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp index 1c07c772a6b..1c4df4a7742 100644 --- a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp +++ b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp @@ -77,7 +77,8 @@ void JsonReportingMetrics::StoreLatencyInContext(const Aws::String& serviceName, } void JsonReportingMetrics::AddPerformanceRecord(const Aws::String& serviceName, const Aws::String& requestName, - const std::shared_ptr& request, const std::variant& durationMs) const { + const std::shared_ptr& request, + const std::variant& durationMs) const { // If no operations are registered, monitor all operations. Otherwise, only monitor registered operations if (!m_monitoredOperations.empty() && m_monitoredOperations.find(requestName) == m_monitoredOperations.end()) { return; From 0fe1876d933725a41baf3c4b05e45b8ed71ec510 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Fri, 27 Jun 2025 15:10:57 -0400 Subject: [PATCH 32/77] fix formatting --- .../include/performance-tests/reporting/JsonReportingMetrics.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h b/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h index dbd76e60890..87ebb6d9374 100644 --- a/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h +++ b/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h @@ -134,7 +134,8 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { * @param durationMs Duration of the request in milliseconds */ void AddPerformanceRecord(const Aws::String& serviceName, const Aws::String& requestName, - const std::shared_ptr& request, const std::variant& durationMs) const; + const std::shared_ptr& request, + const std::variant& durationMs) const; /** * Outputs aggregated performance metrics to JSON file. From 42a6ba576a2477cdc1289d07651b14dba6a61ff2 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Mon, 30 Jun 2025 00:31:49 -0400 Subject: [PATCH 33/77] refine code structure of s3 and dynamodb --- .../include/performance-tests/Utils.h | 71 +++++++++++++++++++ .../dynamodb/DynamoDBPerformanceTest.h | 27 ++++++- .../services/s3/S3PerformanceTest.h | 31 +++++++- .../dynamodb/DynamoDBPerformanceTest.cpp | 45 +++++++----- .../src/services/dynamodb/main.cpp | 7 +- .../src/services/s3/S3PerformanceTest.cpp | 60 ++++++++++------ .../src/services/s3/main.cpp | 7 +- 7 files changed, 197 insertions(+), 51 deletions(-) create mode 100644 tests/performance-tests/include/performance-tests/Utils.h diff --git a/tests/performance-tests/include/performance-tests/Utils.h b/tests/performance-tests/include/performance-tests/Utils.h new file mode 100644 index 00000000000..1cc56c7eadd --- /dev/null +++ b/tests/performance-tests/include/performance-tests/Utils.h @@ -0,0 +1,71 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace PerformanceTest { +namespace Utils { +/** + * Generate a random string of specified length. + * @param length The desired length of the string + * @return A random string containing lowercase letters and digits + */ +static inline Aws::String RandomString(size_t length) { + auto randchar = []() -> char { + const char charset[] = + "0123456789" + "abcdefghijklmnopqrstuvwxyz"; + const size_t max_index = (sizeof(charset) - 1); + return charset[rand() % max_index]; + }; + Aws::String str(length, 0); + std::generate_n(str.begin(), length, randchar); + return str; +} + +/** + * Log error messages to stderr. + * @param service The name of the AWS service + * @param operation The name of the operation that failed + * @param message The error message to log + */ +static inline void LogError(const Aws::String& service, const Aws::String& operation, const Aws::String& message) { + std::cerr << "[ERROR] " << service << ":" << operation << " failed: " << message << '\n'; +} + +/** + * Generate a unique identifier using UUID. + * @return A 10-character lowercase UUID substring + */ +static inline Aws::String GenerateUniqueId() { + Aws::String const rawUUID = Aws::Utils::UUID::RandomUUID(); + return Aws::Utils::StringUtils::ToLower(rawUUID.c_str()).substr(0, 10); +} + +/** + * Get the current SDK version as a formatted string. + * @return SDK version in the format "major.minor.patch" (e.g., "1.11.0") + */ +static inline Aws::String GetSDKVersionString() { + Aws::SDKOptions::SDKVersion const version; + return Aws::Utils::StringUtils::to_string(static_cast(version.major)) + "." + + Aws::Utils::StringUtils::to_string(static_cast(version.minor)) + "." + + Aws::Utils::StringUtils::to_string(static_cast(version.patch)); +} + +} // namespace Utils +} // namespace PerformanceTest \ No newline at end of file diff --git a/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h index 78b02c19ae4..3384db60473 100644 --- a/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h +++ b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h @@ -27,9 +27,32 @@ struct TestCase { * @param dynamodb DynamoDB client instance to use for operations * @param config Test configuration containing size parameters * @param iterations Number of put/get operations to perform - * @return true if test completed successfully, false on error */ -bool RunTest(Aws::DynamoDB::DynamoDBClient& dynamodb, const TestCase& config, int iterations = 3); +void RunTest(Aws::DynamoDB::DynamoDBClient& dynamodb, const TestCase& config, int iterations = 3); + +/** + * Create DynamoDB table for testing and wait for it to become active. + * @param dynamodb DynamoDB client instance + * @param config Test configuration + * @return Table name if successful, empty string if failed + */ +Aws::String SetupTable(Aws::DynamoDB::DynamoDBClient& dynamodb, const TestCase& config); + +/** + * Run PutItem and GetItem operations. + * @param dynamodb DynamoDB client instance + * @param tableName Name of the table to use + * @param config Test configuration + * @param iterations Number of operations to perform + */ +void RunOperations(Aws::DynamoDB::DynamoDBClient& dynamodb, const Aws::String& tableName, const TestCase& config, int iterations); + +/** + * Clean up DynamoDB resources (delete table). + * @param dynamodb DynamoDB client instance + * @param tableName Name of the table to delete + */ +void CleanupResources(Aws::DynamoDB::DynamoDBClient& dynamodb, const Aws::String& tableName); } // namespace DynamoDB } // namespace Services } // namespace PerformanceTest \ No newline at end of file diff --git a/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h b/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h index 08452f004ac..a53ccc7add7 100644 --- a/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h +++ b/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h @@ -26,12 +26,37 @@ struct TestCase { * Runs S3 performance test by creating a bucket, performing PutObject and GetObject operations, * then cleaning up resources. * @param s3 S3 client instance to use for operations - * @param config Test configuration containing size and bucket type parameters + * @param config Test configuration containing object size and bucket type parameters * @param availabilityZoneId Availability zone ID for S3 Express buckets * @param iterations Number of put/get operations to perform - * @return true if test completed successfully, false on error */ -bool RunTest(Aws::S3::S3Client& s3, const TestCase& config, const Aws::String& availabilityZoneId, int iterations = 3); +void RunTest(Aws::S3::S3Client& s3, const TestCase& config, const Aws::String& availabilityZoneId, int iterations = 3); + +/** + * Create S3 bucket for testing. + * @param s3 S3 client instance + * @param config Test configuration + * @param availabilityZoneId Availability zone ID for S3 Express buckets + * @return Bucket name if successful, empty string if failed + */ +Aws::String SetupBucket(Aws::S3::S3Client& s3, const TestCase& config, const Aws::String& availabilityZoneId); + +/** + * Run PutObject and GetObject operations. + * @param s3 S3 client instance + * @param bucketName Name of the bucket to use + * @param config Test configuration + * @param iterations Number of operations to perform + */ +void RunOperations(Aws::S3::S3Client& s3, const Aws::String& bucketName, const TestCase& config, int iterations); + +/** + * Clean up S3 resources (objects and bucket). + * @param s3 S3 client instance + * @param bucketName Name of the bucket to clean up + * @param iterations Number of objects to delete + */ +void CleanupResources(Aws::S3::S3Client& s3, const Aws::String& bucketName, int iterations); } // namespace S3 } // namespace Services } // namespace PerformanceTest \ No newline at end of file diff --git a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp index a9ab4c8591a..f5be8255387 100644 --- a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp +++ b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp @@ -4,7 +4,6 @@ */ #include -#include #include #include #include @@ -20,19 +19,25 @@ #include #include #include -#include +#include #include #include -#include #include #include -bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& dynamodb, const TestCase& config, int iterations) { - Aws::String tableName; - Aws::String const rawUUID = Aws::Utils::UUID::RandomUUID(); - Aws::String const tableId = Aws::Utils::StringUtils::ToLower(rawUUID.c_str()).substr(0, 8); - tableName = "perf-table-" + tableId; +void PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& dynamodb, const TestCase& config, int iterations) { + auto tableName = SetupTable(dynamodb, config); + if (tableName.empty()) { + return; + } + + RunOperations(dynamodb, tableName, config, iterations); + CleanupResources(dynamodb, tableName); +} + +Aws::String PerformanceTest::Services::DynamoDB::SetupTable(Aws::DynamoDB::DynamoDBClient& dynamodb, const TestCase& /* config */) { + Aws::String tableName = "perf-table-" + PerformanceTest::Utils::GenerateUniqueId(); Aws::DynamoDB::Model::CreateTableRequest createTableRequest; createTableRequest.SetTableName(tableName); @@ -51,8 +56,8 @@ bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& auto createTableOutcome = dynamodb.CreateTable(createTableRequest); if (!createTableOutcome.IsSuccess()) { - std::cerr << "[ERROR] CreateTable failed: " << createTableOutcome.GetError().GetMessage() << '\n'; - return false; + PerformanceTest::Utils::LogError("DynamoDB", "CreateTable", createTableOutcome.GetError().GetMessage()); + return ""; } // Wait for table to become active @@ -70,7 +75,12 @@ bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& std::this_thread::sleep_for(std::chrono::seconds(1)); } - Aws::String const payload(config.sizeBytes, 'x'); + return tableName; +} + +void PerformanceTest::Services::DynamoDB::RunOperations(Aws::DynamoDB::DynamoDBClient& dynamodb, const Aws::String& tableName, + const TestCase& config, int iterations) { + const auto payload = PerformanceTest::Utils::RandomString(config.sizeBytes); // Run PutItem multiple times for (int i = 0; i < iterations; i++) { @@ -85,7 +95,7 @@ bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& auto putItemOutcome = dynamodb.PutItem(putItemRequest); if (!putItemOutcome.IsSuccess()) { - std::cerr << "[ERROR] PutItem failed: " << putItemOutcome.GetError().GetMessage() << '\n'; + PerformanceTest::Utils::LogError("DynamoDB", "PutItem", putItemOutcome.GetError().GetMessage()); } } @@ -101,13 +111,16 @@ bool PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& auto getItemOutcome = dynamodb.GetItem(getItemRequest); if (!getItemOutcome.IsSuccess()) { - std::cerr << "[ERROR] GetItem failed: " << getItemOutcome.GetError().GetMessage() << '\n'; + PerformanceTest::Utils::LogError("DynamoDB", "GetItem", getItemOutcome.GetError().GetMessage()); } } +} +void PerformanceTest::Services::DynamoDB::CleanupResources(Aws::DynamoDB::DynamoDBClient& dynamodb, const Aws::String& tableName) { Aws::DynamoDB::Model::DeleteTableRequest deleteTableRequest; deleteTableRequest.SetTableName(tableName); - dynamodb.DeleteTable(deleteTableRequest); - - return true; + auto deleteTableOutcome = dynamodb.DeleteTable(deleteTableRequest); + if (!deleteTableOutcome.IsSuccess()) { + PerformanceTest::Utils::LogError("DynamoDB", "DeleteTable", deleteTableOutcome.GetError().GetMessage()); + } } \ No newline at end of file diff --git a/tests/performance-tests/src/services/dynamodb/main.cpp b/tests/performance-tests/src/services/dynamodb/main.cpp index e9e291ef72f..5e7c7e2fc81 100644 --- a/tests/performance-tests/src/services/dynamodb/main.cpp +++ b/tests/performance-tests/src/services/dynamodb/main.cpp @@ -6,10 +6,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include @@ -33,10 +33,7 @@ int main(int argc, char** argv) { } Aws::SDKOptions options; - Aws::SDKOptions::SDKVersion const version; - Aws::String const versionStr = Aws::Utils::StringUtils::to_string(static_cast(version.major)) + "." + - Aws::Utils::StringUtils::to_string(static_cast(version.minor)) + "." + - Aws::Utils::StringUtils::to_string(static_cast(version.patch)); + Aws::String const versionStr = PerformanceTest::Utils::GetSDKVersionString(); options.monitoringOptions.customizedMonitoringFactory_create_fn = {[&]() -> Aws::UniquePtr { return Aws::MakeUnique( diff --git a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp index bc0cb8aeb66..98102c97cd0 100644 --- a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp +++ b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp @@ -3,12 +3,8 @@ * SPDX-License-Identifier: Apache-2.0. */ -#include "performance-tests/services/s3/S3PerformanceTest.h" - #include -#include #include -#include #include #include #include @@ -22,17 +18,27 @@ #include #include #include -#include +#include +#include -#include #include -bool PerformanceTest::Services::S3::RunTest(Aws::S3::S3Client& s3, const TestCase& config, const Aws::String& availabilityZoneId, +void PerformanceTest::Services::S3::RunTest(Aws::S3::S3Client& s3, const TestCase& config, const Aws::String& availabilityZoneId, int iterations) { + auto bucketName = SetupBucket(s3, config, availabilityZoneId); + if (bucketName.empty()) { + return; + } + + RunOperations(s3, bucketName, config, iterations); + CleanupResources(s3, bucketName, iterations); +} + +Aws::String PerformanceTest::Services::S3::SetupBucket(Aws::S3::S3Client& s3, const TestCase& config, + const Aws::String& availabilityZoneId) { Aws::String bucketName; Aws::S3::Model::CreateBucketRequest cbr; - Aws::String const rawUUID = Aws::Utils::UUID::RandomUUID(); - Aws::String const bucketId = Aws::Utils::StringUtils::ToLower(rawUUID.c_str()).substr(0, 8); + Aws::String const bucketId = PerformanceTest::Utils::GenerateUniqueId(); if (config.bucketTypeLabel == "s3-express") { bucketName = "perf-express-" + bucketId + "--" + availabilityZoneId + "--x-s3"; @@ -53,23 +59,29 @@ bool PerformanceTest::Services::S3::RunTest(Aws::S3::S3Client& s3, const TestCas auto createOutcome = s3.CreateBucket(cbr); if (!createOutcome.IsSuccess()) { - std::cerr << "[ERROR] CreateBucket failed for " << bucketName << ": " << createOutcome.GetError().GetMessage() << '\n'; - return false; + PerformanceTest::Utils::LogError("S3", "CreateBucket", createOutcome.GetError().GetMessage()); + return ""; } - Aws::String const payload(config.sizeBytes, 'x'); + return bucketName; +} + +void PerformanceTest::Services::S3::RunOperations(Aws::S3::S3Client& s3, const Aws::String& bucketName, const TestCase& config, + int iterations) { + const auto randomPayload = PerformanceTest::Utils::RandomString(config.sizeBytes); // Run PutObject multiple times for (int i = 0; i < iterations; i++) { auto stream = Aws::MakeShared("PerfStream"); - *stream << payload; + *stream << randomPayload; Aws::S3::Model::PutObjectRequest por; por.WithBucket(bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i)).SetBody(stream); por.SetAdditionalCustomHeaderValue("test-dimension-size", config.sizeLabel); por.SetAdditionalCustomHeaderValue("test-dimension-bucket-type", config.bucketTypeLabel); - if (!s3.PutObject(por).IsSuccess()) { - std::cerr << "[ERROR] PutObject failed!" << '\n'; + auto putOutcome = s3.PutObject(por); + if (!putOutcome.IsSuccess()) { + PerformanceTest::Utils::LogError("S3", "PutObject", putOutcome.GetError().GetMessage()); } } @@ -79,16 +91,24 @@ bool PerformanceTest::Services::S3::RunTest(Aws::S3::S3Client& s3, const TestCas gor.WithBucket(bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i)); gor.SetAdditionalCustomHeaderValue("test-dimension-size", config.sizeLabel); gor.SetAdditionalCustomHeaderValue("test-dimension-bucket-type", config.bucketTypeLabel); - if (!s3.GetObject(gor).IsSuccess()) { - std::cerr << "[ERROR] GetObject failed!" << '\n'; + auto getOutcome = s3.GetObject(gor); + if (!getOutcome.IsSuccess()) { + PerformanceTest::Utils::LogError("S3", "GetObject", getOutcome.GetError().GetMessage()); } } +} +void PerformanceTest::Services::S3::CleanupResources(Aws::S3::S3Client& s3, const Aws::String& bucketName, int iterations) { for (int i = 0; i < iterations; i++) { - s3.DeleteObject( + auto deleteObjectOutcome = s3.DeleteObject( Aws::S3::Model::DeleteObjectRequest().WithBucket(bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i))); + if (!deleteObjectOutcome.IsSuccess()) { + PerformanceTest::Utils::LogError("S3", "DeleteObject", deleteObjectOutcome.GetError().GetMessage()); + } } - s3.DeleteBucket(Aws::S3::Model::DeleteBucketRequest().WithBucket(bucketName)); - return true; + auto deleteBucketOutcome = s3.DeleteBucket(Aws::S3::Model::DeleteBucketRequest().WithBucket(bucketName)); + if (!deleteBucketOutcome.IsSuccess()) { + PerformanceTest::Utils::LogError("S3", "DeleteBucket", deleteBucketOutcome.GetError().GetMessage()); + } } \ No newline at end of file diff --git a/tests/performance-tests/src/services/s3/main.cpp b/tests/performance-tests/src/services/s3/main.cpp index 33cb2efe71b..914d67e7550 100644 --- a/tests/performance-tests/src/services/s3/main.cpp +++ b/tests/performance-tests/src/services/s3/main.cpp @@ -6,10 +6,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include @@ -36,10 +36,7 @@ int main(int argc, char** argv) { } Aws::SDKOptions options; - Aws::SDKOptions::SDKVersion const version; - Aws::String const versionStr = Aws::Utils::StringUtils::to_string(static_cast(version.major)) + "." + - Aws::Utils::StringUtils::to_string(static_cast(version.minor)) + "." + - Aws::Utils::StringUtils::to_string(static_cast(version.patch)); + Aws::String const versionStr = PerformanceTest::Utils::GetSDKVersionString(); options.monitoringOptions.customizedMonitoringFactory_create_fn = {[&]() -> Aws::UniquePtr { return Aws::MakeUnique( From 3de9407ef1c529015811d43c373e156ef0476e0e Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Mon, 30 Jun 2025 12:36:40 -0400 Subject: [PATCH 34/77] remove unused headers --- .../src/services/dynamodb/DynamoDBPerformanceTest.cpp | 1 - tests/performance-tests/src/services/s3/S3PerformanceTest.cpp | 2 -- 2 files changed, 3 deletions(-) diff --git a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp index f5be8255387..63514076d8e 100644 --- a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp +++ b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp @@ -23,7 +23,6 @@ #include #include -#include #include void PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& dynamodb, const TestCase& config, int iterations) { diff --git a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp index 98102c97cd0..4b21d159ff8 100644 --- a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp +++ b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp @@ -21,8 +21,6 @@ #include #include -#include - void PerformanceTest::Services::S3::RunTest(Aws::S3::S3Client& s3, const TestCase& config, const Aws::String& availabilityZoneId, int iterations) { auto bucketName = SetupBucket(s3, config, availabilityZoneId); From 1fcf4b67b37e230629c8625f4cfb4669a5bd9667 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Tue, 1 Jul 2025 11:01:13 -0400 Subject: [PATCH 35/77] include testing-resources in performance tests --- tests/performance-tests/CMakeLists.txt | 1 + tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh | 2 +- tools/scripts/build-tests/run-al2-s3-performance-tests.sh | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/performance-tests/CMakeLists.txt b/tests/performance-tests/CMakeLists.txt index 5660c9e1438..ef1adca899b 100644 --- a/tests/performance-tests/CMakeLists.txt +++ b/tests/performance-tests/CMakeLists.txt @@ -7,6 +7,7 @@ add_project(performance-tests aws-cpp-sdk-core aws-cpp-sdk-s3 aws-cpp-sdk-dynamodb + testing-resources ) function(add_service_test SERVICE SDK_LIB PERF_TEST_FILE) diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index 44125b24372..6747223b990 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -23,7 +23,7 @@ while [[ "$#" -gt 0 ]]; do esac done -export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/:${PREFIX_DIR}/al2-build/tests/testing-resources/" SDK_REPO_PATH="${PREFIX_DIR}/aws-sdk-cpp" if [ -d "$SDK_REPO_PATH" ]; then diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index a2c737d1e1f..10b447c6f85 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -26,7 +26,7 @@ while [[ "$#" -gt 0 ]]; do esac done -export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/:${PREFIX_DIR}/al2-build/tests/testing-resources/" SDK_REPO_PATH="${PREFIX_DIR}/aws-sdk-cpp" if [ -d "$SDK_REPO_PATH" ]; then From 876962e32519d48805c974f81cdee62b42c87317 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Tue, 1 Jul 2025 11:59:37 -0400 Subject: [PATCH 36/77] try to fix dylb --- tests/performance-tests/CMakeLists.txt | 1 - .../reporting/JsonReportingMetrics.h | 1 - .../src/reporting/JsonReportingMetrics.cpp | 11 +++++------ .../build-tests/run-al2-dynamodb-performance-tests.sh | 4 +++- .../build-tests/run-al2-s3-performance-tests.sh | 4 +++- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/tests/performance-tests/CMakeLists.txt b/tests/performance-tests/CMakeLists.txt index ef1adca899b..5660c9e1438 100644 --- a/tests/performance-tests/CMakeLists.txt +++ b/tests/performance-tests/CMakeLists.txt @@ -7,7 +7,6 @@ add_project(performance-tests aws-cpp-sdk-core aws-cpp-sdk-s3 aws-cpp-sdk-dynamodb - testing-resources ) function(add_service_test SERVICE SDK_LIB PERF_TEST_FILE) diff --git a/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h b/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h index 87ebb6d9374..9320e3caca6 100644 --- a/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h +++ b/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h @@ -155,7 +155,6 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { Aws::String m_sdkVersion; Aws::String m_commitId; Aws::String m_outputFilename; - mutable bool m_hasInvalidLatency; }; /** diff --git a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp index 1c4df4a7742..997d4d9ec68 100644 --- a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp +++ b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp @@ -32,6 +32,7 @@ struct RequestContext { Aws::String requestName; std::shared_ptr request; std::variant durationMs = int64_t(0); + bool failed = false; }; JsonReportingMetrics::JsonReportingMetrics(const Aws::Set& monitoredOperations, const Aws::String& productId, @@ -40,8 +41,7 @@ JsonReportingMetrics::JsonReportingMetrics(const Aws::Set& monitore m_productId(productId), m_sdkVersion(sdkVersion), m_commitId(commitId), - m_outputFilename(outputFilename), - m_hasInvalidLatency(false) {} + m_outputFilename(outputFilename) {} JsonReportingMetrics::~JsonReportingMetrics() { DumpJson(); } @@ -72,7 +72,7 @@ void JsonReportingMetrics::StoreLatencyInContext(const Aws::String& serviceName, requestContext->request = request; requestContext->durationMs = iterator->second; } else { - m_hasInvalidLatency = true; + requestContext->failed = true; } } @@ -132,7 +132,7 @@ void JsonReportingMetrics::OnFinish(const Aws::String&, const Aws::String&, cons void* context) const { RequestContext* requestContext = static_cast(context); - if (std::visit([](auto&& v) { return v > 0; }, requestContext->durationMs)) { + if (!requestContext->failed) { AddPerformanceRecord(requestContext->serviceName, requestContext->requestName, requestContext->request, requestContext->durationMs); } @@ -145,8 +145,7 @@ void JsonReportingMetrics::DumpJson() const { root.WithString("sdkVersion", m_sdkVersion); root.WithString("commitId", m_commitId); - // If there is an invalid latency or there are no records, then use an empty results array - if (m_hasInvalidLatency || m_performanceRecords.empty()) { + if (m_performanceRecords.empty()) { root.WithArray("results", Aws::Utils::Array(0)); WriteJsonToFile(root); return; diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index 6747223b990..d233863f108 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -23,7 +23,9 @@ while [[ "$#" -gt 0 ]]; do esac done -export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/:${PREFIX_DIR}/al2-build/tests/testing-resources/" +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" +cd "${PREFIX_DIR}/al2-build" +if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi SDK_REPO_PATH="${PREFIX_DIR}/aws-sdk-cpp" if [ -d "$SDK_REPO_PATH" ]; then diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index 10b447c6f85..166386ec7f4 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -26,7 +26,9 @@ while [[ "$#" -gt 0 ]]; do esac done -export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/:${PREFIX_DIR}/al2-build/tests/testing-resources/" +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" +cd "${PREFIX_DIR}/al2-build" +if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi SDK_REPO_PATH="${PREFIX_DIR}/aws-sdk-cpp" if [ -d "$SDK_REPO_PATH" ]; then From c7eb7cdbef3f4308ad0949eec7255a21849aa8cd Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Tue, 1 Jul 2025 13:35:04 -0400 Subject: [PATCH 37/77] try to fix asan --- .../build-tests/run-al2-dynamodb-performance-tests.sh | 7 +++---- tools/scripts/build-tests/run-al2-s3-performance-tests.sh | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index d233863f108..116cf0d1600 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -23,10 +23,6 @@ while [[ "$#" -gt 0 ]]; do esac done -export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" -cd "${PREFIX_DIR}/al2-build" -if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi - SDK_REPO_PATH="${PREFIX_DIR}/aws-sdk-cpp" if [ -d "$SDK_REPO_PATH" ]; then cd "$SDK_REPO_PATH" @@ -36,5 +32,8 @@ else COMMIT_ID="unknown" fi +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" +if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi + ./dynamodb-performance-test --region "$REGION" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" cat dynamodb-performance-test-results.json \ No newline at end of file diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index 166386ec7f4..aab788f42e9 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -26,10 +26,6 @@ while [[ "$#" -gt 0 ]]; do esac done -export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" -cd "${PREFIX_DIR}/al2-build" -if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi - SDK_REPO_PATH="${PREFIX_DIR}/aws-sdk-cpp" if [ -d "$SDK_REPO_PATH" ]; then cd "$SDK_REPO_PATH" @@ -39,5 +35,8 @@ else COMMIT_ID="unknown" fi +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" +if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi + ./s3-performance-test --region "$REGION" --az-id "$AZ_ID" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" cat s3-performance-test-results.json \ No newline at end of file From ff10998851884aad58c838809e88fd00aeb97cb7 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Tue, 1 Jul 2025 14:00:28 -0400 Subject: [PATCH 38/77] refine renaming of operation varaiables --- .../performance-tests/services/dynamodb/DynamoDBTestConfig.h | 2 +- .../include/performance-tests/services/s3/S3TestConfig.h | 2 +- tests/performance-tests/src/services/dynamodb/main.cpp | 2 +- tests/performance-tests/src/services/s3/main.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h index f8f13910c92..ea2fc1c2a39 100644 --- a/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h +++ b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h @@ -13,7 +13,7 @@ namespace PerformanceTest { namespace Services { namespace DynamoDB { namespace TestConfig { -const Aws::Set Operations = {"PutItem", "GetItem"}; +const Aws::Set TestOperations = {"PutItem", "GetItem"}; const Aws::Vector TestMatrix = {{"8KB", 8 * 1024}, {"64KB", 64 * 1024}, {"392KB", 392 * 1024}}; diff --git a/tests/performance-tests/include/performance-tests/services/s3/S3TestConfig.h b/tests/performance-tests/include/performance-tests/services/s3/S3TestConfig.h index 256a493cbbe..0ed0ada66d2 100644 --- a/tests/performance-tests/include/performance-tests/services/s3/S3TestConfig.h +++ b/tests/performance-tests/include/performance-tests/services/s3/S3TestConfig.h @@ -13,7 +13,7 @@ namespace PerformanceTest { namespace Services { namespace S3 { namespace TestConfig { -const Aws::Set Operations = {"PutObject", "GetObject"}; +const Aws::Set TestOperations = {"PutObject", "GetObject"}; const Aws::Vector TestMatrix = {{"8KB", 8 * 1024, "s3-standard"}, {"64KB", 64 * 1024, "s3-standard"}, {"1MB", 1024 * 1024, "s3-standard"}, {"8KB", 8 * 1024, "s3-express"}, diff --git a/tests/performance-tests/src/services/dynamodb/main.cpp b/tests/performance-tests/src/services/dynamodb/main.cpp index 5e7c7e2fc81..26d5415a9fd 100644 --- a/tests/performance-tests/src/services/dynamodb/main.cpp +++ b/tests/performance-tests/src/services/dynamodb/main.cpp @@ -37,7 +37,7 @@ int main(int argc, char** argv) { options.monitoringOptions.customizedMonitoringFactory_create_fn = {[&]() -> Aws::UniquePtr { return Aws::MakeUnique( - "JsonReportingMetricsFactory", PerformanceTest::Services::DynamoDB::TestConfig::Operations, "cpp1", versionStr, commitId, + "JsonReportingMetricsFactory", PerformanceTest::Services::DynamoDB::TestConfig::TestOperations, "cpp1", versionStr, commitId, PerformanceTest::Services::DynamoDB::TestConfig::OutputFilename); }}; diff --git a/tests/performance-tests/src/services/s3/main.cpp b/tests/performance-tests/src/services/s3/main.cpp index 914d67e7550..157dee1b120 100644 --- a/tests/performance-tests/src/services/s3/main.cpp +++ b/tests/performance-tests/src/services/s3/main.cpp @@ -40,7 +40,7 @@ int main(int argc, char** argv) { options.monitoringOptions.customizedMonitoringFactory_create_fn = {[&]() -> Aws::UniquePtr { return Aws::MakeUnique( - "JsonReportingMetricsFactory", PerformanceTest::Services::S3::TestConfig::Operations, "cpp1", versionStr, commitId, + "JsonReportingMetricsFactory", PerformanceTest::Services::S3::TestConfig::TestOperations, "cpp1", versionStr, commitId, PerformanceTest::Services::S3::TestConfig::OutputFilename); }}; From f828d52be70862ff00aa2edf80d6002628ff0a09 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Tue, 1 Jul 2025 14:22:24 -0400 Subject: [PATCH 39/77] try to fix perf test scripts again --- .../scripts/build-tests/run-al2-dynamodb-performance-tests.sh | 3 ++- tools/scripts/build-tests/run-al2-s3-performance-tests.sh | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index 116cf0d1600..b1cb5e51fb4 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -33,7 +33,8 @@ else fi export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" +cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi -./dynamodb-performance-test --region "$REGION" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" +./tests/performance-tests/dynamodb-performance-test --region "$REGION" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" cat dynamodb-performance-test-results.json \ No newline at end of file diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index aab788f42e9..86e06a2905c 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -36,7 +36,8 @@ else fi export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" +cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi -./s3-performance-test --region "$REGION" --az-id "$AZ_ID" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" +./tests/performance-tests/s3-performance-test --region "$REGION" --az-id "$AZ_ID" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" cat s3-performance-test-results.json \ No newline at end of file From 8501f9c1c52ec07d06739b73396001894362d45f Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Tue, 1 Jul 2025 15:05:25 -0400 Subject: [PATCH 40/77] try to fix LD_LIBRARY_PATH again --- tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh | 2 +- tools/scripts/build-tests/run-al2-s3-performance-tests.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index b1cb5e51fb4..3de620fdbe3 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -32,7 +32,7 @@ else COMMIT_ID="unknown" fi -export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/:${PREFIX_DIR}/al2-build/lib:/lib64:/lib" cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index 86e06a2905c..ee73dfa451f 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -35,7 +35,7 @@ else COMMIT_ID="unknown" fi -export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/:${PREFIX_DIR}/al2-build/lib:/lib64:/lib" cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi From eb5de745a2526b63d69f360341537c50dd2ce0ab Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Tue, 1 Jul 2025 15:32:46 -0400 Subject: [PATCH 41/77] perf test script not print unncessary file path --- tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh | 2 +- tools/scripts/build-tests/run-al2-s3-performance-tests.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index 3de620fdbe3..3e27601ea5f 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -27,7 +27,7 @@ SDK_REPO_PATH="${PREFIX_DIR}/aws-sdk-cpp" if [ -d "$SDK_REPO_PATH" ]; then cd "$SDK_REPO_PATH" COMMIT_ID=$(git rev-parse HEAD) - cd - + cd - > /dev/null else COMMIT_ID="unknown" fi diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index ee73dfa451f..9c53693db24 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -30,7 +30,7 @@ SDK_REPO_PATH="${PREFIX_DIR}/aws-sdk-cpp" if [ -d "$SDK_REPO_PATH" ]; then cd "$SDK_REPO_PATH" COMMIT_ID=$(git rev-parse HEAD) - cd - + cd - > /dev/null else COMMIT_ID="unknown" fi From 4c31a4e25878badd37fdc114cc01ae0e5dcbd7b0 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Tue, 1 Jul 2025 15:39:15 -0400 Subject: [PATCH 42/77] remove redundant cd command --- .../scripts/build-tests/run-al2-dynamodb-performance-tests.sh | 4 +--- tools/scripts/build-tests/run-al2-s3-performance-tests.sh | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index 3e27601ea5f..9a450b87574 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -25,9 +25,7 @@ done SDK_REPO_PATH="${PREFIX_DIR}/aws-sdk-cpp" if [ -d "$SDK_REPO_PATH" ]; then - cd "$SDK_REPO_PATH" - COMMIT_ID=$(git rev-parse HEAD) - cd - > /dev/null + COMMIT_ID=$(cd "$SDK_REPO_PATH" && git rev-parse HEAD) else COMMIT_ID="unknown" fi diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index 9c53693db24..d216d6ccace 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -28,9 +28,7 @@ done SDK_REPO_PATH="${PREFIX_DIR}/aws-sdk-cpp" if [ -d "$SDK_REPO_PATH" ]; then - cd "$SDK_REPO_PATH" - COMMIT_ID=$(git rev-parse HEAD) - cd - > /dev/null + COMMIT_ID=$(cd "$SDK_REPO_PATH" && git rev-parse HEAD) else COMMIT_ID="unknown" fi From f9825edb084fd42011ce045f668f43ea095dcdef Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Tue, 1 Jul 2025 16:23:25 -0400 Subject: [PATCH 43/77] another trial about LD_LIBRARY_PATH --- tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh | 2 +- tools/scripts/build-tests/run-al2-s3-performance-tests.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index 9a450b87574..077694c90d5 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -30,7 +30,7 @@ else COMMIT_ID="unknown" fi -export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/:${PREFIX_DIR}/al2-build/lib:/lib64:/lib" +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-build/lib:${PREFIX_DIR}/al2-build/tests/testing-resources:/lib64:/lib:/usr/lib64:/usr/lib" cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index d216d6ccace..5a74ae6d7cb 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -33,7 +33,7 @@ else COMMIT_ID="unknown" fi -export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/:${PREFIX_DIR}/al2-build/lib:/lib64:/lib" +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-build/lib:${PREFIX_DIR}/al2-build/tests/testing-resources:/lib64:/lib:/usr/lib64:/usr/lib" cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi From 938f4723c709c18f922da9648afa2f617c544a9c Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Wed, 2 Jul 2025 00:44:31 -0400 Subject: [PATCH 44/77] add exact paths of dynamic libs --- tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh | 2 +- tools/scripts/build-tests/run-al2-s3-performance-tests.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index 077694c90d5..0da14527d41 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -30,7 +30,7 @@ else COMMIT_ID="unknown" fi -export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-build/lib:${PREFIX_DIR}/al2-build/tests/testing-resources:/lib64:/lib:/usr/lib64:/usr/lib" +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-build/generated/src/aws-cpp-sdk-dynamodb:${PREFIX_DIR}/al2-build/src/aws-cpp-sdk-core:${PREFIX_DIR}/al2-build/crt/aws-crt-cpp:${PREFIX_DIR}/al2-build/lib:${PREFIX_DIR}/al2-build/crt/aws-crt-cpp/crt/*" cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index 5a74ae6d7cb..96f09cdf4b6 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -33,7 +33,7 @@ else COMMIT_ID="unknown" fi -export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-build/lib:${PREFIX_DIR}/al2-build/tests/testing-resources:/lib64:/lib:/usr/lib64:/usr/lib" +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-build/generated/src/aws-cpp-sdk-s3:${PREFIX_DIR}/al2-build/src/aws-cpp-sdk-core:${PREFIX_DIR}/al2-build/crt/aws-crt-cpp:${PREFIX_DIR}/al2-build/lib:${PREFIX_DIR}/al2-build/crt/aws-crt-cpp/crt/*" cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi From 35285aa3c7e1da37d6d451828ef2a45a4774a0e0 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Wed, 2 Jul 2025 00:58:18 -0400 Subject: [PATCH 45/77] fix wildcard --- .../build-tests/run-al2-dynamodb-performance-tests.sh | 5 ++++- tools/scripts/build-tests/run-al2-s3-performance-tests.sh | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index 0da14527d41..4f43aad440a 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -30,7 +30,10 @@ else COMMIT_ID="unknown" fi -export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-build/generated/src/aws-cpp-sdk-dynamodb:${PREFIX_DIR}/al2-build/src/aws-cpp-sdk-core:${PREFIX_DIR}/al2-build/crt/aws-crt-cpp:${PREFIX_DIR}/al2-build/lib:${PREFIX_DIR}/al2-build/crt/aws-crt-cpp/crt/*" +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-build/generated/src/aws-cpp-sdk-dynamodb:${PREFIX_DIR}/al2-build/src/aws-cpp-sdk-core:${PREFIX_DIR}/al2-build/crt/aws-crt-cpp:${PREFIX_DIR}/al2-build/lib" +for d in "${PREFIX_DIR}/al2-build/crt/aws-crt-cpp/crt"/*; do + [ -d "$d" ] && LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$d" +done cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index 96f09cdf4b6..e3536727ebd 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -33,7 +33,10 @@ else COMMIT_ID="unknown" fi -export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-build/generated/src/aws-cpp-sdk-s3:${PREFIX_DIR}/al2-build/src/aws-cpp-sdk-core:${PREFIX_DIR}/al2-build/crt/aws-crt-cpp:${PREFIX_DIR}/al2-build/lib:${PREFIX_DIR}/al2-build/crt/aws-crt-cpp/crt/*" +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-build/generated/src/aws-cpp-sdk-s3:${PREFIX_DIR}/al2-build/src/aws-cpp-sdk-core:${PREFIX_DIR}/al2-build/crt/aws-crt-cpp:${PREFIX_DIR}/al2-build/lib" +for d in "${PREFIX_DIR}/al2-build/crt/aws-crt-cpp/crt"/*; do + [ -d "$d" ] && LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$d" +done cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi From 0a7865727aac473a6835a6f1f88b9eab42cb50dd Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Wed, 2 Jul 2025 01:09:51 -0400 Subject: [PATCH 46/77] not add all folders under crt --- .../build-tests/run-al2-dynamodb-performance-tests.sh | 6 ++++-- tools/scripts/build-tests/run-al2-s3-performance-tests.sh | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index 4f43aad440a..7ceebef0957 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -31,8 +31,10 @@ else fi export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-build/generated/src/aws-cpp-sdk-dynamodb:${PREFIX_DIR}/al2-build/src/aws-cpp-sdk-core:${PREFIX_DIR}/al2-build/crt/aws-crt-cpp:${PREFIX_DIR}/al2-build/lib" -for d in "${PREFIX_DIR}/al2-build/crt/aws-crt-cpp/crt"/*; do - [ -d "$d" ] && LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$d" +BINARY=${PREFIX_DIR}/al2-build/tests/performance-tests/dynamodb-performance-test +for lib in $(ldd "$BINARY" | awk '/=>/ {print $3}' | grep "$PREFIX_DIR/al2-build/crt/aws-crt-cpp/crt"); do + dir=$(dirname "$lib") + LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$dir" done cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index e3536727ebd..7c47bcd396f 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -34,8 +34,10 @@ else fi export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-build/generated/src/aws-cpp-sdk-s3:${PREFIX_DIR}/al2-build/src/aws-cpp-sdk-core:${PREFIX_DIR}/al2-build/crt/aws-crt-cpp:${PREFIX_DIR}/al2-build/lib" -for d in "${PREFIX_DIR}/al2-build/crt/aws-crt-cpp/crt"/*; do - [ -d "$d" ] && LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$d" +BINARY=${PREFIX_DIR}/al2-build/tests/performance-tests/s3-performance-test +for lib in $(ldd "$BINARY" | awk '/=>/ {print $3}' | grep "$PREFIX_DIR/al2-build/crt/aws-crt-cpp/crt"); do + dir=$(dirname "$lib") + LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$dir" done cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi From 2d6f65d1aa01ddd1b8c10c12fb344ff1896c7ad8 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Wed, 2 Jul 2025 02:01:13 -0400 Subject: [PATCH 47/77] try another method to add dynamic libs --- .../run-al2-dynamodb-performance-tests.sh | 22 ++++++++++++------- .../run-al2-s3-performance-tests.sh | 22 ++++++++++++------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index 7ceebef0957..175d1ddca65 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -30,14 +30,20 @@ else COMMIT_ID="unknown" fi -export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-build/generated/src/aws-cpp-sdk-dynamodb:${PREFIX_DIR}/al2-build/src/aws-cpp-sdk-core:${PREFIX_DIR}/al2-build/crt/aws-crt-cpp:${PREFIX_DIR}/al2-build/lib" -BINARY=${PREFIX_DIR}/al2-build/tests/performance-tests/dynamodb-performance-test -for lib in $(ldd "$BINARY" | awk '/=>/ {print $3}' | grep "$PREFIX_DIR/al2-build/crt/aws-crt-cpp/crt"); do - dir=$(dirname "$lib") - LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$dir" +#export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-build/generated/src/aws-cpp-sdk-dynamodb:${PREFIX_DIR}/al2-build/src/aws-cpp-sdk-core:${PREFIX_DIR}/al2-build/crt/aws-crt-cpp:${PREFIX_DIR}/al2-build/lib" +#BINARY=${PREFIX_DIR}/al2-build/tests/performance-tests/dynamodb-performance-test +#for lib in $(ldd "$BINARY" | awk '/=>/ {print $3}' | grep "$PREFIX_DIR/al2-build/crt/aws-crt-cpp/crt"); do +# dir=$(dirname "$lib") +# LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$dir" +#done +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:./al2-build/generated/src/aws-cpp-sdk-dynamodb:./al2-build/src/aws-cpp-sdk-core:./al2-build/crt/aws-crt-cpp:./al2-build/lib" +BINARY=./dynamodb-performance-test +for lib in $(ldd "$BINARY" | awk '/=>/ {print $3}' | grep "al2-build/crt/aws-crt-cpp/crt"); do + rel_dir=$(echo "$lib" | sed 's|.*/al2-build/|./al2-build/|' | xargs dirname) + LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$rel_dir" done -cd "${PREFIX_DIR}/al2-build" +#cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi - -./tests/performance-tests/dynamodb-performance-test --region "$REGION" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" +./dynamodb-performance-test --region "$REGION" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" +#./tests/performance-tests/dynamodb-performance-test --region "$REGION" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" cat dynamodb-performance-test-results.json \ No newline at end of file diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index 7c47bcd396f..ba5e2d48b6b 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -33,14 +33,20 @@ else COMMIT_ID="unknown" fi -export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-build/generated/src/aws-cpp-sdk-s3:${PREFIX_DIR}/al2-build/src/aws-cpp-sdk-core:${PREFIX_DIR}/al2-build/crt/aws-crt-cpp:${PREFIX_DIR}/al2-build/lib" -BINARY=${PREFIX_DIR}/al2-build/tests/performance-tests/s3-performance-test -for lib in $(ldd "$BINARY" | awk '/=>/ {print $3}' | grep "$PREFIX_DIR/al2-build/crt/aws-crt-cpp/crt"); do - dir=$(dirname "$lib") - LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$dir" +#export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-build/generated/src/aws-cpp-sdk-s3:${PREFIX_DIR}/al2-build/src/aws-cpp-sdk-core:${PREFIX_DIR}/al2-build/crt/aws-crt-cpp:${PREFIX_DIR}/al2-build/lib" +#BINARY=${PREFIX_DIR}/al2-build/tests/performance-tests/s3-performance-test +#for lib in $(ldd "$BINARY" | awk '/=>/ {print $3}' | grep "$PREFIX_DIR/al2-build/crt/aws-crt-cpp/crt"); do +# dir=$(dirname "$lib") +# LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$dir" +#done +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:./al2-build/generated/src/aws-cpp-sdk-s3:./al2-build/src/aws-cpp-sdk-core:./al2-build/crt/aws-crt-cpp:./al2-build/lib" +BINARY=./s3-performance-test +for lib in $(ldd "$BINARY" | awk '/=>/ {print $3}' | grep "al2-build/crt/aws-crt-cpp/crt"); do + rel_dir=$(echo "$lib" | sed 's|.*/al2-build/|./al2-build/|' | xargs dirname) + LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$rel_dir" done -cd "${PREFIX_DIR}/al2-build" +#cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi - -./tests/performance-tests/s3-performance-test --region "$REGION" --az-id "$AZ_ID" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" +./s3-performance-test --region "$REGION" --az-id "$AZ_ID" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" +#./tests/performance-tests/s3-performance-test --region "$REGION" --az-id "$AZ_ID" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" cat s3-performance-test-results.json \ No newline at end of file From 9ea84cbb6eee612d8a95c8e79437d56a579cdb08 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Wed, 2 Jul 2025 13:19:23 -0400 Subject: [PATCH 48/77] fix perf test sh again to configure dynamic libs --- .../run-al2-dynamodb-performance-tests.sh | 22 +++++-------------- .../run-al2-s3-performance-tests.sh | 22 +++++-------------- 2 files changed, 12 insertions(+), 32 deletions(-) diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index 175d1ddca65..6e1da103a44 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -30,20 +30,10 @@ else COMMIT_ID="unknown" fi -#export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-build/generated/src/aws-cpp-sdk-dynamodb:${PREFIX_DIR}/al2-build/src/aws-cpp-sdk-core:${PREFIX_DIR}/al2-build/crt/aws-crt-cpp:${PREFIX_DIR}/al2-build/lib" -#BINARY=${PREFIX_DIR}/al2-build/tests/performance-tests/dynamodb-performance-test -#for lib in $(ldd "$BINARY" | awk '/=>/ {print $3}' | grep "$PREFIX_DIR/al2-build/crt/aws-crt-cpp/crt"); do -# dir=$(dirname "$lib") -# LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$dir" -#done -export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:./al2-build/generated/src/aws-cpp-sdk-dynamodb:./al2-build/src/aws-cpp-sdk-core:./al2-build/crt/aws-crt-cpp:./al2-build/lib" -BINARY=./dynamodb-performance-test -for lib in $(ldd "$BINARY" | awk '/=>/ {print $3}' | grep "al2-build/crt/aws-crt-cpp/crt"); do - rel_dir=$(echo "$lib" | sed 's|.*/al2-build/|./al2-build/|' | xargs dirname) - LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$rel_dir" -done -#cd "${PREFIX_DIR}/al2-build" +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" + +cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi -./dynamodb-performance-test --region "$REGION" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" -#./tests/performance-tests/dynamodb-performance-test --region "$REGION" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" -cat dynamodb-performance-test-results.json \ No newline at end of file +.tests/performance-tests/dynamodb-performance-test --region "$REGION" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" +cp dynamodb-performance-test-results.json results.json +cat results.json \ No newline at end of file diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index ba5e2d48b6b..2f42e31c4ec 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -33,20 +33,10 @@ else COMMIT_ID="unknown" fi -#export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-build/generated/src/aws-cpp-sdk-s3:${PREFIX_DIR}/al2-build/src/aws-cpp-sdk-core:${PREFIX_DIR}/al2-build/crt/aws-crt-cpp:${PREFIX_DIR}/al2-build/lib" -#BINARY=${PREFIX_DIR}/al2-build/tests/performance-tests/s3-performance-test -#for lib in $(ldd "$BINARY" | awk '/=>/ {print $3}' | grep "$PREFIX_DIR/al2-build/crt/aws-crt-cpp/crt"); do -# dir=$(dirname "$lib") -# LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$dir" -#done -export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:./al2-build/generated/src/aws-cpp-sdk-s3:./al2-build/src/aws-cpp-sdk-core:./al2-build/crt/aws-crt-cpp:./al2-build/lib" -BINARY=./s3-performance-test -for lib in $(ldd "$BINARY" | awk '/=>/ {print $3}' | grep "al2-build/crt/aws-crt-cpp/crt"); do - rel_dir=$(echo "$lib" | sed 's|.*/al2-build/|./al2-build/|' | xargs dirname) - LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$rel_dir" -done -#cd "${PREFIX_DIR}/al2-build" +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" + +cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi -./s3-performance-test --region "$REGION" --az-id "$AZ_ID" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" -#./tests/performance-tests/s3-performance-test --region "$REGION" --az-id "$AZ_ID" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" -cat s3-performance-test-results.json \ No newline at end of file +.tests/performance-tests/s3-performance-test --region "$REGION" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" +cp s3-performance-test-results.json results.json +cat results.json \ No newline at end of file From ed6241cb91909a167ef18301cdfbe5ae11dc25be Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Wed, 2 Jul 2025 14:17:26 -0400 Subject: [PATCH 49/77] edit perf test sh to run the executables --- tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh | 2 +- tools/scripts/build-tests/run-al2-s3-performance-tests.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index 6e1da103a44..d67bebb0d70 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -34,6 +34,6 @@ export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi -.tests/performance-tests/dynamodb-performance-test --region "$REGION" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" +./tests/performance-tests/dynamodb-performance-test --region "$REGION" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" cp dynamodb-performance-test-results.json results.json cat results.json \ No newline at end of file diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index 2f42e31c4ec..ab3e67e9804 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -37,6 +37,6 @@ export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi -.tests/performance-tests/s3-performance-test --region "$REGION" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" +./tests/performance-tests/s3-performance-test --region "$REGION" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" cp s3-performance-test-results.json results.json cat results.json \ No newline at end of file From b1111bbbfebcbda7287d7c6ac8e4f9104063c0cf Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Wed, 2 Jul 2025 17:02:47 -0400 Subject: [PATCH 50/77] 10 iterations by default --- tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh | 2 +- tools/scripts/build-tests/run-al2-s3-performance-tests.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index d67bebb0d70..66f35313281 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -2,7 +2,7 @@ set -e DEFAULT_REGION="us-east-1" -DEFAULT_ITERATIONS=3 +DEFAULT_ITERATIONS=10 if [ "$#" -lt 1 ]; then echo "Usage: ${0} PREFIX_DIR [--region REGION] [--iterations NUM]" diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index ab3e67e9804..f3b0d58f0c9 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -3,7 +3,7 @@ set -e DEFAULT_REGION="us-east-1" DEFAULT_AZ_ID="use1-az4" -DEFAULT_ITERATIONS=3 +DEFAULT_ITERATIONS=10 if [ "$#" -lt 1 ]; then echo "Usage: ${0} PREFIX_DIR [--region REGION] [--az-id AZ_ID] [--iterations NUM]" From 547ee89780ad42eb65a287484fe798680918083b Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Thu, 3 Jul 2025 15:26:52 -0400 Subject: [PATCH 51/77] fix pr issues --- tests/performance-tests/CMakeLists.txt | 13 ++- .../performance-tests/PerformanceTestBase.h | 33 +++++++ .../include/performance-tests/Utils.h | 25 ----- .../dynamodb/DynamoDBPerformanceTest.h | 50 ++++------ .../services/dynamodb/DynamoDBTestConfig.h | 13 +-- .../services/s3/S3PerformanceTest.h | 56 +++++------ .../services/s3/S3TestConfig.h | 20 ++-- .../dynamodb/DynamoDBPerformanceTest.cpp | 79 ++++++++------- .../src/services/dynamodb/main.cpp | 57 +++++------ .../src/services/s3/S3PerformanceTest.cpp | 97 ++++++++++--------- .../src/services/s3/main.cpp | 65 ++++++------- 11 files changed, 262 insertions(+), 246 deletions(-) create mode 100644 tests/performance-tests/include/performance-tests/PerformanceTestBase.h diff --git a/tests/performance-tests/CMakeLists.txt b/tests/performance-tests/CMakeLists.txt index 5660c9e1438..951a269cb2c 100644 --- a/tests/performance-tests/CMakeLists.txt +++ b/tests/performance-tests/CMakeLists.txt @@ -9,6 +9,15 @@ add_project(performance-tests aws-cpp-sdk-dynamodb ) +# Add cxxopts dependency +include(FetchContent) +FetchContent_Declare( + cxxopts + GIT_REPOSITORY https://github.com/jarro2783/cxxopts.git + GIT_TAG v3.1.1 +) +FetchContent_MakeAvailable(cxxopts) + function(add_service_test SERVICE SDK_LIB PERF_TEST_FILE) add_executable(${SERVICE}-performance-test src/services/${SERVICE}/main.cpp @@ -18,8 +27,8 @@ function(add_service_test SERVICE SDK_LIB PERF_TEST_FILE) set_compiler_flags(${SERVICE}-performance-test) set_compiler_warnings(${SERVICE}-performance-test) target_include_directories(${SERVICE}-performance-test PRIVATE include) - target_link_libraries(${SERVICE}-performance-test PRIVATE aws-cpp-sdk-core ${SDK_LIB}) - target_compile_options(${SERVICE}-performance-test PRIVATE -std=c++17) + target_link_libraries(${SERVICE}-performance-test PRIVATE aws-cpp-sdk-core ${SDK_LIB} cxxopts::cxxopts) + target_compile_options(${SERVICE}-performance-test PRIVATE -std=c++17 -fexceptions) endfunction() add_service_test(s3 aws-cpp-sdk-s3 S3PerformanceTest.cpp) diff --git a/tests/performance-tests/include/performance-tests/PerformanceTestBase.h b/tests/performance-tests/include/performance-tests/PerformanceTestBase.h new file mode 100644 index 00000000000..ef4fb45dbf5 --- /dev/null +++ b/tests/performance-tests/include/performance-tests/PerformanceTestBase.h @@ -0,0 +1,33 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once + +namespace PerformanceTest { + +/** + * Base class for all performance tests. + */ +class PerformanceTestBase { + public: + virtual ~PerformanceTestBase() = default; + + /** + * Initialize resources for the test. + */ + virtual void Setup() = 0; + + /** + * Run the performance test operations. + */ + virtual void Run() = 0; + + /** + * Clean up resources created during setup. + */ + virtual void TearDown() = 0; +}; + +} // namespace PerformanceTest \ No newline at end of file diff --git a/tests/performance-tests/include/performance-tests/Utils.h b/tests/performance-tests/include/performance-tests/Utils.h index 1cc56c7eadd..eac2f4ab7e8 100644 --- a/tests/performance-tests/include/performance-tests/Utils.h +++ b/tests/performance-tests/include/performance-tests/Utils.h @@ -5,7 +5,6 @@ #pragma once -#include #include #include #include @@ -13,9 +12,6 @@ #include #include #include -#include -#include -#include namespace PerformanceTest { namespace Utils { @@ -37,16 +33,6 @@ static inline Aws::String RandomString(size_t length) { return str; } -/** - * Log error messages to stderr. - * @param service The name of the AWS service - * @param operation The name of the operation that failed - * @param message The error message to log - */ -static inline void LogError(const Aws::String& service, const Aws::String& operation, const Aws::String& message) { - std::cerr << "[ERROR] " << service << ":" << operation << " failed: " << message << '\n'; -} - /** * Generate a unique identifier using UUID. * @return A 10-character lowercase UUID substring @@ -56,16 +42,5 @@ static inline Aws::String GenerateUniqueId() { return Aws::Utils::StringUtils::ToLower(rawUUID.c_str()).substr(0, 10); } -/** - * Get the current SDK version as a formatted string. - * @return SDK version in the format "major.minor.patch" (e.g., "1.11.0") - */ -static inline Aws::String GetSDKVersionString() { - Aws::SDKOptions::SDKVersion const version; - return Aws::Utils::StringUtils::to_string(static_cast(version.major)) + "." + - Aws::Utils::StringUtils::to_string(static_cast(version.minor)) + "." + - Aws::Utils::StringUtils::to_string(static_cast(version.patch)); -} - } // namespace Utils } // namespace PerformanceTest \ No newline at end of file diff --git a/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h index 3384db60473..65e94ca132e 100644 --- a/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h +++ b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h @@ -5,8 +5,10 @@ #pragma once +#include #include #include +#include #include @@ -17,42 +19,30 @@ namespace DynamoDB { * Configuration for DynamoDB performance test cases. */ struct TestCase { - Aws::String sizeLabel; + const char* sizeLabel; size_t sizeBytes; }; /** - * Runs DynamoDB performance test by creating a table, performing PutItem and GetItem operations, - * then cleaning up resources. - * @param dynamodb DynamoDB client instance to use for operations - * @param config Test configuration containing size parameters - * @param iterations Number of put/get operations to perform + * DynamoDB performance test implementation. + * Tests PutItem and GetItem operations with different payload sizes. */ -void RunTest(Aws::DynamoDB::DynamoDBClient& dynamodb, const TestCase& config, int iterations = 3); - -/** - * Create DynamoDB table for testing and wait for it to become active. - * @param dynamodb DynamoDB client instance - * @param config Test configuration - * @return Table name if successful, empty string if failed - */ -Aws::String SetupTable(Aws::DynamoDB::DynamoDBClient& dynamodb, const TestCase& config); - -/** - * Run PutItem and GetItem operations. - * @param dynamodb DynamoDB client instance - * @param tableName Name of the table to use - * @param config Test configuration - * @param iterations Number of operations to perform - */ -void RunOperations(Aws::DynamoDB::DynamoDBClient& dynamodb, const Aws::String& tableName, const TestCase& config, int iterations); +class DynamoDBPerformanceTest : public PerformanceTestBase { + public: + DynamoDBPerformanceTest(const Aws::String& region, const TestCase& config, int iterations = 3); + + void Setup() override; + void TearDown() override; + void Run() override; + + private: + const TestCase& m_config; + const Aws::String m_region; + const int m_iterations; + Aws::UniquePtr m_dynamodb; + Aws::String m_tableName; +}; -/** - * Clean up DynamoDB resources (delete table). - * @param dynamodb DynamoDB client instance - * @param tableName Name of the table to delete - */ -void CleanupResources(Aws::DynamoDB::DynamoDBClient& dynamodb, const Aws::String& tableName); } // namespace DynamoDB } // namespace Services } // namespace PerformanceTest \ No newline at end of file diff --git a/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h index ea2fc1c2a39..c7428389851 100644 --- a/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h +++ b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h @@ -5,19 +5,20 @@ #pragma once -#include -#include -#include +#include + +#include +#include namespace PerformanceTest { namespace Services { namespace DynamoDB { namespace TestConfig { -const Aws::Set TestOperations = {"PutItem", "GetItem"}; +const std::set TestOperations = {"PutItem", "GetItem"}; -const Aws::Vector TestMatrix = {{"8KB", 8 * 1024}, {"64KB", 64 * 1024}, {"392KB", 392 * 1024}}; +const std::array TestMatrix = {{{"8KB", 8 * 1024}, {"64KB", 64 * 1024}, {"392KB", 392 * 1024}}}; -const Aws::String OutputFilename = "dynamodb-performance-test-results.json"; +const char* OutputFilename = "dynamodb-performance-test-results.json"; } // namespace TestConfig } // namespace DynamoDB } // namespace Services diff --git a/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h b/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h index a53ccc7add7..2d39f19bf19 100644 --- a/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h +++ b/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h @@ -5,8 +5,10 @@ #pragma once +#include #include #include +#include #include @@ -17,46 +19,32 @@ namespace S3 { * Configuration for S3 performance test cases. */ struct TestCase { - Aws::String sizeLabel; + const char* sizeLabel; size_t sizeBytes; - Aws::String bucketTypeLabel; + const char* bucketTypeLabel; }; /** - * Runs S3 performance test by creating a bucket, performing PutObject and GetObject operations, - * then cleaning up resources. - * @param s3 S3 client instance to use for operations - * @param config Test configuration containing object size and bucket type parameters - * @param availabilityZoneId Availability zone ID for S3 Express buckets - * @param iterations Number of put/get operations to perform + * S3 performance test implementation. + * Tests PutObject and GetObject operations with different payload sizes and bucket types. */ -void RunTest(Aws::S3::S3Client& s3, const TestCase& config, const Aws::String& availabilityZoneId, int iterations = 3); - -/** - * Create S3 bucket for testing. - * @param s3 S3 client instance - * @param config Test configuration - * @param availabilityZoneId Availability zone ID for S3 Express buckets - * @return Bucket name if successful, empty string if failed - */ -Aws::String SetupBucket(Aws::S3::S3Client& s3, const TestCase& config, const Aws::String& availabilityZoneId); - -/** - * Run PutObject and GetObject operations. - * @param s3 S3 client instance - * @param bucketName Name of the bucket to use - * @param config Test configuration - * @param iterations Number of operations to perform - */ -void RunOperations(Aws::S3::S3Client& s3, const Aws::String& bucketName, const TestCase& config, int iterations); +class S3PerformanceTest : public PerformanceTestBase { + public: + S3PerformanceTest(const Aws::String& region, const TestCase& config, const Aws::String& availabilityZoneId, int iterations = 3); + + void Setup() override; + void TearDown() override; + void Run() override; + + private: + const TestCase& m_config; + const Aws::String m_region; + const Aws::String m_availabilityZoneId; + const int m_iterations; + Aws::UniquePtr m_s3; + Aws::String m_bucketName; +}; -/** - * Clean up S3 resources (objects and bucket). - * @param s3 S3 client instance - * @param bucketName Name of the bucket to clean up - * @param iterations Number of objects to delete - */ -void CleanupResources(Aws::S3::S3Client& s3, const Aws::String& bucketName, int iterations); } // namespace S3 } // namespace Services } // namespace PerformanceTest \ No newline at end of file diff --git a/tests/performance-tests/include/performance-tests/services/s3/S3TestConfig.h b/tests/performance-tests/include/performance-tests/services/s3/S3TestConfig.h index 0ed0ada66d2..24fc8c56a3c 100644 --- a/tests/performance-tests/include/performance-tests/services/s3/S3TestConfig.h +++ b/tests/performance-tests/include/performance-tests/services/s3/S3TestConfig.h @@ -5,21 +5,25 @@ #pragma once -#include -#include -#include +#include + +#include +#include namespace PerformanceTest { namespace Services { namespace S3 { namespace TestConfig { -const Aws::Set TestOperations = {"PutObject", "GetObject"}; +const std::set TestOperations = {"PutObject", "GetObject"}; -const Aws::Vector TestMatrix = {{"8KB", 8 * 1024, "s3-standard"}, {"64KB", 64 * 1024, "s3-standard"}, - {"1MB", 1024 * 1024, "s3-standard"}, {"8KB", 8 * 1024, "s3-express"}, - {"64KB", 64 * 1024, "s3-express"}, {"1MB", 1024 * 1024, "s3-express"}}; +const std::array TestMatrix = {{{"8KB", 8 * 1024, "s3-standard"}, + {"64KB", 64 * 1024, "s3-standard"}, + {"1MB", 1024 * 1024, "s3-standard"}, + {"8KB", 8 * 1024, "s3-express"}, + {"64KB", 64 * 1024, "s3-express"}, + {"1MB", 1024 * 1024, "s3-express"}}}; -const Aws::String OutputFilename = "s3-performance-test-results.json"; +const char* OutputFilename = "s3-performance-test-results.json"; } // namespace TestConfig } // namespace S3 } // namespace Services diff --git a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp index 63514076d8e..02487c2d96c 100644 --- a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp +++ b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp @@ -3,7 +3,10 @@ * SPDX-License-Identifier: Apache-2.0. */ +#include #include +#include +#include #include #include #include @@ -25,21 +28,19 @@ #include #include -void PerformanceTest::Services::DynamoDB::RunTest(Aws::DynamoDB::DynamoDBClient& dynamodb, const TestCase& config, int iterations) { - auto tableName = SetupTable(dynamodb, config); - if (tableName.empty()) { - return; - } +PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::DynamoDBPerformanceTest(const Aws::String& region, const TestCase& config, + int iterations) + : m_config(config), m_region(region), m_iterations(iterations) {} - RunOperations(dynamodb, tableName, config, iterations); - CleanupResources(dynamodb, tableName); -} +void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Setup() { + Aws::Client::ClientConfiguration cfg; + cfg.region = m_region; + m_dynamodb = Aws::MakeUnique("DynamoDBPerformanceTest", cfg); -Aws::String PerformanceTest::Services::DynamoDB::SetupTable(Aws::DynamoDB::DynamoDBClient& dynamodb, const TestCase& /* config */) { - Aws::String tableName = "perf-table-" + PerformanceTest::Utils::GenerateUniqueId(); + m_tableName = "perf-table-" + PerformanceTest::Utils::GenerateUniqueId(); Aws::DynamoDB::Model::CreateTableRequest createTableRequest; - createTableRequest.SetTableName(tableName); + createTableRequest.SetTableName(m_tableName); Aws::DynamoDB::Model::AttributeDefinition hashKey; hashKey.SetAttributeName("id"); @@ -53,18 +54,19 @@ Aws::String PerformanceTest::Services::DynamoDB::SetupTable(Aws::DynamoDB::Dynam Aws::DynamoDB::Model::BillingMode const billingMode = Aws::DynamoDB::Model::BillingMode::PAY_PER_REQUEST; createTableRequest.SetBillingMode(billingMode); - auto createTableOutcome = dynamodb.CreateTable(createTableRequest); + auto createTableOutcome = m_dynamodb->CreateTable(createTableRequest); if (!createTableOutcome.IsSuccess()) { - PerformanceTest::Utils::LogError("DynamoDB", "CreateTable", createTableOutcome.GetError().GetMessage()); - return ""; + AWS_LOG_ERROR("PerformanceTest", ("DynamoDB:CreateTable failed: " + createTableOutcome.GetError().GetMessage()).c_str()); + m_tableName.clear(); + return; } // Wait for table to become active Aws::DynamoDB::Model::DescribeTableRequest describeRequest; - describeRequest.SetTableName(tableName); + describeRequest.SetTableName(m_tableName); while (true) { - auto describeOutcome = dynamodb.DescribeTable(describeRequest); + auto describeOutcome = m_dynamodb->DescribeTable(describeRequest); if (describeOutcome.IsSuccess()) { auto status = describeOutcome.GetResult().GetTable().GetTableStatus(); if (status == Aws::DynamoDB::Model::TableStatus::ACTIVE) { @@ -73,53 +75,60 @@ Aws::String PerformanceTest::Services::DynamoDB::SetupTable(Aws::DynamoDB::Dynam } std::this_thread::sleep_for(std::chrono::seconds(1)); } - - return tableName; } -void PerformanceTest::Services::DynamoDB::RunOperations(Aws::DynamoDB::DynamoDBClient& dynamodb, const Aws::String& tableName, - const TestCase& config, int iterations) { - const auto payload = PerformanceTest::Utils::RandomString(config.sizeBytes); +void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Run() { + if (m_tableName.empty()) { + AWS_LOG_ERROR("PerformanceTest", "DynamoDB:Run - Table setup failed, skipping test"); + return; + } + + const auto payload = PerformanceTest::Utils::RandomString(m_config.sizeBytes); // Run PutItem multiple times - for (int i = 0; i < iterations; i++) { + for (int i = 0; i < m_iterations; i++) { Aws::DynamoDB::Model::PutItemRequest putItemRequest; - putItemRequest.SetTableName(tableName); - putItemRequest.SetAdditionalCustomHeaderValue("test-dimension-size", config.sizeLabel); + putItemRequest.SetTableName(m_tableName); + putItemRequest.SetAdditionalCustomHeaderValue("test-dimension-size", m_config.sizeLabel); Aws::Map item; item["id"].SetS(Aws::String("test-key-") + Aws::Utils::StringUtils::to_string(i)); item["data"].SetS(payload); putItemRequest.SetItem(item); - auto putItemOutcome = dynamodb.PutItem(putItemRequest); + auto putItemOutcome = m_dynamodb->PutItem(putItemRequest); if (!putItemOutcome.IsSuccess()) { - PerformanceTest::Utils::LogError("DynamoDB", "PutItem", putItemOutcome.GetError().GetMessage()); + AWS_LOG_ERROR("PerformanceTest", ("DynamoDB:PutItem failed: " + putItemOutcome.GetError().GetMessage()).c_str()); } } // Run GetItem multiple times - for (int i = 0; i < iterations; i++) { + for (int i = 0; i < m_iterations; i++) { Aws::DynamoDB::Model::GetItemRequest getItemRequest; - getItemRequest.SetTableName(tableName); - getItemRequest.SetAdditionalCustomHeaderValue("test-dimension-size", config.sizeLabel); + getItemRequest.SetTableName(m_tableName); + getItemRequest.SetAdditionalCustomHeaderValue("test-dimension-size", m_config.sizeLabel); Aws::Map key; key["id"].SetS(Aws::String("test-key-") + Aws::Utils::StringUtils::to_string(i)); getItemRequest.SetKey(key); - auto getItemOutcome = dynamodb.GetItem(getItemRequest); + auto getItemOutcome = m_dynamodb->GetItem(getItemRequest); if (!getItemOutcome.IsSuccess()) { - PerformanceTest::Utils::LogError("DynamoDB", "GetItem", getItemOutcome.GetError().GetMessage()); + AWS_LOG_ERROR("PerformanceTest", ("DynamoDB:GetItem failed: " + getItemOutcome.GetError().GetMessage()).c_str()); } } } -void PerformanceTest::Services::DynamoDB::CleanupResources(Aws::DynamoDB::DynamoDBClient& dynamodb, const Aws::String& tableName) { +void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::TearDown() { + if (m_tableName.empty()) { + AWS_LOG_ERROR("PerformanceTest", "DynamoDB:TearDown - No table to clean up, setup likely failed"); + return; + } + Aws::DynamoDB::Model::DeleteTableRequest deleteTableRequest; - deleteTableRequest.SetTableName(tableName); - auto deleteTableOutcome = dynamodb.DeleteTable(deleteTableRequest); + deleteTableRequest.SetTableName(m_tableName); + auto deleteTableOutcome = m_dynamodb->DeleteTable(deleteTableRequest); if (!deleteTableOutcome.IsSuccess()) { - PerformanceTest::Utils::LogError("DynamoDB", "DeleteTable", deleteTableOutcome.GetError().GetMessage()); + AWS_LOG_ERROR("PerformanceTest", ("DynamoDB:DeleteTable failed: " + deleteTableOutcome.GetError().GetMessage()).c_str()); } } \ No newline at end of file diff --git a/tests/performance-tests/src/services/dynamodb/main.cpp b/tests/performance-tests/src/services/dynamodb/main.cpp index 26d5415a9fd..542b9626c29 100644 --- a/tests/performance-tests/src/services/dynamodb/main.cpp +++ b/tests/performance-tests/src/services/dynamodb/main.cpp @@ -4,55 +4,56 @@ */ #include -#include +#include #include +#include #include +#include #include -#include -#include #include #include #include +#include #include int main(int argc, char** argv) { - Aws::String region = "us-east-1"; - Aws::String commitId = "unknown"; - int iterations = 10; - - for (int i = 1; i < argc; ++i) { - Aws::String const arg = argv[i]; - if (arg == "--region" && i + 1 < argc) { - region = argv[++i]; - } else if (arg == "--iterations" && i + 1 < argc) { - iterations = std::stoi(argv[++i]); - } else if (arg == "--commit-id" && i + 1 < argc) { - commitId = argv[++i]; - } - } + cxxopts::Options options("dynamodb-perf-test", "DynamoDB Performance Test"); + options.add_options()("r,region", "AWS region", cxxopts::value()->default_value("us-east-1"))( + "i,iterations", "Number of iterations", cxxopts::value()->default_value("10"))( + "c,commit-id", "Commit ID", cxxopts::value()->default_value("unknown")); + + auto const result = options.parse(argc, argv); - Aws::SDKOptions options; - Aws::String const versionStr = PerformanceTest::Utils::GetSDKVersionString(); + Aws::String const region = Aws::Utils::StringUtils::to_string(result["region"].as()); + Aws::String const commitId = Aws::Utils::StringUtils::to_string(result["commit-id"].as()); + int const iterations = result["iterations"].as(); - options.monitoringOptions.customizedMonitoringFactory_create_fn = {[&]() -> Aws::UniquePtr { + Aws::SDKOptions sdkOptions; + Aws::String const versionStr = Aws::Version::GetVersionString(); + + sdkOptions.monitoringOptions.customizedMonitoringFactory_create_fn = {[&]() -> Aws::UniquePtr { + Aws::Set operations; + for (const auto& operation : PerformanceTest::Services::DynamoDB::TestConfig::TestOperations) { + operations.insert(operation); + } return Aws::MakeUnique( - "JsonReportingMetricsFactory", PerformanceTest::Services::DynamoDB::TestConfig::TestOperations, "cpp1", versionStr, commitId, + "JsonReportingMetricsFactory", operations, "cpp1", versionStr, commitId, PerformanceTest::Services::DynamoDB::TestConfig::OutputFilename); }}; - Aws::InitAPI(options); + Aws::InitAPI(sdkOptions); { - Aws::Client::ClientConfiguration cfg; - cfg.region = region; - - Aws::DynamoDB::DynamoDBClient dynamodb(cfg); for (const auto& config : PerformanceTest::Services::DynamoDB::TestConfig::TestMatrix) { - PerformanceTest::Services::DynamoDB::RunTest(dynamodb, config, iterations); + auto performanceTest = Aws::MakeUnique("DynamoDBPerformanceTest", + region, config, iterations); + performanceTest->Setup(); + performanceTest->Run(); + performanceTest->TearDown(); } } - Aws::ShutdownAPI(options); + Aws::ShutdownAPI(sdkOptions); return 0; } \ No newline at end of file diff --git a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp index 4b21d159ff8..68a5d9b84da 100644 --- a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp +++ b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp @@ -3,7 +3,10 @@ * SPDX-License-Identifier: Apache-2.0. */ +#include #include +#include +#include #include #include #include @@ -21,29 +24,26 @@ #include #include -void PerformanceTest::Services::S3::RunTest(Aws::S3::S3Client& s3, const TestCase& config, const Aws::String& availabilityZoneId, - int iterations) { - auto bucketName = SetupBucket(s3, config, availabilityZoneId); - if (bucketName.empty()) { - return; - } +#include - RunOperations(s3, bucketName, config, iterations); - CleanupResources(s3, bucketName, iterations); -} +PerformanceTest::Services::S3::S3PerformanceTest::S3PerformanceTest(const Aws::String& region, const TestCase& config, + const Aws::String& availabilityZoneId, int iterations) + : m_config(config), m_region(region), m_availabilityZoneId(availabilityZoneId), m_iterations(iterations) {} + +void PerformanceTest::Services::S3::S3PerformanceTest::Setup() { + Aws::Client::ClientConfiguration cfg; + cfg.region = m_region; + m_s3 = Aws::MakeUnique("S3PerformanceTest", cfg); -Aws::String PerformanceTest::Services::S3::SetupBucket(Aws::S3::S3Client& s3, const TestCase& config, - const Aws::String& availabilityZoneId) { - Aws::String bucketName; Aws::S3::Model::CreateBucketRequest cbr; Aws::String const bucketId = PerformanceTest::Utils::GenerateUniqueId(); - if (config.bucketTypeLabel == "s3-express") { - bucketName = "perf-express-" + bucketId + "--" + availabilityZoneId + "--x-s3"; - cbr.SetBucket(bucketName); + if (strcmp(m_config.bucketTypeLabel, "s3-express") == 0) { + m_bucketName = "perf-express-" + bucketId + "--" + m_availabilityZoneId + "--x-s3"; + cbr.SetBucket(m_bucketName); Aws::S3::Model::CreateBucketConfiguration bucketConfig; bucketConfig.SetLocation( - Aws::S3::Model::LocationInfo().WithType(Aws::S3::Model::LocationType::AvailabilityZone).WithName(availabilityZoneId)); + Aws::S3::Model::LocationInfo().WithType(Aws::S3::Model::LocationType::AvailabilityZone).WithName(m_availabilityZoneId)); bucketConfig.SetBucket(Aws::S3::Model::BucketInfo() .WithType(Aws::S3::Model::BucketType::Directory) @@ -51,62 +51,69 @@ Aws::String PerformanceTest::Services::S3::SetupBucket(Aws::S3::S3Client& s3, co cbr.SetCreateBucketConfiguration(bucketConfig); } else { - bucketName = "perf-standard-" + bucketId; - cbr.SetBucket(bucketName); + m_bucketName = "perf-standard-" + bucketId; + cbr.SetBucket(m_bucketName); } - auto createOutcome = s3.CreateBucket(cbr); + auto createOutcome = m_s3->CreateBucket(cbr); if (!createOutcome.IsSuccess()) { - PerformanceTest::Utils::LogError("S3", "CreateBucket", createOutcome.GetError().GetMessage()); - return ""; + AWS_LOG_ERROR("PerformanceTest", ("S3:CreateBucket failed: " + createOutcome.GetError().GetMessage()).c_str()); + m_bucketName.clear(); } - - return bucketName; } -void PerformanceTest::Services::S3::RunOperations(Aws::S3::S3Client& s3, const Aws::String& bucketName, const TestCase& config, - int iterations) { - const auto randomPayload = PerformanceTest::Utils::RandomString(config.sizeBytes); +void PerformanceTest::Services::S3::S3PerformanceTest::Run() { + if (m_bucketName.empty()) { + AWS_LOG_ERROR("PerformanceTest", "S3:Run - Bucket setup failed, skipping test"); + return; + } + + const auto randomPayload = PerformanceTest::Utils::RandomString(m_config.sizeBytes); // Run PutObject multiple times - for (int i = 0; i < iterations; i++) { + for (int i = 0; i < m_iterations; i++) { auto stream = Aws::MakeShared("PerfStream"); *stream << randomPayload; Aws::S3::Model::PutObjectRequest por; - por.WithBucket(bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i)).SetBody(stream); - por.SetAdditionalCustomHeaderValue("test-dimension-size", config.sizeLabel); - por.SetAdditionalCustomHeaderValue("test-dimension-bucket-type", config.bucketTypeLabel); - auto putOutcome = s3.PutObject(por); + por.WithBucket(m_bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i)).SetBody(stream); + por.SetAdditionalCustomHeaderValue("test-dimension-size", m_config.sizeLabel); + por.SetAdditionalCustomHeaderValue("test-dimension-bucket-type", m_config.bucketTypeLabel); + auto putOutcome = m_s3->PutObject(por); if (!putOutcome.IsSuccess()) { - PerformanceTest::Utils::LogError("S3", "PutObject", putOutcome.GetError().GetMessage()); + AWS_LOG_ERROR("PerformanceTest", ("S3:PutObject failed: " + putOutcome.GetError().GetMessage()).c_str()); } } // Run GetObject multiple times - for (int i = 0; i < iterations; i++) { + for (int i = 0; i < m_iterations; i++) { Aws::S3::Model::GetObjectRequest gor; - gor.WithBucket(bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i)); - gor.SetAdditionalCustomHeaderValue("test-dimension-size", config.sizeLabel); - gor.SetAdditionalCustomHeaderValue("test-dimension-bucket-type", config.bucketTypeLabel); - auto getOutcome = s3.GetObject(gor); + gor.WithBucket(m_bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i)); + gor.SetAdditionalCustomHeaderValue("test-dimension-size", m_config.sizeLabel); + gor.SetAdditionalCustomHeaderValue("test-dimension-bucket-type", m_config.bucketTypeLabel); + auto getOutcome = m_s3->GetObject(gor); if (!getOutcome.IsSuccess()) { - PerformanceTest::Utils::LogError("S3", "GetObject", getOutcome.GetError().GetMessage()); + AWS_LOG_ERROR("PerformanceTest", ("S3:GetObject failed: " + getOutcome.GetError().GetMessage()).c_str()); } } } -void PerformanceTest::Services::S3::CleanupResources(Aws::S3::S3Client& s3, const Aws::String& bucketName, int iterations) { - for (int i = 0; i < iterations; i++) { - auto deleteObjectOutcome = s3.DeleteObject( - Aws::S3::Model::DeleteObjectRequest().WithBucket(bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i))); +void PerformanceTest::Services::S3::S3PerformanceTest::TearDown() { + if (m_bucketName.empty()) { + AWS_LOG_ERROR("PerformanceTest", "S3:TearDown - No bucket to clean up, setup likely failed"); + return; + } + + for (int i = 0; i < m_iterations; i++) { + auto deleteObjectOutcome = m_s3->DeleteObject( + Aws::S3::Model::DeleteObjectRequest().WithBucket(m_bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i))); if (!deleteObjectOutcome.IsSuccess()) { - PerformanceTest::Utils::LogError("S3", "DeleteObject", deleteObjectOutcome.GetError().GetMessage()); + AWS_LOG_ERROR("PerformanceTest", ("S3:DeleteObject failed: " + deleteObjectOutcome.GetError().GetMessage()).c_str()); } } - auto deleteBucketOutcome = s3.DeleteBucket(Aws::S3::Model::DeleteBucketRequest().WithBucket(bucketName)); + auto deleteBucketOutcome = m_s3->DeleteBucket(Aws::S3::Model::DeleteBucketRequest().WithBucket(m_bucketName)); if (!deleteBucketOutcome.IsSuccess()) { - PerformanceTest::Utils::LogError("S3", "DeleteBucket", deleteBucketOutcome.GetError().GetMessage()); + AWS_LOG_ERROR("PerformanceTest", ("S3:DeleteBucket failed: " + deleteBucketOutcome.GetError().GetMessage()).c_str()); } } \ No newline at end of file diff --git a/tests/performance-tests/src/services/s3/main.cpp b/tests/performance-tests/src/services/s3/main.cpp index 157dee1b120..0be30cd4999 100644 --- a/tests/performance-tests/src/services/s3/main.cpp +++ b/tests/performance-tests/src/services/s3/main.cpp @@ -4,58 +4,57 @@ */ #include -#include +#include #include +#include #include +#include #include -#include -#include #include #include #include +#include #include int main(int argc, char** argv) { - Aws::String region = "us-east-1"; - Aws::String availabilityZoneId = "use1-az4"; - Aws::String commitId = "unknown"; - int iterations = 10; - - for (int i = 1; i < argc; ++i) { - Aws::String const arg = argv[i]; - if (arg == "--region" && i + 1 < argc) { - region = argv[++i]; - } else if (arg == "--az-id" && i + 1 < argc) { - availabilityZoneId = argv[++i]; - } else if (arg == "--iterations" && i + 1 < argc) { - iterations = std::stoi(argv[++i]); - } else if (arg == "--commit-id" && i + 1 < argc) { - commitId = argv[++i]; + cxxopts::Options options("s3-perf-test", "S3 Performance Test"); + options.add_options()("r,region", "AWS region", cxxopts::value()->default_value("us-east-1"))( + "a,az-id", "Availability zone ID", cxxopts::value()->default_value("use1-az4"))( + "i,iterations", "Number of iterations", cxxopts::value()->default_value("10"))( + "c,commit-id", "Commit ID", cxxopts::value()->default_value("unknown")); + + auto const result = options.parse(argc, argv); + + Aws::String const region = Aws::Utils::StringUtils::to_string(result["region"].as()); + Aws::String const availabilityZoneId = Aws::Utils::StringUtils::to_string(result["az-id"].as()); + Aws::String const commitId = Aws::Utils::StringUtils::to_string(result["commit-id"].as()); + int const iterations = result["iterations"].as(); + + Aws::SDKOptions sdkOptions; + Aws::String const versionStr = Aws::Version::GetVersionString(); + + sdkOptions.monitoringOptions.customizedMonitoringFactory_create_fn = {[&]() -> Aws::UniquePtr { + Aws::Set operations; + for (const auto& operation : PerformanceTest::Services::S3::TestConfig::TestOperations) { + operations.insert(operation); } - } - - Aws::SDKOptions options; - Aws::String const versionStr = PerformanceTest::Utils::GetSDKVersionString(); - - options.monitoringOptions.customizedMonitoringFactory_create_fn = {[&]() -> Aws::UniquePtr { return Aws::MakeUnique( - "JsonReportingMetricsFactory", PerformanceTest::Services::S3::TestConfig::TestOperations, "cpp1", versionStr, commitId, - PerformanceTest::Services::S3::TestConfig::OutputFilename); + "JsonReportingMetricsFactory", operations, "cpp1", versionStr, commitId, PerformanceTest::Services::S3::TestConfig::OutputFilename); }}; - Aws::InitAPI(options); + Aws::InitAPI(sdkOptions); { - Aws::Client::ClientConfiguration cfg; - cfg.region = region; - - Aws::S3::S3Client s3(cfg); for (const auto& config : PerformanceTest::Services::S3::TestConfig::TestMatrix) { - PerformanceTest::Services::S3::RunTest(s3, config, availabilityZoneId, iterations); + auto performanceTest = Aws::MakeUnique("S3PerformanceTest", region, config, + availabilityZoneId, iterations); + performanceTest->Setup(); + performanceTest->Run(); + performanceTest->TearDown(); } } - Aws::ShutdownAPI(options); + Aws::ShutdownAPI(sdkOptions); return 0; } \ No newline at end of file From 158771931f56c1718dc86a9263592a39f0369a57 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Mon, 7 Jul 2025 17:47:22 -0400 Subject: [PATCH 52/77] address code review feedback: upgrade to C++20, replace std::set with std::array, optimize StringStream construction, add client null checks, and prevent possible ODR violations by moving config definitions to .cpp files. --- tests/performance-tests/CMakeLists.txt | 4 ++- .../services/dynamodb/DynamoDBTestConfig.h | 9 ++---- .../services/s3/S3TestConfig.h | 14 ++------- .../dynamodb/DynamoDBPerformanceTest.cpp | 10 +++++++ .../services/dynamodb/DynamoDBTestConfig.cpp | 27 +++++++++++++++++ .../src/services/s3/S3PerformanceTest.cpp | 13 ++++++-- .../src/services/s3/S3TestConfig.cpp | 30 +++++++++++++++++++ 7 files changed, 87 insertions(+), 20 deletions(-) create mode 100644 tests/performance-tests/src/services/dynamodb/DynamoDBTestConfig.cpp create mode 100644 tests/performance-tests/src/services/s3/S3TestConfig.cpp diff --git a/tests/performance-tests/CMakeLists.txt b/tests/performance-tests/CMakeLists.txt index 951a269cb2c..12c2372b2a6 100644 --- a/tests/performance-tests/CMakeLists.txt +++ b/tests/performance-tests/CMakeLists.txt @@ -23,12 +23,14 @@ function(add_service_test SERVICE SDK_LIB PERF_TEST_FILE) src/services/${SERVICE}/main.cpp src/reporting/JsonReportingMetrics.cpp src/services/${SERVICE}/${PERF_TEST_FILE} + src/services/${SERVICE}/${SERVICE}TestConfig.cpp ) set_compiler_flags(${SERVICE}-performance-test) set_compiler_warnings(${SERVICE}-performance-test) target_include_directories(${SERVICE}-performance-test PRIVATE include) target_link_libraries(${SERVICE}-performance-test PRIVATE aws-cpp-sdk-core ${SDK_LIB} cxxopts::cxxopts) - target_compile_options(${SERVICE}-performance-test PRIVATE -std=c++17 -fexceptions) + set_property(TARGET ${SERVICE}-performance-test PROPERTY CXX_STANDARD 20) + set_property(TARGET ${SERVICE}-performance-test PROPERTY COMPILE_OPTIONS "-fexceptions") endfunction() add_service_test(s3 aws-cpp-sdk-s3 S3PerformanceTest.cpp) diff --git a/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h index c7428389851..467b3efa552 100644 --- a/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h +++ b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h @@ -8,17 +8,14 @@ #include #include -#include namespace PerformanceTest { namespace Services { namespace DynamoDB { namespace TestConfig { -const std::set TestOperations = {"PutItem", "GetItem"}; - -const std::array TestMatrix = {{{"8KB", 8 * 1024}, {"64KB", 64 * 1024}, {"392KB", 392 * 1024}}}; - -const char* OutputFilename = "dynamodb-performance-test-results.json"; +extern const std::array TestOperations; +extern const std::array TestMatrix; +extern const char* OutputFilename; } // namespace TestConfig } // namespace DynamoDB } // namespace Services diff --git a/tests/performance-tests/include/performance-tests/services/s3/S3TestConfig.h b/tests/performance-tests/include/performance-tests/services/s3/S3TestConfig.h index 24fc8c56a3c..1daa595ba52 100644 --- a/tests/performance-tests/include/performance-tests/services/s3/S3TestConfig.h +++ b/tests/performance-tests/include/performance-tests/services/s3/S3TestConfig.h @@ -8,22 +8,14 @@ #include #include -#include namespace PerformanceTest { namespace Services { namespace S3 { namespace TestConfig { -const std::set TestOperations = {"PutObject", "GetObject"}; - -const std::array TestMatrix = {{{"8KB", 8 * 1024, "s3-standard"}, - {"64KB", 64 * 1024, "s3-standard"}, - {"1MB", 1024 * 1024, "s3-standard"}, - {"8KB", 8 * 1024, "s3-express"}, - {"64KB", 64 * 1024, "s3-express"}, - {"1MB", 1024 * 1024, "s3-express"}}}; - -const char* OutputFilename = "s3-performance-test-results.json"; +extern const std::array TestOperations; +extern const std::array TestMatrix; +extern const char* OutputFilename; } // namespace TestConfig } // namespace S3 } // namespace Services diff --git a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp index 02487c2d96c..81f5dba5563 100644 --- a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp +++ b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp @@ -78,6 +78,11 @@ void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Setup() { } void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Run() { + if (!m_dynamodb) { + AWS_LOG_ERROR("PerformanceTest", "DynamoDB:Run - DynamoDB client not initialized, Setup() failed or was not called"); + return; + } + if (m_tableName.empty()) { AWS_LOG_ERROR("PerformanceTest", "DynamoDB:Run - Table setup failed, skipping test"); return; @@ -120,6 +125,11 @@ void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Run() { } void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::TearDown() { + if (!m_dynamodb) { + AWS_LOG_ERROR("PerformanceTest", "DynamoDB:TearDown - DynamoDB client not initialized, Setup() failed or was not called"); + return; + } + if (m_tableName.empty()) { AWS_LOG_ERROR("PerformanceTest", "DynamoDB:TearDown - No table to clean up, setup likely failed"); return; diff --git a/tests/performance-tests/src/services/dynamodb/DynamoDBTestConfig.cpp b/tests/performance-tests/src/services/dynamodb/DynamoDBTestConfig.cpp new file mode 100644 index 00000000000..b7ef24bdd12 --- /dev/null +++ b/tests/performance-tests/src/services/dynamodb/DynamoDBTestConfig.cpp @@ -0,0 +1,27 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include + +#include + +namespace PerformanceTest { +namespace Services { +namespace DynamoDB { +namespace TestConfig { + +const std::array TestOperations = {"PutItem", "GetItem"}; + +const std::array TestMatrix = {{{.sizeLabel = "8KB", .sizeBytes = 8 * 1024}, + {.sizeLabel = "64KB", .sizeBytes = 64 * 1024}, + {.sizeLabel = "392KB", .sizeBytes = 392 * 1024}}}; + +const char* OutputFilename = "dynamodb-performance-test-results.json"; + +} // namespace TestConfig +} // namespace DynamoDB +} // namespace Services +} // namespace PerformanceTest \ No newline at end of file diff --git a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp index 68a5d9b84da..ea12f6a5669 100644 --- a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp +++ b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp @@ -63,6 +63,11 @@ void PerformanceTest::Services::S3::S3PerformanceTest::Setup() { } void PerformanceTest::Services::S3::S3PerformanceTest::Run() { + if (!m_s3) { + AWS_LOG_ERROR("PerformanceTest", "S3:Run - S3 client not initialized, Setup() failed or was not called"); + return; + } + if (m_bucketName.empty()) { AWS_LOG_ERROR("PerformanceTest", "S3:Run - Bucket setup failed, skipping test"); return; @@ -72,8 +77,7 @@ void PerformanceTest::Services::S3::S3PerformanceTest::Run() { // Run PutObject multiple times for (int i = 0; i < m_iterations; i++) { - auto stream = Aws::MakeShared("PerfStream"); - *stream << randomPayload; + const auto stream = Aws::MakeShared("PerfStream", randomPayload); Aws::S3::Model::PutObjectRequest por; por.WithBucket(m_bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i)).SetBody(stream); @@ -99,6 +103,11 @@ void PerformanceTest::Services::S3::S3PerformanceTest::Run() { } void PerformanceTest::Services::S3::S3PerformanceTest::TearDown() { + if (!m_s3) { + AWS_LOG_ERROR("PerformanceTest", "S3:TearDown - S3 client not initialized, Setup() failed or was not called"); + return; + } + if (m_bucketName.empty()) { AWS_LOG_ERROR("PerformanceTest", "S3:TearDown - No bucket to clean up, setup likely failed"); return; diff --git a/tests/performance-tests/src/services/s3/S3TestConfig.cpp b/tests/performance-tests/src/services/s3/S3TestConfig.cpp new file mode 100644 index 00000000000..568162e42df --- /dev/null +++ b/tests/performance-tests/src/services/s3/S3TestConfig.cpp @@ -0,0 +1,30 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include + +#include + +namespace PerformanceTest { +namespace Services { +namespace S3 { +namespace TestConfig { + +const std::array TestOperations = {"PutObject", "GetObject"}; + +const std::array TestMatrix = {{{.sizeLabel = "8KB", .sizeBytes = 8 * 1024, .bucketTypeLabel = "s3-standard"}, + {.sizeLabel = "64KB", .sizeBytes = 64 * 1024, .bucketTypeLabel = "s3-standard"}, + {.sizeLabel = "1MB", .sizeBytes = 1024 * 1024, .bucketTypeLabel = "s3-standard"}, + {.sizeLabel = "8KB", .sizeBytes = 8 * 1024, .bucketTypeLabel = "s3-express"}, + {.sizeLabel = "64KB", .sizeBytes = 64 * 1024, .bucketTypeLabel = "s3-express"}, + {.sizeLabel = "1MB", .sizeBytes = 1024 * 1024, .bucketTypeLabel = "s3-express"}}}; + +const char* OutputFilename = "s3-performance-test-results.json"; + +} // namespace TestConfig +} // namespace S3 +} // namespace Services +} // namespace PerformanceTest \ No newline at end of file From a11ba7d7d268c18f9cadd04ea15e55bc537e50c0 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Mon, 7 Jul 2025 18:34:44 -0400 Subject: [PATCH 53/77] refine cmake file for performance tests --- tests/performance-tests/CMakeLists.txt | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/performance-tests/CMakeLists.txt b/tests/performance-tests/CMakeLists.txt index 12c2372b2a6..002a8ca0df3 100644 --- a/tests/performance-tests/CMakeLists.txt +++ b/tests/performance-tests/CMakeLists.txt @@ -9,7 +9,6 @@ add_project(performance-tests aws-cpp-sdk-dynamodb ) -# Add cxxopts dependency include(FetchContent) FetchContent_Declare( cxxopts @@ -18,20 +17,21 @@ FetchContent_Declare( ) FetchContent_MakeAvailable(cxxopts) -function(add_service_test SERVICE SDK_LIB PERF_TEST_FILE) - add_executable(${SERVICE}-performance-test - src/services/${SERVICE}/main.cpp +function(add_service_test SERVICE) + string(TOLOWER ${SERVICE} SERVICE_LOWER) + add_executable(${SERVICE_LOWER}-performance-test + src/services/${SERVICE_LOWER}/main.cpp src/reporting/JsonReportingMetrics.cpp - src/services/${SERVICE}/${PERF_TEST_FILE} - src/services/${SERVICE}/${SERVICE}TestConfig.cpp + src/services/${SERVICE_LOWER}/${SERVICE}PerformanceTest.cpp + src/services/${SERVICE_LOWER}/${SERVICE}TestConfig.cpp ) - set_compiler_flags(${SERVICE}-performance-test) - set_compiler_warnings(${SERVICE}-performance-test) - target_include_directories(${SERVICE}-performance-test PRIVATE include) - target_link_libraries(${SERVICE}-performance-test PRIVATE aws-cpp-sdk-core ${SDK_LIB} cxxopts::cxxopts) - set_property(TARGET ${SERVICE}-performance-test PROPERTY CXX_STANDARD 20) - set_property(TARGET ${SERVICE}-performance-test PROPERTY COMPILE_OPTIONS "-fexceptions") + set_compiler_flags(${SERVICE_LOWER}-performance-test) + set_compiler_warnings(${SERVICE_LOWER}-performance-test) + target_include_directories(${SERVICE_LOWER}-performance-test PRIVATE include) + target_link_libraries(${SERVICE_LOWER}-performance-test PRIVATE aws-cpp-sdk-core aws-cpp-sdk-${SERVICE_LOWER} cxxopts::cxxopts) + set_property(TARGET ${SERVICE_LOWER}-performance-test PROPERTY CXX_STANDARD 20) + set_property(TARGET ${SERVICE_LOWER}-performance-test PROPERTY COMPILE_OPTIONS "-fexceptions") endfunction() -add_service_test(s3 aws-cpp-sdk-s3 S3PerformanceTest.cpp) -add_service_test(dynamodb aws-cpp-sdk-dynamodb DynamoDBPerformanceTest.cpp) +add_service_test(S3) +add_service_test(DynamoDB) From ce98fc9986a1483c13a3a8d6c50777b1bbd87cc3 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Tue, 8 Jul 2025 10:19:28 -0400 Subject: [PATCH 54/77] default set to 10 rather than 3 --- .../services/dynamodb/DynamoDBPerformanceTest.h | 2 +- .../include/performance-tests/services/s3/S3PerformanceTest.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h index 65e94ca132e..5fdde96707e 100644 --- a/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h +++ b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h @@ -29,7 +29,7 @@ struct TestCase { */ class DynamoDBPerformanceTest : public PerformanceTestBase { public: - DynamoDBPerformanceTest(const Aws::String& region, const TestCase& config, int iterations = 3); + DynamoDBPerformanceTest(const Aws::String& region, const TestCase& config, int iterations = 10); void Setup() override; void TearDown() override; diff --git a/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h b/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h index 2d39f19bf19..752d642b3cd 100644 --- a/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h +++ b/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h @@ -30,7 +30,7 @@ struct TestCase { */ class S3PerformanceTest : public PerformanceTestBase { public: - S3PerformanceTest(const Aws::String& region, const TestCase& config, const Aws::String& availabilityZoneId, int iterations = 3); + S3PerformanceTest(const Aws::String& region, const TestCase& config, const Aws::String& availabilityZoneId, int iterations = 10); void Setup() override; void TearDown() override; From 25483fb1b2b128e86a438b5e2de6f4d7c2a17f29 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Tue, 8 Jul 2025 13:44:26 -0400 Subject: [PATCH 55/77] refine dynamodb test --- .../dynamodb/DynamoDBPerformanceTest.cpp | 41 +++++++++++-------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp index 81f5dba5563..d8b148b759c 100644 --- a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp +++ b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp @@ -4,12 +4,11 @@ */ #include -#include #include #include -#include #include #include +#include #include #include #include @@ -43,12 +42,12 @@ void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Setup() { createTableRequest.SetTableName(m_tableName); Aws::DynamoDB::Model::AttributeDefinition hashKey; - hashKey.SetAttributeName("id"); + hashKey.SetAttributeName("data"); hashKey.SetAttributeType(Aws::DynamoDB::Model::ScalarAttributeType::S); createTableRequest.AddAttributeDefinitions(hashKey); Aws::DynamoDB::Model::KeySchemaElement keySchema; - keySchema.WithAttributeName("id").WithKeyType(Aws::DynamoDB::Model::KeyType::HASH); + keySchema.WithAttributeName("data").WithKeyType(Aws::DynamoDB::Model::KeyType::HASH); createTableRequest.AddKeySchema(keySchema); Aws::DynamoDB::Model::BillingMode const billingMode = Aws::DynamoDB::Model::BillingMode::PAY_PER_REQUEST; @@ -62,18 +61,31 @@ void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Setup() { } // Wait for table to become active + const int MAX_QUERIES = 20; Aws::DynamoDB::Model::DescribeTableRequest describeRequest; describeRequest.SetTableName(m_tableName); - while (true) { - auto describeOutcome = m_dynamodb->DescribeTable(describeRequest); + int count = 0; + while (count < MAX_QUERIES) { + const Aws::DynamoDB::Model::DescribeTableOutcome& describeOutcome = m_dynamodb->DescribeTable(describeRequest); if (describeOutcome.IsSuccess()) { - auto status = describeOutcome.GetResult().GetTable().GetTableStatus(); - if (status == Aws::DynamoDB::Model::TableStatus::ACTIVE) { + Aws::DynamoDB::Model::TableStatus status = describeOutcome.GetResult().GetTable().GetTableStatus(); + if (Aws::DynamoDB::Model::TableStatus::ACTIVE == status) { break; } + std::this_thread::sleep_for(std::chrono::seconds(1)); + } else { + AWS_LOG_ERROR("PerformanceTest", ("DynamoDB:DescribeTable failed: " + describeOutcome.GetError().GetMessage()).c_str()); + m_tableName.clear(); + return; } - std::this_thread::sleep_for(std::chrono::seconds(1)); + count++; + } + + if (count >= MAX_QUERIES) { + AWS_LOG_ERROR("PerformanceTest", "DynamoDB:Table did not become active within timeout"); + m_tableName.clear(); + return; } } @@ -95,11 +107,7 @@ void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Run() { Aws::DynamoDB::Model::PutItemRequest putItemRequest; putItemRequest.SetTableName(m_tableName); putItemRequest.SetAdditionalCustomHeaderValue("test-dimension-size", m_config.sizeLabel); - - Aws::Map item; - item["id"].SetS(Aws::String("test-key-") + Aws::Utils::StringUtils::to_string(i)); - item["data"].SetS(payload); - putItemRequest.SetItem(item); + putItemRequest.AddItem("data", Aws::DynamoDB::Model::AttributeValue().SetS(payload)); auto putItemOutcome = m_dynamodb->PutItem(putItemRequest); if (!putItemOutcome.IsSuccess()) { @@ -112,10 +120,7 @@ void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Run() { Aws::DynamoDB::Model::GetItemRequest getItemRequest; getItemRequest.SetTableName(m_tableName); getItemRequest.SetAdditionalCustomHeaderValue("test-dimension-size", m_config.sizeLabel); - - Aws::Map key; - key["id"].SetS(Aws::String("test-key-") + Aws::Utils::StringUtils::to_string(i)); - getItemRequest.SetKey(key); + getItemRequest.AddKey("data", Aws::DynamoDB::Model::AttributeValue().SetS(payload)); auto getItemOutcome = m_dynamodb->GetItem(getItemRequest); if (!getItemOutcome.IsSuccess()) { From af2c72c7ef9a6aa1a5fb0b35f2fd7b3b8d746d91 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Tue, 8 Jul 2025 14:49:45 -0400 Subject: [PATCH 56/77] refine docs for perf test --- docs/CMake_Parameters.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/CMake_Parameters.md b/docs/CMake_Parameters.md index 9f99830012c..274911e910e 100644 --- a/docs/CMake_Parameters.md +++ b/docs/CMake_Parameters.md @@ -129,7 +129,7 @@ You can also tell gcc or clang to pass these linker flags by specifying `-Wl,--g (Defaults to OFF) Enables building the benchmark executable ### BUILD_PERFORMANCE_TESTS -(Defaults to OFF) Enables building the performance test executables for S3 and DynamoDB that measure and report operation latencies in JSON format. Requires S3 and DynamoDB clients to be built. +(Defaults to OFF) Enables building performance test executables for S3 and DynamoDB. These tests measure operation latencies and output results to JSON files. Requires S3 and DynamoDB clients to be built. ### BUILD_OPTEL (Defaults to OFF) Enables building the open telemetry implementation of tracing From 95f9671549bfc466a474690d8016310d8a98aeeb Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Tue, 8 Jul 2025 15:05:43 -0400 Subject: [PATCH 57/77] refine perf test scripts by updating params checks --- .../build-tests/run-al2-dynamodb-performance-tests.sh | 6 +++--- tools/scripts/build-tests/run-al2-s3-performance-tests.sh | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index 66f35313281..f730d239080 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -5,7 +5,7 @@ DEFAULT_REGION="us-east-1" DEFAULT_ITERATIONS=10 if [ "$#" -lt 1 ]; then - echo "Usage: ${0} PREFIX_DIR [--region REGION] [--iterations NUM]" + echo "Usage: ${0} PREFIX_DIR [-r|--region REGION] [-i|--iterations NUM]" exit 1 fi @@ -17,8 +17,8 @@ ITERATIONS="$DEFAULT_ITERATIONS" while [[ "$#" -gt 0 ]]; do case "$1" in - --region) REGION="$2"; shift 2 ;; - --iterations) ITERATIONS="$2"; shift 2 ;; + -r|--region) REGION="$2"; shift 2 ;; + -i|--iterations) ITERATIONS="$2"; shift 2 ;; *) echo "Unknown parameter: $1"; exit 1 ;; esac done diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index f3b0d58f0c9..8b8e1a69bd6 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -6,7 +6,7 @@ DEFAULT_AZ_ID="use1-az4" DEFAULT_ITERATIONS=10 if [ "$#" -lt 1 ]; then - echo "Usage: ${0} PREFIX_DIR [--region REGION] [--az-id AZ_ID] [--iterations NUM]" + echo "Usage: ${0} PREFIX_DIR [-r|--region REGION] [-a|--az-id AZ_ID] [-i|--iterations NUM]" exit 1 fi @@ -19,9 +19,9 @@ ITERATIONS="$DEFAULT_ITERATIONS" while [[ "$#" -gt 0 ]]; do case "$1" in - --region) REGION="$2"; shift 2 ;; - --az-id) AZ_ID="$2"; shift 2 ;; - --iterations) ITERATIONS="$2"; shift 2 ;; + -r|--region) REGION="$2"; shift 2 ;; + -a|--az-id) AZ_ID="$2"; shift 2 ;; + -i|--iterations) ITERATIONS="$2"; shift 2 ;; *) echo "Unknown parameter: $1"; exit 1 ;; esac done From 3fbdd1d0e66406f8eeace6c1177541de7a6b2cb0 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Tue, 8 Jul 2025 15:14:08 -0400 Subject: [PATCH 58/77] refine error msg --- .../build-tests/run-al2-dynamodb-performance-tests.sh | 5 +++-- tools/scripts/build-tests/run-al2-s3-performance-tests.sh | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index f730d239080..a41a20ea9c7 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -5,7 +5,7 @@ DEFAULT_REGION="us-east-1" DEFAULT_ITERATIONS=10 if [ "$#" -lt 1 ]; then - echo "Usage: ${0} PREFIX_DIR [-r|--region REGION] [-i|--iterations NUM]" + echo "Error: Missing required argument. Usage: ${0} PREFIX_DIR [-r|--region REGION] [-i|--iterations NUM]" exit 1 fi @@ -27,7 +27,8 @@ SDK_REPO_PATH="${PREFIX_DIR}/aws-sdk-cpp" if [ -d "$SDK_REPO_PATH" ]; then COMMIT_ID=$(cd "$SDK_REPO_PATH" && git rev-parse HEAD) else - COMMIT_ID="unknown" + echo "Error: Git repository not found at $SDK_REPO_PATH" + exit 1 fi export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index 8b8e1a69bd6..df2792b8fbb 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -6,7 +6,7 @@ DEFAULT_AZ_ID="use1-az4" DEFAULT_ITERATIONS=10 if [ "$#" -lt 1 ]; then - echo "Usage: ${0} PREFIX_DIR [-r|--region REGION] [-a|--az-id AZ_ID] [-i|--iterations NUM]" + echo "Error: Missing required argument. Usage: ${0} PREFIX_DIR [-r|--region REGION] [-a|--az-id AZ_ID] [-i|--iterations NUM]" exit 1 fi @@ -30,7 +30,8 @@ SDK_REPO_PATH="${PREFIX_DIR}/aws-sdk-cpp" if [ -d "$SDK_REPO_PATH" ]; then COMMIT_ID=$(cd "$SDK_REPO_PATH" && git rev-parse HEAD) else - COMMIT_ID="unknown" + echo "Error: Git repository not found at $SDK_REPO_PATH" + exit 1 fi export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" From 2543083b318eefe15bba6dae160c19a7de0336a6 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Tue, 8 Jul 2025 15:21:20 -0400 Subject: [PATCH 59/77] add comments for perf test sh --- .../build-tests/run-al2-dynamodb-performance-tests.sh | 8 ++++++++ tools/scripts/build-tests/run-al2-s3-performance-tests.sh | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index a41a20ea9c7..9725ec7f29e 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -1,4 +1,12 @@ #!/bin/bash +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0. + +# This script runs the pre-built DynamoDB performance test executable +# Expects SDK build directory at ${PREFIX_DIR}/al2-build, source project at ${PREFIX_DIR}/aws-sdk-cpp, +# and SDK installation directory at ${PREFIX_DIR}/al2-install +# Platform: Amazon Linux 2 + set -e DEFAULT_REGION="us-east-1" diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index df2792b8fbb..c415787be9c 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -1,4 +1,12 @@ #!/bin/bash +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0. + +# This script runs the pre-built S3 performance test executable +# Expects SDK build directory at ${PREFIX_DIR}/al2-build, source project at ${PREFIX_DIR}/aws-sdk-cpp, +# and SDK installation directory at ${PREFIX_DIR}/al2-install +# Platform: Amazon Linux 2 + set -e DEFAULT_REGION="us-east-1" From f5c1ce655d9e9e709cc52cea8f391ae51a8a8da8 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Tue, 8 Jul 2025 15:28:39 -0400 Subject: [PATCH 60/77] remove unnecessary renaming --- .../scripts/build-tests/run-al2-dynamodb-performance-tests.sh | 3 +-- tools/scripts/build-tests/run-al2-s3-performance-tests.sh | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index 9725ec7f29e..4b11184903b 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -44,5 +44,4 @@ export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi ./tests/performance-tests/dynamodb-performance-test --region "$REGION" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" -cp dynamodb-performance-test-results.json results.json -cat results.json \ No newline at end of file +cat dynamodb-performance-test-results.json \ No newline at end of file diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index c415787be9c..b77e447f3a1 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -47,5 +47,4 @@ export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi ./tests/performance-tests/s3-performance-test --region "$REGION" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" -cp s3-performance-test-results.json results.json -cat results.json \ No newline at end of file +cat s3-performance-test-results.json \ No newline at end of file From 6343d35313c4590f80902b8abc61f67e21b8cd23 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Fri, 11 Jul 2025 18:08:24 -0400 Subject: [PATCH 61/77] fix most issues of perf tests --- .../CMakeLists.txt | 37 +++++++++++++++ .../performance-tests/PerformanceTestBase.h | 15 +++++- .../dynamodb/DynamoDBPerformanceTest.h | 5 +- .../services/s3/S3PerformanceTest.h | 5 +- .../dynamodb/DynamoDBPerformanceTest.cpp | 47 +++++++------------ .../src/services/dynamodb/main.cpp | 14 ++++-- .../src/services/s3/S3PerformanceTest.cpp | 40 ++++++---------- .../src/services/s3/main.cpp | 15 ++++-- 8 files changed, 107 insertions(+), 71 deletions(-) create mode 100644 tests/generated-performance-tests/CMakeLists.txt diff --git a/tests/generated-performance-tests/CMakeLists.txt b/tests/generated-performance-tests/CMakeLists.txt new file mode 100644 index 00000000000..002a8ca0df3 --- /dev/null +++ b/tests/generated-performance-tests/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0. +# + +add_project(performance-tests + "A suite of AWS C++ SDK performance tests" + aws-cpp-sdk-core + aws-cpp-sdk-s3 + aws-cpp-sdk-dynamodb +) + +include(FetchContent) +FetchContent_Declare( + cxxopts + GIT_REPOSITORY https://github.com/jarro2783/cxxopts.git + GIT_TAG v3.1.1 +) +FetchContent_MakeAvailable(cxxopts) + +function(add_service_test SERVICE) + string(TOLOWER ${SERVICE} SERVICE_LOWER) + add_executable(${SERVICE_LOWER}-performance-test + src/services/${SERVICE_LOWER}/main.cpp + src/reporting/JsonReportingMetrics.cpp + src/services/${SERVICE_LOWER}/${SERVICE}PerformanceTest.cpp + src/services/${SERVICE_LOWER}/${SERVICE}TestConfig.cpp + ) + set_compiler_flags(${SERVICE_LOWER}-performance-test) + set_compiler_warnings(${SERVICE_LOWER}-performance-test) + target_include_directories(${SERVICE_LOWER}-performance-test PRIVATE include) + target_link_libraries(${SERVICE_LOWER}-performance-test PRIVATE aws-cpp-sdk-core aws-cpp-sdk-${SERVICE_LOWER} cxxopts::cxxopts) + set_property(TARGET ${SERVICE_LOWER}-performance-test PROPERTY CXX_STANDARD 20) + set_property(TARGET ${SERVICE_LOWER}-performance-test PROPERTY COMPILE_OPTIONS "-fexceptions") +endfunction() + +add_service_test(S3) +add_service_test(DynamoDB) diff --git a/tests/performance-tests/include/performance-tests/PerformanceTestBase.h b/tests/performance-tests/include/performance-tests/PerformanceTestBase.h index ef4fb45dbf5..ad7431e5c15 100644 --- a/tests/performance-tests/include/performance-tests/PerformanceTestBase.h +++ b/tests/performance-tests/include/performance-tests/PerformanceTestBase.h @@ -5,8 +5,20 @@ #pragma once +#include +#include + namespace PerformanceTest { +/** + * Setup error for performance tests. + */ +struct SetupError { + Aws::String message; + SetupError() = default; + SetupError(const Aws::String& msg) : message(msg) {} +}; + /** * Base class for all performance tests. */ @@ -16,8 +28,9 @@ class PerformanceTestBase { /** * Initialize resources for the test. + * @return Outcome indicating success or failure with error details */ - virtual void Setup() = 0; + virtual Aws::Utils::Outcome Setup() = 0; /** * Run the performance test operations. diff --git a/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h index 5fdde96707e..02914ee1c60 100644 --- a/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h +++ b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -31,12 +32,12 @@ class DynamoDBPerformanceTest : public PerformanceTestBase { public: DynamoDBPerformanceTest(const Aws::String& region, const TestCase& config, int iterations = 10); - void Setup() override; + Aws::Utils::Outcome Setup() override; void TearDown() override; void Run() override; private: - const TestCase& m_config; + const TestCase m_config; const Aws::String m_region; const int m_iterations; Aws::UniquePtr m_dynamodb; diff --git a/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h b/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h index 752d642b3cd..b6fa3dcfccf 100644 --- a/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h +++ b/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -32,12 +33,12 @@ class S3PerformanceTest : public PerformanceTestBase { public: S3PerformanceTest(const Aws::String& region, const TestCase& config, const Aws::String& availabilityZoneId, int iterations = 10); - void Setup() override; + Aws::Utils::Outcome Setup() override; void TearDown() override; void Run() override; private: - const TestCase& m_config; + const TestCase m_config; const Aws::String m_region; const Aws::String m_availabilityZoneId; const int m_iterations; diff --git a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp index d8b148b759c..8b85e77e362 100644 --- a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp +++ b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -21,21 +22,23 @@ #include #include #include +#include #include #include +#include #include #include PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::DynamoDBPerformanceTest(const Aws::String& region, const TestCase& config, int iterations) - : m_config(config), m_region(region), m_iterations(iterations) {} - -void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Setup() { + : m_config(config), m_region(region), m_iterations(iterations) { Aws::Client::ClientConfiguration cfg; cfg.region = m_region; m_dynamodb = Aws::MakeUnique("DynamoDBPerformanceTest", cfg); +} +Aws::Utils::Outcome PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Setup() { m_tableName = "perf-table-" + PerformanceTest::Utils::GenerateUniqueId(); Aws::DynamoDB::Model::CreateTableRequest createTableRequest; @@ -55,9 +58,7 @@ void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Setup() { auto createTableOutcome = m_dynamodb->CreateTable(createTableRequest); if (!createTableOutcome.IsSuccess()) { - AWS_LOG_ERROR("PerformanceTest", ("DynamoDB:CreateTable failed: " + createTableOutcome.GetError().GetMessage()).c_str()); - m_tableName.clear(); - return; + return PerformanceTest::SetupError("DynamoDB Setup() - CreateTable failed: " + createTableOutcome.GetError().GetMessage()); } // Wait for table to become active @@ -75,30 +76,20 @@ void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Setup() { } std::this_thread::sleep_for(std::chrono::seconds(1)); } else { - AWS_LOG_ERROR("PerformanceTest", ("DynamoDB:DescribeTable failed: " + describeOutcome.GetError().GetMessage()).c_str()); - m_tableName.clear(); - return; + return PerformanceTest::SetupError("DynamoDB Setup() - DescribeTable failed: " + describeOutcome.GetError().GetMessage()); } count++; } if (count >= MAX_QUERIES) { - AWS_LOG_ERROR("PerformanceTest", "DynamoDB:Table did not become active within timeout"); - m_tableName.clear(); - return; + return PerformanceTest::SetupError("DynamoDB Setup() - Table did not become active within timeout"); } + return true; } void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Run() { - if (!m_dynamodb) { - AWS_LOG_ERROR("PerformanceTest", "DynamoDB:Run - DynamoDB client not initialized, Setup() failed or was not called"); - return; - } - - if (m_tableName.empty()) { - AWS_LOG_ERROR("PerformanceTest", "DynamoDB:Run - Table setup failed, skipping test"); - return; - } + assert(m_dynamodb && "DynamoDB client not initialized - Setup() must succeed before Run()"); + assert(!m_tableName.empty() && "DynamoDB table name empty - Setup() must succeed before Run()"); const auto payload = PerformanceTest::Utils::RandomString(m_config.sizeBytes); @@ -111,7 +102,7 @@ void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Run() { auto putItemOutcome = m_dynamodb->PutItem(putItemRequest); if (!putItemOutcome.IsSuccess()) { - AWS_LOG_ERROR("PerformanceTest", ("DynamoDB:PutItem failed: " + putItemOutcome.GetError().GetMessage()).c_str()); + AWS_LOG_ERROR("PerformanceTest", ("DynamoDB Run() - PutItem failed: " + putItemOutcome.GetError().GetMessage()).c_str()); } } @@ -124,19 +115,13 @@ void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Run() { auto getItemOutcome = m_dynamodb->GetItem(getItemRequest); if (!getItemOutcome.IsSuccess()) { - AWS_LOG_ERROR("PerformanceTest", ("DynamoDB:GetItem failed: " + getItemOutcome.GetError().GetMessage()).c_str()); + AWS_LOG_ERROR("PerformanceTest", ("DynamoDB Run() - GetItem failed: " + getItemOutcome.GetError().GetMessage()).c_str()); } } } void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::TearDown() { - if (!m_dynamodb) { - AWS_LOG_ERROR("PerformanceTest", "DynamoDB:TearDown - DynamoDB client not initialized, Setup() failed or was not called"); - return; - } - - if (m_tableName.empty()) { - AWS_LOG_ERROR("PerformanceTest", "DynamoDB:TearDown - No table to clean up, setup likely failed"); + if (!m_dynamodb || m_tableName.empty()) { return; } @@ -144,6 +129,6 @@ void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::TearDown() { deleteTableRequest.SetTableName(m_tableName); auto deleteTableOutcome = m_dynamodb->DeleteTable(deleteTableRequest); if (!deleteTableOutcome.IsSuccess()) { - AWS_LOG_ERROR("PerformanceTest", ("DynamoDB:DeleteTable failed: " + deleteTableOutcome.GetError().GetMessage()).c_str()); + AWS_LOG_ERROR("PerformanceTest", ("DynamoDB TearDown() - DeleteTable failed: " + deleteTableOutcome.GetError().GetMessage()).c_str()); } } \ No newline at end of file diff --git a/tests/performance-tests/src/services/dynamodb/main.cpp b/tests/performance-tests/src/services/dynamodb/main.cpp index 542b9626c29..78cc4d22b1e 100644 --- a/tests/performance-tests/src/services/dynamodb/main.cpp +++ b/tests/performance-tests/src/services/dynamodb/main.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -46,11 +47,14 @@ int main(int argc, char** argv) { { for (const auto& config : PerformanceTest::Services::DynamoDB::TestConfig::TestMatrix) { - auto performanceTest = Aws::MakeUnique("DynamoDBPerformanceTest", - region, config, iterations); - performanceTest->Setup(); - performanceTest->Run(); - performanceTest->TearDown(); + PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest performanceTest(region, config, iterations); + auto setupResult = performanceTest.Setup(); + if (setupResult.IsSuccess()) { + performanceTest.Run(); + } else { + AWS_LOG_ERROR("PerformanceTest", setupResult.GetError().message.c_str()); + } + performanceTest.TearDown(); } } diff --git a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp index ea12f6a5669..71fa2a45637 100644 --- a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp +++ b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -21,20 +22,22 @@ #include #include #include +#include #include #include +#include #include PerformanceTest::Services::S3::S3PerformanceTest::S3PerformanceTest(const Aws::String& region, const TestCase& config, const Aws::String& availabilityZoneId, int iterations) - : m_config(config), m_region(region), m_availabilityZoneId(availabilityZoneId), m_iterations(iterations) {} - -void PerformanceTest::Services::S3::S3PerformanceTest::Setup() { + : m_config(config), m_region(region), m_availabilityZoneId(availabilityZoneId), m_iterations(iterations) { Aws::Client::ClientConfiguration cfg; cfg.region = m_region; m_s3 = Aws::MakeUnique("S3PerformanceTest", cfg); +} +Aws::Utils::Outcome PerformanceTest::Services::S3::S3PerformanceTest::Setup() { Aws::S3::Model::CreateBucketRequest cbr; Aws::String const bucketId = PerformanceTest::Utils::GenerateUniqueId(); @@ -57,21 +60,14 @@ void PerformanceTest::Services::S3::S3PerformanceTest::Setup() { auto createOutcome = m_s3->CreateBucket(cbr); if (!createOutcome.IsSuccess()) { - AWS_LOG_ERROR("PerformanceTest", ("S3:CreateBucket failed: " + createOutcome.GetError().GetMessage()).c_str()); - m_bucketName.clear(); + return PerformanceTest::SetupError("S3 Setup() - CreateBucket failed: " + createOutcome.GetError().GetMessage()); } + return true; } void PerformanceTest::Services::S3::S3PerformanceTest::Run() { - if (!m_s3) { - AWS_LOG_ERROR("PerformanceTest", "S3:Run - S3 client not initialized, Setup() failed or was not called"); - return; - } - - if (m_bucketName.empty()) { - AWS_LOG_ERROR("PerformanceTest", "S3:Run - Bucket setup failed, skipping test"); - return; - } + assert(m_s3 && "S3 client not initialized - Setup() must succeed before Run()"); + assert(!m_bucketName.empty() && "S3 bucket name empty - Setup() must succeed before Run()"); const auto randomPayload = PerformanceTest::Utils::RandomString(m_config.sizeBytes); @@ -85,7 +81,7 @@ void PerformanceTest::Services::S3::S3PerformanceTest::Run() { por.SetAdditionalCustomHeaderValue("test-dimension-bucket-type", m_config.bucketTypeLabel); auto putOutcome = m_s3->PutObject(por); if (!putOutcome.IsSuccess()) { - AWS_LOG_ERROR("PerformanceTest", ("S3:PutObject failed: " + putOutcome.GetError().GetMessage()).c_str()); + AWS_LOG_ERROR("PerformanceTest", ("S3 Run() - PutObject failed: " + putOutcome.GetError().GetMessage()).c_str()); } } @@ -97,19 +93,13 @@ void PerformanceTest::Services::S3::S3PerformanceTest::Run() { gor.SetAdditionalCustomHeaderValue("test-dimension-bucket-type", m_config.bucketTypeLabel); auto getOutcome = m_s3->GetObject(gor); if (!getOutcome.IsSuccess()) { - AWS_LOG_ERROR("PerformanceTest", ("S3:GetObject failed: " + getOutcome.GetError().GetMessage()).c_str()); + AWS_LOG_ERROR("PerformanceTest", ("S3 Run() - GetObject failed: " + getOutcome.GetError().GetMessage()).c_str()); } } } void PerformanceTest::Services::S3::S3PerformanceTest::TearDown() { - if (!m_s3) { - AWS_LOG_ERROR("PerformanceTest", "S3:TearDown - S3 client not initialized, Setup() failed or was not called"); - return; - } - - if (m_bucketName.empty()) { - AWS_LOG_ERROR("PerformanceTest", "S3:TearDown - No bucket to clean up, setup likely failed"); + if (!m_s3 || m_bucketName.empty()) { return; } @@ -117,12 +107,12 @@ void PerformanceTest::Services::S3::S3PerformanceTest::TearDown() { auto deleteObjectOutcome = m_s3->DeleteObject( Aws::S3::Model::DeleteObjectRequest().WithBucket(m_bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i))); if (!deleteObjectOutcome.IsSuccess()) { - AWS_LOG_ERROR("PerformanceTest", ("S3:DeleteObject failed: " + deleteObjectOutcome.GetError().GetMessage()).c_str()); + AWS_LOG_ERROR("PerformanceTest", ("S3 TearDown() - DeleteObject failed: " + deleteObjectOutcome.GetError().GetMessage()).c_str()); } } auto deleteBucketOutcome = m_s3->DeleteBucket(Aws::S3::Model::DeleteBucketRequest().WithBucket(m_bucketName)); if (!deleteBucketOutcome.IsSuccess()) { - AWS_LOG_ERROR("PerformanceTest", ("S3:DeleteBucket failed: " + deleteBucketOutcome.GetError().GetMessage()).c_str()); + AWS_LOG_ERROR("PerformanceTest", ("S3 TearDown() - DeleteBucket failed: " + deleteBucketOutcome.GetError().GetMessage()).c_str()); } } \ No newline at end of file diff --git a/tests/performance-tests/src/services/s3/main.cpp b/tests/performance-tests/src/services/s3/main.cpp index 0be30cd4999..f5bf2c36337 100644 --- a/tests/performance-tests/src/services/s3/main.cpp +++ b/tests/performance-tests/src/services/s3/main.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -15,6 +16,7 @@ #include #include +#include #include int main(int argc, char** argv) { @@ -47,11 +49,14 @@ int main(int argc, char** argv) { { for (const auto& config : PerformanceTest::Services::S3::TestConfig::TestMatrix) { - auto performanceTest = Aws::MakeUnique("S3PerformanceTest", region, config, - availabilityZoneId, iterations); - performanceTest->Setup(); - performanceTest->Run(); - performanceTest->TearDown(); + PerformanceTest::Services::S3::S3PerformanceTest performanceTest(region, config, availabilityZoneId, iterations); + auto setupResult = performanceTest.Setup(); + if (setupResult.IsSuccess()) { + performanceTest.Run(); + } else { + AWS_LOG_ERROR("PerformanceTest", setupResult.GetError().message.c_str()); + } + performanceTest.TearDown(); } } From 62c4585a03a08840d6ab9a0a300375818e899d57 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Mon, 14 Jul 2025 14:26:16 -0400 Subject: [PATCH 62/77] remove unused include --- tests/performance-tests/src/services/s3/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/performance-tests/src/services/s3/main.cpp b/tests/performance-tests/src/services/s3/main.cpp index f5bf2c36337..71a063940c5 100644 --- a/tests/performance-tests/src/services/s3/main.cpp +++ b/tests/performance-tests/src/services/s3/main.cpp @@ -16,7 +16,6 @@ #include #include -#include #include int main(int argc, char** argv) { From 43fa40528aefccba91b20e016c790469570127b8 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Mon, 14 Jul 2025 16:51:25 -0400 Subject: [PATCH 63/77] update codegen for performance test --- .../CMakeLists.txt | 37 --------- .../perf-gen/configs/dynamodb_perf_test.json | 47 +++++++++++ tools/perf-gen/configs/s3_perf_test.json | 78 +++++++++++++++++++ .../dynamodb/DynamoDBPerformanceTest.h | 48 ++++++++++++ .../services/dynamodb/DynamoDBTestConfig.h | 22 ++++++ .../services/s3/S3PerformanceTest.h | 50 ++++++++++++ .../services/s3/S3TestConfig.h | 22 ++++++ .../dynamodb/DynamoDBPerformanceTest.cpp | 48 ++++++++++++ .../services/dynamodb/DynamoDBTestConfig.cpp | 25 ++++++ .../src/services/dynamodb/main.cpp | 61 +++++++++++++++ .../src/services/s3/S3PerformanceTest.cpp | 48 ++++++++++++ .../src/services/s3/S3TestConfig.cpp | 25 ++++++ .../src/services/s3/main.cpp | 62 +++++++++++++++ tools/perf-gen/performance_test_generator.py | 54 +++++++++++++ .../perf-gen/templates/PerformanceTest.cpp.j2 | 48 ++++++++++++ tools/perf-gen/templates/PerformanceTest.h.j2 | 58 ++++++++++++++ tools/perf-gen/templates/TestConfig.cpp.j2 | 37 +++++++++ tools/perf-gen/templates/TestConfig.h.j2 | 22 ++++++ tools/perf-gen/templates/main.cpp.j2 | 69 ++++++++++++++++ 19 files changed, 824 insertions(+), 37 deletions(-) delete mode 100644 tests/generated-performance-tests/CMakeLists.txt create mode 100644 tools/perf-gen/configs/dynamodb_perf_test.json create mode 100644 tools/perf-gen/configs/s3_perf_test.json create mode 100644 tools/perf-gen/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h create mode 100644 tools/perf-gen/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h create mode 100644 tools/perf-gen/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h create mode 100644 tools/perf-gen/performance-tests/include/performance-tests/services/s3/S3TestConfig.h create mode 100644 tools/perf-gen/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp create mode 100644 tools/perf-gen/performance-tests/src/services/dynamodb/DynamoDBTestConfig.cpp create mode 100644 tools/perf-gen/performance-tests/src/services/dynamodb/main.cpp create mode 100644 tools/perf-gen/performance-tests/src/services/s3/S3PerformanceTest.cpp create mode 100644 tools/perf-gen/performance-tests/src/services/s3/S3TestConfig.cpp create mode 100644 tools/perf-gen/performance-tests/src/services/s3/main.cpp create mode 100644 tools/perf-gen/performance_test_generator.py create mode 100644 tools/perf-gen/templates/PerformanceTest.cpp.j2 create mode 100644 tools/perf-gen/templates/PerformanceTest.h.j2 create mode 100644 tools/perf-gen/templates/TestConfig.cpp.j2 create mode 100644 tools/perf-gen/templates/TestConfig.h.j2 create mode 100644 tools/perf-gen/templates/main.cpp.j2 diff --git a/tests/generated-performance-tests/CMakeLists.txt b/tests/generated-performance-tests/CMakeLists.txt deleted file mode 100644 index 002a8ca0df3..00000000000 --- a/tests/generated-performance-tests/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0. -# - -add_project(performance-tests - "A suite of AWS C++ SDK performance tests" - aws-cpp-sdk-core - aws-cpp-sdk-s3 - aws-cpp-sdk-dynamodb -) - -include(FetchContent) -FetchContent_Declare( - cxxopts - GIT_REPOSITORY https://github.com/jarro2783/cxxopts.git - GIT_TAG v3.1.1 -) -FetchContent_MakeAvailable(cxxopts) - -function(add_service_test SERVICE) - string(TOLOWER ${SERVICE} SERVICE_LOWER) - add_executable(${SERVICE_LOWER}-performance-test - src/services/${SERVICE_LOWER}/main.cpp - src/reporting/JsonReportingMetrics.cpp - src/services/${SERVICE_LOWER}/${SERVICE}PerformanceTest.cpp - src/services/${SERVICE_LOWER}/${SERVICE}TestConfig.cpp - ) - set_compiler_flags(${SERVICE_LOWER}-performance-test) - set_compiler_warnings(${SERVICE_LOWER}-performance-test) - target_include_directories(${SERVICE_LOWER}-performance-test PRIVATE include) - target_link_libraries(${SERVICE_LOWER}-performance-test PRIVATE aws-cpp-sdk-core aws-cpp-sdk-${SERVICE_LOWER} cxxopts::cxxopts) - set_property(TARGET ${SERVICE_LOWER}-performance-test PROPERTY CXX_STANDARD 20) - set_property(TARGET ${SERVICE_LOWER}-performance-test PROPERTY COMPILE_OPTIONS "-fexceptions") -endfunction() - -add_service_test(S3) -add_service_test(DynamoDB) diff --git a/tools/perf-gen/configs/dynamodb_perf_test.json b/tools/perf-gen/configs/dynamodb_perf_test.json new file mode 100644 index 00000000000..82eb52614ff --- /dev/null +++ b/tools/perf-gen/configs/dynamodb_perf_test.json @@ -0,0 +1,47 @@ +{ + "service": "DynamoDB", + "service_lower": "dynamodb", + "resource_name_variable": "m_tableName", + "operations": [ + "PutItem", + "GetItem" + ], + "test_matrix": [ + { + "sizeLabel": "8KB", + "sizeBytes": "8 * 1024" + }, + { + "sizeLabel": "64KB", + "sizeBytes": "64 * 1024" + }, + { + "sizeLabel": "392KB", + "sizeBytes": "392 * 1024" + } + ], + "output_filename": "dynamodb-performance-test-results.json", + "main_args": [ + { + "name": "region", + "short": "r", + "description": "AWS region", + "type": "std::string", + "default": "us-east-1" + }, + { + "name": "iterations", + "short": "i", + "description": "Number of iterations", + "type": "int", + "default": "10" + }, + { + "name": "commit-id", + "short": "c", + "description": "Commit ID", + "type": "std::string", + "default": "unknown" + } + ] +} \ No newline at end of file diff --git a/tools/perf-gen/configs/s3_perf_test.json b/tools/perf-gen/configs/s3_perf_test.json new file mode 100644 index 00000000000..4d654745853 --- /dev/null +++ b/tools/perf-gen/configs/s3_perf_test.json @@ -0,0 +1,78 @@ +{ + "service": "S3", + "service_lower": "s3", + "resource_name_variable": "m_bucketName", + "operations": [ + "PutObject", + "GetObject" + ], + "constructor_params": [ + { + "type": "const Aws::String&", + "main_arg_name": "az-id" + } + ], + "test_matrix": [ + { + "sizeLabel": "8KB", + "sizeBytes": "8 * 1024", + "bucketTypeLabel": "s3-standard" + }, + { + "sizeLabel": "64KB", + "sizeBytes": "64 * 1024", + "bucketTypeLabel": "s3-standard" + }, + { + "sizeLabel": "1MB", + "sizeBytes": "1024 * 1024", + "bucketTypeLabel": "s3-standard" + }, + { + "sizeLabel": "8KB", + "sizeBytes": "8 * 1024", + "bucketTypeLabel": "s3-express" + }, + { + "sizeLabel": "64KB", + "sizeBytes": "64 * 1024", + "bucketTypeLabel": "s3-express" + }, + { + "sizeLabel": "1MB", + "sizeBytes": "1024 * 1024", + "bucketTypeLabel": "s3-express" + } + ], + "output_filename": "s3-performance-test-results.json", + "main_args": [ + { + "name": "region", + "short": "r", + "description": "AWS region", + "type": "std::string", + "default": "us-east-1" + }, + { + "name": "az-id", + "short": "a", + "description": "Availability zone ID", + "type": "std::string", + "default": "use1-az4" + }, + { + "name": "iterations", + "short": "i", + "description": "Number of iterations", + "type": "int", + "default": "10" + }, + { + "name": "commit-id", + "short": "c", + "description": "Commit ID", + "type": "std::string", + "default": "unknown" + } + ] +} \ No newline at end of file diff --git a/tools/perf-gen/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h b/tools/perf-gen/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h new file mode 100644 index 00000000000..f2b4add5b6c --- /dev/null +++ b/tools/perf-gen/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h @@ -0,0 +1,48 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include + +namespace PerformanceTest { +namespace Services { +namespace DynamoDB { +/** + * Configuration for DynamoDB performance test cases. + */ +struct TestCase { + const char* sizeLabel; + size_t sizeBytes; +}; + +/** + * DynamoDB performance test implementation. + */ +class DynamoDBPerformanceTest : public PerformanceTestBase { + public: + DynamoDBPerformanceTest(const Aws::String& region, const TestCase& config, int iterations = 10); + + Aws::Utils::Outcome Setup() override; + void TearDown() override; + void Run() override; + + private: + const TestCase m_config; + const Aws::String m_region; + const int m_iterations; + Aws::UniquePtr m_dynamodb; + Aws::String m_tableName; +}; + +} // namespace DynamoDB +} // namespace Services +} // namespace PerformanceTest \ No newline at end of file diff --git a/tools/perf-gen/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h b/tools/perf-gen/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h new file mode 100644 index 00000000000..467b3efa552 --- /dev/null +++ b/tools/perf-gen/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h @@ -0,0 +1,22 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once + +#include + +#include + +namespace PerformanceTest { +namespace Services { +namespace DynamoDB { +namespace TestConfig { +extern const std::array TestOperations; +extern const std::array TestMatrix; +extern const char* OutputFilename; +} // namespace TestConfig +} // namespace DynamoDB +} // namespace Services +} // namespace PerformanceTest \ No newline at end of file diff --git a/tools/perf-gen/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h b/tools/perf-gen/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h new file mode 100644 index 00000000000..84c4387cad2 --- /dev/null +++ b/tools/perf-gen/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h @@ -0,0 +1,50 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include + +namespace PerformanceTest { +namespace Services { +namespace S3 { +/** + * Configuration for S3 performance test cases. + */ +struct TestCase { + const char* sizeLabel; + size_t sizeBytes; + const char* bucketTypeLabel; +}; + +/** + * S3 performance test implementation. + */ +class S3PerformanceTest : public PerformanceTestBase { + public: + S3PerformanceTest(const Aws::String& region, const TestCase& config, const Aws::String& az_id, int iterations = 10); + + Aws::Utils::Outcome Setup() override; + void TearDown() override; + void Run() override; + + private: + const TestCase m_config; + const Aws::String m_region; + const Aws::String m_az_id; + const int m_iterations; + Aws::UniquePtr m_s3; + Aws::String m_bucketName; +}; + +} // namespace S3 +} // namespace Services +} // namespace PerformanceTest \ No newline at end of file diff --git a/tools/perf-gen/performance-tests/include/performance-tests/services/s3/S3TestConfig.h b/tools/perf-gen/performance-tests/include/performance-tests/services/s3/S3TestConfig.h new file mode 100644 index 00000000000..1daa595ba52 --- /dev/null +++ b/tools/perf-gen/performance-tests/include/performance-tests/services/s3/S3TestConfig.h @@ -0,0 +1,22 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once + +#include + +#include + +namespace PerformanceTest { +namespace Services { +namespace S3 { +namespace TestConfig { +extern const std::array TestOperations; +extern const std::array TestMatrix; +extern const char* OutputFilename; +} // namespace TestConfig +} // namespace S3 +} // namespace Services +} // namespace PerformanceTest \ No newline at end of file diff --git a/tools/perf-gen/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp b/tools/perf-gen/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp new file mode 100644 index 00000000000..fc05745c0d5 --- /dev/null +++ b/tools/perf-gen/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp @@ -0,0 +1,48 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// Include the service-specific AWS SDK headers here. +PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::DynamoDBPerformanceTest(const Aws::String& region, const TestCase& config, int iterations) + : m_config(config), m_region(region), m_iterations(iterations) { + Aws::Client::ClientConfiguration cfg; + cfg.region = m_region; + m_dynamodb = Aws::MakeUnique("DynamoDBPerformanceTest", cfg); +} + +Aws::Utils::Outcome PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Setup() { + // Write resource Setup logic here. + + return true; +} + +void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Run() { + assert(m_dynamodb && "DynamoDB client not initialized - Setup() must succeed before Run()"); + assert(!m_tableName.empty() && "DynamoDB resource name empty - Setup() must succeed before Run()"); + + // Write Run logic here. +} + +void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::TearDown() { + if (!m_dynamodb || m_tableName.empty()) { + return; + } + + // Write resource cleanup (TearDown) logic here. +} \ No newline at end of file diff --git a/tools/perf-gen/performance-tests/src/services/dynamodb/DynamoDBTestConfig.cpp b/tools/perf-gen/performance-tests/src/services/dynamodb/DynamoDBTestConfig.cpp new file mode 100644 index 00000000000..06e10084c27 --- /dev/null +++ b/tools/perf-gen/performance-tests/src/services/dynamodb/DynamoDBTestConfig.cpp @@ -0,0 +1,25 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include + +#include + +namespace PerformanceTest { +namespace Services { +namespace DynamoDB { +namespace TestConfig { + +const std::array TestOperations = {"PutItem", "GetItem"}; + +const std::array TestMatrix = {{{.sizeLabel = "8KB", .sizeBytes = 8 * 1024},{.sizeLabel = "64KB", .sizeBytes = 64 * 1024},{.sizeLabel = "392KB", .sizeBytes = 392 * 1024}}}; + +const char* OutputFilename = "dynamodb-performance-test-results.json"; + +} // namespace TestConfig +} // namespace DynamoDB +} // namespace Services +} // namespace PerformanceTest \ No newline at end of file diff --git a/tools/perf-gen/performance-tests/src/services/dynamodb/main.cpp b/tools/perf-gen/performance-tests/src/services/dynamodb/main.cpp new file mode 100644 index 00000000000..211e1748d6a --- /dev/null +++ b/tools/perf-gen/performance-tests/src/services/dynamodb/main.cpp @@ -0,0 +1,61 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +int main(int argc, char** argv) { + cxxopts::Options options("dynamodb-perf-test", "DynamoDB Performance Test"); + options.add_options()("r,region", "AWS region", cxxopts::value()->default_value("us-east-1"))("i,iterations", "Number of iterations", cxxopts::value()->default_value("10"))("c,commit-id", "Commit ID", cxxopts::value()->default_value("unknown")); + + auto const result = options.parse(argc, argv); + + Aws::String const region = Aws::Utils::StringUtils::to_string(result["region"].as()); + int const iterations = result["iterations"].as(); + Aws::String const commit_id = Aws::Utils::StringUtils::to_string(result["commit-id"].as()); + + Aws::SDKOptions sdkOptions; + Aws::String const versionStr = Aws::Version::GetVersionString(); + + sdkOptions.monitoringOptions.customizedMonitoringFactory_create_fn = {[&]() -> Aws::UniquePtr { + Aws::Set operations; + for (const auto& operation : PerformanceTest::Services::DynamoDB::TestConfig::TestOperations) { + operations.insert(operation); + } + return Aws::MakeUnique( + "JsonReportingMetricsFactory", operations, "cpp1", versionStr, commit_id, PerformanceTest::Services::DynamoDB::TestConfig::OutputFilename); + }}; + + Aws::InitAPI(sdkOptions); + + { + for (const auto& config : PerformanceTest::Services::DynamoDB::TestConfig::TestMatrix) { + PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest performanceTest(region, config, iterations); + auto setupResult = performanceTest.Setup(); + if (setupResult.IsSuccess()) { + performanceTest.Run(); + } else { + AWS_LOG_ERROR("PerformanceTest", setupResult.GetError().message.c_str()); + } + performanceTest.TearDown(); + } + } + + Aws::ShutdownAPI(sdkOptions); + return 0; +} \ No newline at end of file diff --git a/tools/perf-gen/performance-tests/src/services/s3/S3PerformanceTest.cpp b/tools/perf-gen/performance-tests/src/services/s3/S3PerformanceTest.cpp new file mode 100644 index 00000000000..c543604a173 --- /dev/null +++ b/tools/perf-gen/performance-tests/src/services/s3/S3PerformanceTest.cpp @@ -0,0 +1,48 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// Include the service-specific AWS SDK headers here. +PerformanceTest::Services::S3::S3PerformanceTest::S3PerformanceTest(const Aws::String& region, const TestCase& config, const Aws::String& az_id, int iterations) + : m_config(config), m_region(region), m_az_id(az_id), m_iterations(iterations) { + Aws::Client::ClientConfiguration cfg; + cfg.region = m_region; + m_s3 = Aws::MakeUnique("S3PerformanceTest", cfg); +} + +Aws::Utils::Outcome PerformanceTest::Services::S3::S3PerformanceTest::Setup() { + // Write resource Setup logic here. + + return true; +} + +void PerformanceTest::Services::S3::S3PerformanceTest::Run() { + assert(m_s3 && "S3 client not initialized - Setup() must succeed before Run()"); + assert(!m_bucketName.empty() && "S3 resource name empty - Setup() must succeed before Run()"); + + // Write Run logic here. +} + +void PerformanceTest::Services::S3::S3PerformanceTest::TearDown() { + if (!m_s3 || m_bucketName.empty()) { + return; + } + + // Write resource cleanup (TearDown) logic here. +} \ No newline at end of file diff --git a/tools/perf-gen/performance-tests/src/services/s3/S3TestConfig.cpp b/tools/perf-gen/performance-tests/src/services/s3/S3TestConfig.cpp new file mode 100644 index 00000000000..f19ecc4cde8 --- /dev/null +++ b/tools/perf-gen/performance-tests/src/services/s3/S3TestConfig.cpp @@ -0,0 +1,25 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include + +#include + +namespace PerformanceTest { +namespace Services { +namespace S3 { +namespace TestConfig { + +const std::array TestOperations = {"PutObject", "GetObject"}; + +const std::array TestMatrix = {{{.sizeLabel = "8KB", .sizeBytes = 8 * 1024, .bucketTypeLabel = "s3-standard"},{.sizeLabel = "64KB", .sizeBytes = 64 * 1024, .bucketTypeLabel = "s3-standard"},{.sizeLabel = "1MB", .sizeBytes = 1024 * 1024, .bucketTypeLabel = "s3-standard"},{.sizeLabel = "8KB", .sizeBytes = 8 * 1024, .bucketTypeLabel = "s3-express"},{.sizeLabel = "64KB", .sizeBytes = 64 * 1024, .bucketTypeLabel = "s3-express"},{.sizeLabel = "1MB", .sizeBytes = 1024 * 1024, .bucketTypeLabel = "s3-express"}}}; + +const char* OutputFilename = "s3-performance-test-results.json"; + +} // namespace TestConfig +} // namespace S3 +} // namespace Services +} // namespace PerformanceTest \ No newline at end of file diff --git a/tools/perf-gen/performance-tests/src/services/s3/main.cpp b/tools/perf-gen/performance-tests/src/services/s3/main.cpp new file mode 100644 index 00000000000..10a60b720aa --- /dev/null +++ b/tools/perf-gen/performance-tests/src/services/s3/main.cpp @@ -0,0 +1,62 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +int main(int argc, char** argv) { + cxxopts::Options options("s3-perf-test", "S3 Performance Test"); + options.add_options()("r,region", "AWS region", cxxopts::value()->default_value("us-east-1"))("a,az-id", "Availability zone ID", cxxopts::value()->default_value("use1-az4"))("i,iterations", "Number of iterations", cxxopts::value()->default_value("10"))("c,commit-id", "Commit ID", cxxopts::value()->default_value("unknown")); + + auto const result = options.parse(argc, argv); + + Aws::String const region = Aws::Utils::StringUtils::to_string(result["region"].as()); + Aws::String const az_id = Aws::Utils::StringUtils::to_string(result["az-id"].as()); + int const iterations = result["iterations"].as(); + Aws::String const commit_id = Aws::Utils::StringUtils::to_string(result["commit-id"].as()); + + Aws::SDKOptions sdkOptions; + Aws::String const versionStr = Aws::Version::GetVersionString(); + + sdkOptions.monitoringOptions.customizedMonitoringFactory_create_fn = {[&]() -> Aws::UniquePtr { + Aws::Set operations; + for (const auto& operation : PerformanceTest::Services::S3::TestConfig::TestOperations) { + operations.insert(operation); + } + return Aws::MakeUnique( + "JsonReportingMetricsFactory", operations, "cpp1", versionStr, commit_id, PerformanceTest::Services::S3::TestConfig::OutputFilename); + }}; + + Aws::InitAPI(sdkOptions); + + { + for (const auto& config : PerformanceTest::Services::S3::TestConfig::TestMatrix) { + PerformanceTest::Services::S3::S3PerformanceTest performanceTest(region, config, az_id, iterations); + auto setupResult = performanceTest.Setup(); + if (setupResult.IsSuccess()) { + performanceTest.Run(); + } else { + AWS_LOG_ERROR("PerformanceTest", setupResult.GetError().message.c_str()); + } + performanceTest.TearDown(); + } + } + + Aws::ShutdownAPI(sdkOptions); + return 0; +} \ No newline at end of file diff --git a/tools/perf-gen/performance_test_generator.py b/tools/perf-gen/performance_test_generator.py new file mode 100644 index 00000000000..74b910f1f15 --- /dev/null +++ b/tools/perf-gen/performance_test_generator.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 + +import os +import json +from jinja2 import Environment, FileSystemLoader +import argparse + +def generate_performance_test(config_path, template_dir, output_dir): + with open(config_path, 'r', encoding='utf-8') as f: + config = json.load(f) + + service_name = config['service'] + service_lower = config['service_lower'] + + env = Environment( + loader=FileSystemLoader(template_dir), + trim_blocks=True, + lstrip_blocks=True + ) + + service_src_dir = os.path.join(output_dir, f"performance-tests/src/services/{service_lower}") + service_include_dir = os.path.join(output_dir, f"performance-tests/include/performance-tests/services/{service_lower}") + + os.makedirs(service_src_dir, exist_ok=True) + os.makedirs(service_include_dir, exist_ok=True) + + templates_to_render = { + 'main.cpp.j2': os.path.join(service_src_dir, 'main.cpp'), + 'PerformanceTest.h.j2': os.path.join(service_include_dir, f'{service_name}PerformanceTest.h'), + 'PerformanceTest.cpp.j2': os.path.join(service_src_dir, f'{service_name}PerformanceTest.cpp'), + 'TestConfig.h.j2': os.path.join(service_include_dir, f'{service_name}TestConfig.h'), + 'TestConfig.cpp.j2': os.path.join(service_src_dir, f'{service_name}TestConfig.cpp'), + } + + for template_file, output_path in templates_to_render.items(): + template = env.get_template(template_file) + rendered_content = template.render(config) + with open(output_path, 'w', encoding='utf-8') as f: + f.write(rendered_content) + print(f"Successfully generated file: {output_path}") + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Generate a performance test framework for the AWS C++ SDK.') + parser.add_argument('--config', required=True, help='Path to the service JSON configuration file.') + parser.add_argument('--templates', default='templates', help='Path to the directory containing Jinja2 templates.') + parser.add_argument('--output', default='.', help='The root output directory for the generated code.') + + args = parser.parse_args() + + if not os.path.exists(args.config): + print(f"Error: Configuration file '{args.config}' not found.") + exit(1) + + generate_performance_test(args.config, args.templates, args.output) \ No newline at end of file diff --git a/tools/perf-gen/templates/PerformanceTest.cpp.j2 b/tools/perf-gen/templates/PerformanceTest.cpp.j2 new file mode 100644 index 00000000000..1e6d4fbe5cb --- /dev/null +++ b/tools/perf-gen/templates/PerformanceTest.cpp.j2 @@ -0,0 +1,48 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// Include the service-specific AWS SDK headers here. +PerformanceTest::Services::{{ service }}::{{ service }}PerformanceTest::{{ service }}PerformanceTest(const Aws::String& region, const TestCase& config, {% if constructor_params %}{% for param in constructor_params %}{{ param.type }} {{ param.main_arg_name | replace('-', '_') }}{% if not loop.last %}, {% endif %}{% endfor %}, {% endif %}int iterations) + : m_config(config), m_region(region){% if constructor_params %}, {% for param in constructor_params %}m_{{ param.main_arg_name | replace('-', '_') }}({{ param.main_arg_name | replace('-', '_') }}){% if not loop.last %}, {% endif %}{% endfor %}{% endif %}, m_iterations(iterations) { + Aws::Client::ClientConfiguration cfg; + cfg.region = m_region; + m_{{ service_lower }} = Aws::MakeUnique("{{ service }}PerformanceTest", cfg); +} + +Aws::Utils::Outcome PerformanceTest::Services::{{ service }}::{{ service }}PerformanceTest::Setup() { + // Write resource Setup logic here. + + return true; +} + +void PerformanceTest::Services::{{ service }}::{{ service }}PerformanceTest::Run() { + assert(m_{{ service_lower }} && "{{ service }} client not initialized - Setup() must succeed before Run()"); + assert(!{{ resource_name_variable }}.empty() && "{{ service }} resource name empty - Setup() must succeed before Run()"); + + // Write Run logic here. +} + +void PerformanceTest::Services::{{ service }}::{{ service }}PerformanceTest::TearDown() { + if (!m_{{ service_lower }} || {{ resource_name_variable }}.empty()) { + return; + } + + // Write resource cleanup (TearDown) logic here. +} \ No newline at end of file diff --git a/tools/perf-gen/templates/PerformanceTest.h.j2 b/tools/perf-gen/templates/PerformanceTest.h.j2 new file mode 100644 index 00000000000..9ce09bf0473 --- /dev/null +++ b/tools/perf-gen/templates/PerformanceTest.h.j2 @@ -0,0 +1,58 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include + +namespace PerformanceTest { +namespace Services { +namespace {{ service }} { +/** + * Configuration for {{ service }} performance test cases. + */ +struct TestCase { +{% for key in test_matrix[0].keys() %} +{% if key.endswith("Bytes") %} + size_t {{ key }}; +{% else %} + const char* {{ key }}; +{% endif %} +{% endfor %} +}; + +/** + * {{ service }} performance test implementation. + */ +class {{ service }}PerformanceTest : public PerformanceTestBase { + public: + {{ service }}PerformanceTest(const Aws::String& region, const TestCase& config, {% if constructor_params %}{% for param in constructor_params %}{{ param.type }} {{ param.main_arg_name | replace('-', '_') }}{% if not loop.last %}, {% endif %}{% endfor %}, {% endif %}int iterations = 10); + + Aws::Utils::Outcome Setup() override; + void TearDown() override; + void Run() override; + + private: + const TestCase m_config; + const Aws::String m_region; +{% if constructor_params %} +{% for param in constructor_params %} + const Aws::String m_{{ param.main_arg_name | replace('-', '_') }}; +{% endfor %} +{% endif %} + const int m_iterations; + Aws::UniquePtr m_{{ service_lower }}; + Aws::String {{ resource_name_variable }}; +}; + +} // namespace {{ service }} +} // namespace Services +} // namespace PerformanceTest \ No newline at end of file diff --git a/tools/perf-gen/templates/TestConfig.cpp.j2 b/tools/perf-gen/templates/TestConfig.cpp.j2 new file mode 100644 index 00000000000..f6a50b371e8 --- /dev/null +++ b/tools/perf-gen/templates/TestConfig.cpp.j2 @@ -0,0 +1,37 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include + +#include + +namespace PerformanceTest { +namespace Services { +namespace {{ service }} { +namespace TestConfig { + +const std::array TestOperations = { +{%- for op in operations -%} +"{{ op }}"{% if not loop.last %}, {% endif %} +{%- endfor -%} +}; + +const std::array TestMatrix = {% raw %}{{% endraw %}{% raw %}{{% endraw %} +{% for item in test_matrix %} +{ +{%- for key, value in item.items() -%} +.{{ key }} = {% if key.endswith('Bytes') %}{{ value }}{% else %}"{{ value }}"{% endif %}{% if not loop.last %}, {% endif %} +{%- endfor -%} +}{% if not loop.last %},{% endif %} +{% endfor %} +{% raw %}}{% endraw %}{% raw %}}{% endraw %}; + +const char* OutputFilename = "{{ output_filename }}"; + +} // namespace TestConfig +} // namespace {{ service }} +} // namespace Services +} // namespace PerformanceTest \ No newline at end of file diff --git a/tools/perf-gen/templates/TestConfig.h.j2 b/tools/perf-gen/templates/TestConfig.h.j2 new file mode 100644 index 00000000000..9708cb6b68d --- /dev/null +++ b/tools/perf-gen/templates/TestConfig.h.j2 @@ -0,0 +1,22 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#pragma once + +#include + +#include + +namespace PerformanceTest { +namespace Services { +namespace {{ service }} { +namespace TestConfig { +extern const std::array TestOperations; +extern const std::array TestMatrix; +extern const char* OutputFilename; +} // namespace TestConfig +} // namespace {{ service }} +} // namespace Services +} // namespace PerformanceTest \ No newline at end of file diff --git a/tools/perf-gen/templates/main.cpp.j2 b/tools/perf-gen/templates/main.cpp.j2 new file mode 100644 index 00000000000..044583fd6e0 --- /dev/null +++ b/tools/perf-gen/templates/main.cpp.j2 @@ -0,0 +1,69 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +int main(int argc, char** argv) { + cxxopts::Options options("{{ service_lower }}-perf-test", "{{ service }} Performance Test"); + options.add_options() +{%- for arg in main_args -%} +("{{ arg.short }},{{ arg.name }}", "{{ arg.description }}", cxxopts::value<{{ arg.type }}>()->default_value("{{ arg.default }}")) +{%- endfor -%} +; + + auto const result = options.parse(argc, argv); + +{% for arg in main_args %} +{% if arg.type == 'int' %} + int const {{ arg.name | replace('-', '_') }} = result["{{ arg.name }}"].as(); +{% else %} + Aws::String const {{ arg.name | replace('-', '_') }} = Aws::Utils::StringUtils::to_string(result["{{ arg.name }}"].as()); +{% endif %} +{% endfor %} + + Aws::SDKOptions sdkOptions; + Aws::String const versionStr = Aws::Version::GetVersionString(); + + sdkOptions.monitoringOptions.customizedMonitoringFactory_create_fn = {[&]() -> Aws::UniquePtr { + Aws::Set operations; + for (const auto& operation : PerformanceTest::Services::{{ service }}::TestConfig::TestOperations) { + operations.insert(operation); + } + return Aws::MakeUnique( + "JsonReportingMetricsFactory", operations, "cpp1", versionStr, commit_id, PerformanceTest::Services::{{ service }}::TestConfig::OutputFilename); + }}; + + Aws::InitAPI(sdkOptions); + + { + for (const auto& config : PerformanceTest::Services::{{ service }}::TestConfig::TestMatrix) { + PerformanceTest::Services::{{ service }}::{{ service }}PerformanceTest performanceTest(region, config, {% if constructor_params %}{% for param in constructor_params %}{{ param.main_arg_name | replace('-', '_') }}{% if not loop.last %}, {% endif %}{% endfor %}, {% endif %}iterations); + auto setupResult = performanceTest.Setup(); + if (setupResult.IsSuccess()) { + performanceTest.Run(); + } else { + AWS_LOG_ERROR("PerformanceTest", setupResult.GetError().message.c_str()); + } + performanceTest.TearDown(); + } + } + + Aws::ShutdownAPI(sdkOptions); + return 0; +} \ No newline at end of file From a1c103df7d5c25ccb1ed37ba08d7b9bb405c0e20 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Wed, 16 Jul 2025 00:41:12 -0400 Subject: [PATCH 64/77] exclude perf-gen from endpointers_checker --- tools/scripts/endpoints_checker.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/scripts/endpoints_checker.py b/tools/scripts/endpoints_checker.py index 80fc38170d0..7d14ad11089 100644 --- a/tools/scripts/endpoints_checker.py +++ b/tools/scripts/endpoints_checker.py @@ -47,6 +47,7 @@ def skip_file(filename): '|.*source/[^/]+Endpoint.cpp' '|.*aws-cpp-sdk-core/include/aws/core/Region.h' '|.*tests/.*Test.cpp' + '|.*tools/perf-gen/' # add more white lists here ) if skip_file_pattern.match(filename): From 3609f100d7390b803132341a93675e5bc5871697 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Wed, 16 Jul 2025 00:42:03 -0400 Subject: [PATCH 65/77] address issues from DynamoDB PR --- .../performance-tests/PerformanceTestBase.h | 11 +--- .../dynamodb/DynamoDBPerformanceTest.h | 27 ++++------ .../services/dynamodb/DynamoDBTestConfig.h | 36 ++++++++++++- .../services/s3/S3PerformanceTest.h | 30 ++++------- .../services/s3/S3TestConfig.h | 49 +++++++++++++++++- .../dynamodb/DynamoDBPerformanceTest.cpp | 39 ++++++--------- .../services/dynamodb/DynamoDBTestConfig.cpp | 30 +++++++++-- .../src/services/dynamodb/main.cpp | 13 +++-- .../src/services/s3/S3PerformanceTest.cpp | 50 ++++++++----------- .../src/services/s3/S3TestConfig.cpp | 46 ++++++++++++++--- .../src/services/s3/main.cpp | 13 +++-- 11 files changed, 223 insertions(+), 121 deletions(-) diff --git a/tests/performance-tests/include/performance-tests/PerformanceTestBase.h b/tests/performance-tests/include/performance-tests/PerformanceTestBase.h index ad7431e5c15..4f0c05fc439 100644 --- a/tests/performance-tests/include/performance-tests/PerformanceTestBase.h +++ b/tests/performance-tests/include/performance-tests/PerformanceTestBase.h @@ -10,15 +10,6 @@ namespace PerformanceTest { -/** - * Setup error for performance tests. - */ -struct SetupError { - Aws::String message; - SetupError() = default; - SetupError(const Aws::String& msg) : message(msg) {} -}; - /** * Base class for all performance tests. */ @@ -30,7 +21,7 @@ class PerformanceTestBase { * Initialize resources for the test. * @return Outcome indicating success or failure with error details */ - virtual Aws::Utils::Outcome Setup() = 0; + virtual Aws::Utils::Outcome Setup() = 0; /** * Run the performance test operations. diff --git a/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h index 02914ee1c60..03cf247a82f 100644 --- a/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h +++ b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h @@ -5,24 +5,17 @@ #pragma once +#include +#include #include #include -#include #include #include - -#include +#include namespace PerformanceTest { namespace Services { namespace DynamoDB { -/** - * Configuration for DynamoDB performance test cases. - */ -struct TestCase { - const char* sizeLabel; - size_t sizeBytes; -}; /** * DynamoDB performance test implementation. @@ -30,18 +23,18 @@ struct TestCase { */ class DynamoDBPerformanceTest : public PerformanceTestBase { public: - DynamoDBPerformanceTest(const Aws::String& region, const TestCase& config, int iterations = 10); + DynamoDBPerformanceTest(const Aws::Client::ClientConfiguration& clientConfig, const TestConfig::TestCase& testConfig, + int iterations = 10); - Aws::Utils::Outcome Setup() override; - void TearDown() override; + Aws::Utils::Outcome Setup() override; void Run() override; + void TearDown() override; private: - const TestCase m_config; - const Aws::String m_region; + const Aws::UniquePtr m_dynamodb; + const TestConfig::TestCase m_testConfig; const int m_iterations; - Aws::UniquePtr m_dynamodb; - Aws::String m_tableName; + const Aws::String m_tableName; }; } // namespace DynamoDB diff --git a/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h index 467b3efa552..786a2032f2e 100644 --- a/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h +++ b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBTestConfig.h @@ -5,17 +5,51 @@ #pragma once -#include +#include #include +#include namespace PerformanceTest { namespace Services { namespace DynamoDB { namespace TestConfig { + +/** + * Payload sizes for DynamoDB performance tests. + */ +enum class PayloadSize { K8, K64, K392 }; + +/** + * Configuration for DynamoDB performance test cases. + */ +struct TestCase { + PayloadSize payloadSize; +}; + +/** + * Get the payload size in bytes for a given PayloadSize enum. + * @param payloadSize The PayloadSize enum value + * @return Size in bytes + */ +size_t GetPayloadSizeInBytes(PayloadSize payloadSize); + +/** + * Get the string label for a given PayloadSize enum. + * @param payloadSize The PayloadSize enum value + * @return String label (e.g., "8KB", "64KB", "392KB") + */ +Aws::String GetPayloadSizeLabel(PayloadSize payloadSize); + +/** Operations tested in DynamoDB performance tests. */ extern const std::array TestOperations; + +/** Array of all test case combinations. */ extern const std::array TestMatrix; + +/** Output filename for test results. */ extern const char* OutputFilename; + } // namespace TestConfig } // namespace DynamoDB } // namespace Services diff --git a/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h b/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h index b6fa3dcfccf..9583f9552fb 100644 --- a/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h +++ b/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h @@ -5,25 +5,17 @@ #pragma once +#include +#include #include #include -#include #include #include - -#include +#include namespace PerformanceTest { namespace Services { namespace S3 { -/** - * Configuration for S3 performance test cases. - */ -struct TestCase { - const char* sizeLabel; - size_t sizeBytes; - const char* bucketTypeLabel; -}; /** * S3 performance test implementation. @@ -31,19 +23,19 @@ struct TestCase { */ class S3PerformanceTest : public PerformanceTestBase { public: - S3PerformanceTest(const Aws::String& region, const TestCase& config, const Aws::String& availabilityZoneId, int iterations = 10); + S3PerformanceTest(const Aws::Client::ClientConfiguration& clientConfig, const TestConfig::TestCase& testConfig, int iterations = 10, + const Aws::String& availabilityZoneId = ""); - Aws::Utils::Outcome Setup() override; - void TearDown() override; + Aws::Utils::Outcome Setup() override; void Run() override; + void TearDown() override; private: - const TestCase m_config; - const Aws::String m_region; - const Aws::String m_availabilityZoneId; + const Aws::UniquePtr m_s3; + const TestConfig::TestCase m_testConfig; const int m_iterations; - Aws::UniquePtr m_s3; - Aws::String m_bucketName; + const Aws::String m_bucketName; + const Aws::String m_availabilityZoneId; }; } // namespace S3 diff --git a/tests/performance-tests/include/performance-tests/services/s3/S3TestConfig.h b/tests/performance-tests/include/performance-tests/services/s3/S3TestConfig.h index 1daa595ba52..9f180b21c59 100644 --- a/tests/performance-tests/include/performance-tests/services/s3/S3TestConfig.h +++ b/tests/performance-tests/include/performance-tests/services/s3/S3TestConfig.h @@ -5,17 +5,64 @@ #pragma once -#include +#include #include +#include namespace PerformanceTest { namespace Services { namespace S3 { namespace TestConfig { + +/** + * Payload sizes for S3 performance tests. + */ +enum class PayloadSize { K8, K64, M1 }; + +/** + * Bucket types for S3 performance tests. + */ +enum class BucketType { Standard, Express }; + +/** + * Configuration for S3 performance test cases. + */ +struct TestCase { + PayloadSize payloadSize; + BucketType bucketType; +}; + +/** + * Get the payload size in bytes for a given PayloadSize enum. + * @param payloadSize The PayloadSize enum value + * @return Size in bytes + */ +size_t GetPayloadSizeInBytes(PayloadSize payloadSize); + +/** + * Get the string label for a given PayloadSize enum. + * @param payloadSize The PayloadSize enum value + * @return String label (e.g., "8KB", "64KB", "1MB") + */ +Aws::String GetPayloadSizeLabel(PayloadSize payloadSize); + +/** + * Get the string label for a given BucketType enum. + * @param bucketType The BucketType enum value + * @return String label (e.g., "s3-standard", "s3-express") + */ +Aws::String GetBucketTypeLabel(BucketType bucketType); + +/** Operations tested in S3 performance tests. */ extern const std::array TestOperations; + +/** Array of all test case combinations. */ extern const std::array TestMatrix; + +/** Output filename for test results. */ extern const char* OutputFilename; + } // namespace TestConfig } // namespace S3 } // namespace Services diff --git a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp index 8b85e77e362..2f9dba5c039 100644 --- a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp +++ b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp @@ -22,25 +22,25 @@ #include #include #include -#include #include #include +#include #include #include #include -PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::DynamoDBPerformanceTest(const Aws::String& region, const TestCase& config, +PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::DynamoDBPerformanceTest(const Aws::Client::ClientConfiguration& clientConfig, + const TestConfig::TestCase& testConfig, int iterations) - : m_config(config), m_region(region), m_iterations(iterations) { - Aws::Client::ClientConfiguration cfg; - cfg.region = m_region; - m_dynamodb = Aws::MakeUnique("DynamoDBPerformanceTest", cfg); + : m_dynamodb(Aws::MakeUnique("DynamoDBPerformanceTest", clientConfig)), + m_testConfig(testConfig), + m_iterations(iterations), + m_tableName("perf-table-" + PerformanceTest::Utils::GenerateUniqueId()) { + assert(m_dynamodb && "DynamoDB client not initialized"); } -Aws::Utils::Outcome PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Setup() { - m_tableName = "perf-table-" + PerformanceTest::Utils::GenerateUniqueId(); - +Aws::Utils::Outcome PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Setup() { Aws::DynamoDB::Model::CreateTableRequest createTableRequest; createTableRequest.SetTableName(m_tableName); @@ -58,7 +58,7 @@ Aws::Utils::Outcome PerformanceTest::Services auto createTableOutcome = m_dynamodb->CreateTable(createTableRequest); if (!createTableOutcome.IsSuccess()) { - return PerformanceTest::SetupError("DynamoDB Setup() - CreateTable failed: " + createTableOutcome.GetError().GetMessage()); + return "DynamoDB Setup() - CreateTable failed: " + createTableOutcome.GetError().GetMessage(); } // Wait for table to become active @@ -70,34 +70,31 @@ Aws::Utils::Outcome PerformanceTest::Services while (count < MAX_QUERIES) { const Aws::DynamoDB::Model::DescribeTableOutcome& describeOutcome = m_dynamodb->DescribeTable(describeRequest); if (describeOutcome.IsSuccess()) { - Aws::DynamoDB::Model::TableStatus status = describeOutcome.GetResult().GetTable().GetTableStatus(); + Aws::DynamoDB::Model::TableStatus const status = describeOutcome.GetResult().GetTable().GetTableStatus(); if (Aws::DynamoDB::Model::TableStatus::ACTIVE == status) { break; } std::this_thread::sleep_for(std::chrono::seconds(1)); } else { - return PerformanceTest::SetupError("DynamoDB Setup() - DescribeTable failed: " + describeOutcome.GetError().GetMessage()); + return "DynamoDB Setup() - DescribeTable failed: " + describeOutcome.GetError().GetMessage(); } count++; } if (count >= MAX_QUERIES) { - return PerformanceTest::SetupError("DynamoDB Setup() - Table did not become active within timeout"); + return "DynamoDB Setup() - Table did not become active within timeout"; } return true; } void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Run() { - assert(m_dynamodb && "DynamoDB client not initialized - Setup() must succeed before Run()"); - assert(!m_tableName.empty() && "DynamoDB table name empty - Setup() must succeed before Run()"); - - const auto payload = PerformanceTest::Utils::RandomString(m_config.sizeBytes); + const auto payload = PerformanceTest::Utils::RandomString(TestConfig::GetPayloadSizeInBytes(m_testConfig.payloadSize)); // Run PutItem multiple times for (int i = 0; i < m_iterations; i++) { Aws::DynamoDB::Model::PutItemRequest putItemRequest; putItemRequest.SetTableName(m_tableName); - putItemRequest.SetAdditionalCustomHeaderValue("test-dimension-size", m_config.sizeLabel); + putItemRequest.SetAdditionalCustomHeaderValue("test-dimension-size", TestConfig::GetPayloadSizeLabel(m_testConfig.payloadSize)); putItemRequest.AddItem("data", Aws::DynamoDB::Model::AttributeValue().SetS(payload)); auto putItemOutcome = m_dynamodb->PutItem(putItemRequest); @@ -110,7 +107,7 @@ void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Run() { for (int i = 0; i < m_iterations; i++) { Aws::DynamoDB::Model::GetItemRequest getItemRequest; getItemRequest.SetTableName(m_tableName); - getItemRequest.SetAdditionalCustomHeaderValue("test-dimension-size", m_config.sizeLabel); + getItemRequest.SetAdditionalCustomHeaderValue("test-dimension-size", TestConfig::GetPayloadSizeLabel(m_testConfig.payloadSize)); getItemRequest.AddKey("data", Aws::DynamoDB::Model::AttributeValue().SetS(payload)); auto getItemOutcome = m_dynamodb->GetItem(getItemRequest); @@ -121,10 +118,6 @@ void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Run() { } void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::TearDown() { - if (!m_dynamodb || m_tableName.empty()) { - return; - } - Aws::DynamoDB::Model::DeleteTableRequest deleteTableRequest; deleteTableRequest.SetTableName(m_tableName); auto deleteTableOutcome = m_dynamodb->DeleteTable(deleteTableRequest); diff --git a/tests/performance-tests/src/services/dynamodb/DynamoDBTestConfig.cpp b/tests/performance-tests/src/services/dynamodb/DynamoDBTestConfig.cpp index b7ef24bdd12..c9718f8384a 100644 --- a/tests/performance-tests/src/services/dynamodb/DynamoDBTestConfig.cpp +++ b/tests/performance-tests/src/services/dynamodb/DynamoDBTestConfig.cpp @@ -3,10 +3,11 @@ * SPDX-License-Identifier: Apache-2.0. */ -#include +#include #include #include +#include namespace PerformanceTest { namespace Services { @@ -15,12 +16,33 @@ namespace TestConfig { const std::array TestOperations = {"PutItem", "GetItem"}; -const std::array TestMatrix = {{{.sizeLabel = "8KB", .sizeBytes = 8 * 1024}, - {.sizeLabel = "64KB", .sizeBytes = 64 * 1024}, - {.sizeLabel = "392KB", .sizeBytes = 392 * 1024}}}; +const std::array TestMatrix = { + {{.payloadSize = PayloadSize::K8}, {.payloadSize = PayloadSize::K64}, {.payloadSize = PayloadSize::K392}}}; const char* OutputFilename = "dynamodb-performance-test-results.json"; +size_t GetPayloadSizeInBytes(PayloadSize size) { + switch (size) { + case PayloadSize::K8: + return 8 * 1024; + case PayloadSize::K64: + return 64 * 1024; + case PayloadSize::K392: + return 392 * 1024; + } +} + +Aws::String GetPayloadSizeLabel(PayloadSize size) { + switch (size) { + case PayloadSize::K8: + return "8KB"; + case PayloadSize::K64: + return "64KB"; + case PayloadSize::K392: + return "392KB"; + } +} + } // namespace TestConfig } // namespace DynamoDB } // namespace Services diff --git a/tests/performance-tests/src/services/dynamodb/main.cpp b/tests/performance-tests/src/services/dynamodb/main.cpp index 78cc4d22b1e..82d5aaf0512 100644 --- a/tests/performance-tests/src/services/dynamodb/main.cpp +++ b/tests/performance-tests/src/services/dynamodb/main.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -46,13 +47,15 @@ int main(int argc, char** argv) { Aws::InitAPI(sdkOptions); { - for (const auto& config : PerformanceTest::Services::DynamoDB::TestConfig::TestMatrix) { - PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest performanceTest(region, config, iterations); - auto setupResult = performanceTest.Setup(); - if (setupResult.IsSuccess()) { + for (const auto& testConfig : PerformanceTest::Services::DynamoDB::TestConfig::TestMatrix) { + Aws::Client::ClientConfiguration clientConfig; + clientConfig.region = region; + PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest performanceTest(clientConfig, testConfig, iterations); + auto setupOutcome = performanceTest.Setup(); + if (setupOutcome.IsSuccess()) { performanceTest.Run(); } else { - AWS_LOG_ERROR("PerformanceTest", setupResult.GetError().message.c_str()); + AWS_LOG_ERROR("PerformanceTest", setupOutcome.GetError().c_str()); } performanceTest.TearDown(); } diff --git a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp index 71fa2a45637..cb0547d73c9 100644 --- a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp +++ b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp @@ -22,28 +22,30 @@ #include #include #include -#include #include #include +#include #include -#include -PerformanceTest::Services::S3::S3PerformanceTest::S3PerformanceTest(const Aws::String& region, const TestCase& config, - const Aws::String& availabilityZoneId, int iterations) - : m_config(config), m_region(region), m_availabilityZoneId(availabilityZoneId), m_iterations(iterations) { - Aws::Client::ClientConfiguration cfg; - cfg.region = m_region; - m_s3 = Aws::MakeUnique("S3PerformanceTest", cfg); +PerformanceTest::Services::S3::S3PerformanceTest::S3PerformanceTest(const Aws::Client::ClientConfiguration& clientConfig, + const TestConfig::TestCase& testConfig, int iterations, + const Aws::String& availabilityZoneId) + : m_s3(Aws::MakeUnique("S3PerformanceTest", clientConfig)), + m_testConfig(testConfig), + m_iterations(iterations), + m_bucketName(testConfig.bucketType == TestConfig::BucketType::Express + ? "perf-express-" + PerformanceTest::Utils::GenerateUniqueId() + "--" + availabilityZoneId + "--x-s3" + : "perf-standard-" + PerformanceTest::Utils::GenerateUniqueId()), + m_availabilityZoneId(availabilityZoneId) { + assert(m_s3 && "S3 client not initialized"); } -Aws::Utils::Outcome PerformanceTest::Services::S3::S3PerformanceTest::Setup() { +Aws::Utils::Outcome PerformanceTest::Services::S3::S3PerformanceTest::Setup() { Aws::S3::Model::CreateBucketRequest cbr; - Aws::String const bucketId = PerformanceTest::Utils::GenerateUniqueId(); + cbr.SetBucket(m_bucketName); - if (strcmp(m_config.bucketTypeLabel, "s3-express") == 0) { - m_bucketName = "perf-express-" + bucketId + "--" + m_availabilityZoneId + "--x-s3"; - cbr.SetBucket(m_bucketName); + if (m_testConfig.bucketType == TestConfig::BucketType::Express) { Aws::S3::Model::CreateBucketConfiguration bucketConfig; bucketConfig.SetLocation( Aws::S3::Model::LocationInfo().WithType(Aws::S3::Model::LocationType::AvailabilityZone).WithName(m_availabilityZoneId)); @@ -53,23 +55,17 @@ Aws::Utils::Outcome PerformanceTest::Services .WithDataRedundancy(Aws::S3::Model::DataRedundancy::SingleAvailabilityZone)); cbr.SetCreateBucketConfiguration(bucketConfig); - } else { - m_bucketName = "perf-standard-" + bucketId; - cbr.SetBucket(m_bucketName); } auto createOutcome = m_s3->CreateBucket(cbr); if (!createOutcome.IsSuccess()) { - return PerformanceTest::SetupError("S3 Setup() - CreateBucket failed: " + createOutcome.GetError().GetMessage()); + return "S3 Setup() - CreateBucket failed: " + createOutcome.GetError().GetMessage(); } return true; } void PerformanceTest::Services::S3::S3PerformanceTest::Run() { - assert(m_s3 && "S3 client not initialized - Setup() must succeed before Run()"); - assert(!m_bucketName.empty() && "S3 bucket name empty - Setup() must succeed before Run()"); - - const auto randomPayload = PerformanceTest::Utils::RandomString(m_config.sizeBytes); + const auto randomPayload = PerformanceTest::Utils::RandomString(TestConfig::GetPayloadSizeInBytes(m_testConfig.payloadSize)); // Run PutObject multiple times for (int i = 0; i < m_iterations; i++) { @@ -77,8 +73,8 @@ void PerformanceTest::Services::S3::S3PerformanceTest::Run() { Aws::S3::Model::PutObjectRequest por; por.WithBucket(m_bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i)).SetBody(stream); - por.SetAdditionalCustomHeaderValue("test-dimension-size", m_config.sizeLabel); - por.SetAdditionalCustomHeaderValue("test-dimension-bucket-type", m_config.bucketTypeLabel); + por.SetAdditionalCustomHeaderValue("test-dimension-size", TestConfig::GetPayloadSizeLabel(m_testConfig.payloadSize)); + por.SetAdditionalCustomHeaderValue("test-dimension-bucket-type", TestConfig::GetBucketTypeLabel(m_testConfig.bucketType)); auto putOutcome = m_s3->PutObject(por); if (!putOutcome.IsSuccess()) { AWS_LOG_ERROR("PerformanceTest", ("S3 Run() - PutObject failed: " + putOutcome.GetError().GetMessage()).c_str()); @@ -89,8 +85,8 @@ void PerformanceTest::Services::S3::S3PerformanceTest::Run() { for (int i = 0; i < m_iterations; i++) { Aws::S3::Model::GetObjectRequest gor; gor.WithBucket(m_bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i)); - gor.SetAdditionalCustomHeaderValue("test-dimension-size", m_config.sizeLabel); - gor.SetAdditionalCustomHeaderValue("test-dimension-bucket-type", m_config.bucketTypeLabel); + gor.SetAdditionalCustomHeaderValue("test-dimension-size", TestConfig::GetPayloadSizeLabel(m_testConfig.payloadSize)); + gor.SetAdditionalCustomHeaderValue("test-dimension-bucket-type", TestConfig::GetBucketTypeLabel(m_testConfig.bucketType)); auto getOutcome = m_s3->GetObject(gor); if (!getOutcome.IsSuccess()) { AWS_LOG_ERROR("PerformanceTest", ("S3 Run() - GetObject failed: " + getOutcome.GetError().GetMessage()).c_str()); @@ -99,10 +95,6 @@ void PerformanceTest::Services::S3::S3PerformanceTest::Run() { } void PerformanceTest::Services::S3::S3PerformanceTest::TearDown() { - if (!m_s3 || m_bucketName.empty()) { - return; - } - for (int i = 0; i < m_iterations; i++) { auto deleteObjectOutcome = m_s3->DeleteObject( Aws::S3::Model::DeleteObjectRequest().WithBucket(m_bucketName).WithKey("test-object-" + Aws::Utils::StringUtils::to_string(i))); diff --git a/tests/performance-tests/src/services/s3/S3TestConfig.cpp b/tests/performance-tests/src/services/s3/S3TestConfig.cpp index 568162e42df..2b0b359de8f 100644 --- a/tests/performance-tests/src/services/s3/S3TestConfig.cpp +++ b/tests/performance-tests/src/services/s3/S3TestConfig.cpp @@ -3,10 +3,11 @@ * SPDX-License-Identifier: Apache-2.0. */ -#include +#include #include #include +#include namespace PerformanceTest { namespace Services { @@ -15,15 +16,46 @@ namespace TestConfig { const std::array TestOperations = {"PutObject", "GetObject"}; -const std::array TestMatrix = {{{.sizeLabel = "8KB", .sizeBytes = 8 * 1024, .bucketTypeLabel = "s3-standard"}, - {.sizeLabel = "64KB", .sizeBytes = 64 * 1024, .bucketTypeLabel = "s3-standard"}, - {.sizeLabel = "1MB", .sizeBytes = 1024 * 1024, .bucketTypeLabel = "s3-standard"}, - {.sizeLabel = "8KB", .sizeBytes = 8 * 1024, .bucketTypeLabel = "s3-express"}, - {.sizeLabel = "64KB", .sizeBytes = 64 * 1024, .bucketTypeLabel = "s3-express"}, - {.sizeLabel = "1MB", .sizeBytes = 1024 * 1024, .bucketTypeLabel = "s3-express"}}}; +const std::array TestMatrix = {{{.payloadSize = PayloadSize::K8, .bucketType = BucketType::Standard}, + {.payloadSize = PayloadSize::K64, .bucketType = BucketType::Standard}, + {.payloadSize = PayloadSize::M1, .bucketType = BucketType::Standard}, + {.payloadSize = PayloadSize::K8, .bucketType = BucketType::Express}, + {.payloadSize = PayloadSize::K64, .bucketType = BucketType::Express}, + {.payloadSize = PayloadSize::M1, .bucketType = BucketType::Express}}}; const char* OutputFilename = "s3-performance-test-results.json"; +size_t GetPayloadSizeInBytes(PayloadSize size) { + switch (size) { + case PayloadSize::K8: + return 8 * 1024; + case PayloadSize::K64: + return 64 * 1024; + case PayloadSize::M1: + return 1024 * 1024; + } +} + +Aws::String GetPayloadSizeLabel(PayloadSize size) { + switch (size) { + case PayloadSize::K8: + return "8KB"; + case PayloadSize::K64: + return "64KB"; + case PayloadSize::M1: + return "1MB"; + } +} + +Aws::String GetBucketTypeLabel(BucketType type) { + switch (type) { + case BucketType::Standard: + return "s3-standard"; + case BucketType::Express: + return "s3-express"; + } +} + } // namespace TestConfig } // namespace S3 } // namespace Services diff --git a/tests/performance-tests/src/services/s3/main.cpp b/tests/performance-tests/src/services/s3/main.cpp index 71a063940c5..2fe03398823 100644 --- a/tests/performance-tests/src/services/s3/main.cpp +++ b/tests/performance-tests/src/services/s3/main.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -47,13 +48,15 @@ int main(int argc, char** argv) { Aws::InitAPI(sdkOptions); { - for (const auto& config : PerformanceTest::Services::S3::TestConfig::TestMatrix) { - PerformanceTest::Services::S3::S3PerformanceTest performanceTest(region, config, availabilityZoneId, iterations); - auto setupResult = performanceTest.Setup(); - if (setupResult.IsSuccess()) { + for (const auto& testConfig : PerformanceTest::Services::S3::TestConfig::TestMatrix) { + Aws::Client::ClientConfiguration clientConfig; + clientConfig.region = region; + PerformanceTest::Services::S3::S3PerformanceTest performanceTest(clientConfig, testConfig, iterations, availabilityZoneId); + auto setupOutcome = performanceTest.Setup(); + if (setupOutcome.IsSuccess()) { performanceTest.Run(); } else { - AWS_LOG_ERROR("PerformanceTest", setupResult.GetError().message.c_str()); + AWS_LOG_ERROR("PerformanceTest", setupOutcome.GetError().c_str()); } performanceTest.TearDown(); } From b6339fbdc1f4612b2259ad5d90b0340e0b0374fb Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Wed, 16 Jul 2025 09:47:04 -0400 Subject: [PATCH 66/77] add autoscope to Environment declartion of Jinja --- tools/perf-gen/performance_test_generator.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/perf-gen/performance_test_generator.py b/tools/perf-gen/performance_test_generator.py index 74b910f1f15..eae5e6d2de9 100644 --- a/tools/perf-gen/performance_test_generator.py +++ b/tools/perf-gen/performance_test_generator.py @@ -2,7 +2,7 @@ import os import json -from jinja2 import Environment, FileSystemLoader +from jinja2 import Environment, FileSystemLoader, select_autoescape import argparse def generate_performance_test(config_path, template_dir, output_dir): @@ -15,7 +15,8 @@ def generate_performance_test(config_path, template_dir, output_dir): env = Environment( loader=FileSystemLoader(template_dir), trim_blocks=True, - lstrip_blocks=True + lstrip_blocks=True, + autoescape=select_autoescape(['html', 'xml']) ) service_src_dir = os.path.join(output_dir, f"performance-tests/src/services/{service_lower}") From 94880984c46d75d797367ada75ec376714de333b Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Wed, 16 Jul 2025 13:28:45 -0400 Subject: [PATCH 67/77] update performance test setup Outcome to use NoResult --- .../include/performance-tests/PerformanceTestBase.h | 3 ++- .../services/dynamodb/DynamoDBPerformanceTest.h | 3 ++- .../performance-tests/services/s3/S3PerformanceTest.h | 3 ++- .../src/services/dynamodb/DynamoDBPerformanceTest.cpp | 6 ++++-- .../performance-tests/src/services/s3/S3PerformanceTest.cpp | 6 ++++-- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/tests/performance-tests/include/performance-tests/PerformanceTestBase.h b/tests/performance-tests/include/performance-tests/PerformanceTestBase.h index 4f0c05fc439..0fdfe303062 100644 --- a/tests/performance-tests/include/performance-tests/PerformanceTestBase.h +++ b/tests/performance-tests/include/performance-tests/PerformanceTestBase.h @@ -5,6 +5,7 @@ #pragma once +#include #include #include @@ -21,7 +22,7 @@ class PerformanceTestBase { * Initialize resources for the test. * @return Outcome indicating success or failure with error details */ - virtual Aws::Utils::Outcome Setup() = 0; + virtual Aws::Utils::Outcome Setup() = 0; /** * Run the performance test operations. diff --git a/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h index 03cf247a82f..660bfc567f2 100644 --- a/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h +++ b/tests/performance-tests/include/performance-tests/services/dynamodb/DynamoDBPerformanceTest.h @@ -5,6 +5,7 @@ #pragma once +#include #include #include #include @@ -26,7 +27,7 @@ class DynamoDBPerformanceTest : public PerformanceTestBase { DynamoDBPerformanceTest(const Aws::Client::ClientConfiguration& clientConfig, const TestConfig::TestCase& testConfig, int iterations = 10); - Aws::Utils::Outcome Setup() override; + Aws::Utils::Outcome Setup() override; void Run() override; void TearDown() override; diff --git a/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h b/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h index 9583f9552fb..002d0c1b451 100644 --- a/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h +++ b/tests/performance-tests/include/performance-tests/services/s3/S3PerformanceTest.h @@ -5,6 +5,7 @@ #pragma once +#include #include #include #include @@ -26,7 +27,7 @@ class S3PerformanceTest : public PerformanceTestBase { S3PerformanceTest(const Aws::Client::ClientConfiguration& clientConfig, const TestConfig::TestCase& testConfig, int iterations = 10, const Aws::String& availabilityZoneId = ""); - Aws::Utils::Outcome Setup() override; + Aws::Utils::Outcome Setup() override; void Run() override; void TearDown() override; diff --git a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp index 2f9dba5c039..bc678640c88 100644 --- a/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp +++ b/tests/performance-tests/src/services/dynamodb/DynamoDBPerformanceTest.cpp @@ -3,6 +3,8 @@ * SPDX-License-Identifier: Apache-2.0. */ +#include +#include #include #include #include @@ -40,7 +42,7 @@ PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::DynamoDBPerformanc assert(m_dynamodb && "DynamoDB client not initialized"); } -Aws::Utils::Outcome PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Setup() { +Aws::Utils::Outcome PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Setup() { Aws::DynamoDB::Model::CreateTableRequest createTableRequest; createTableRequest.SetTableName(m_tableName); @@ -84,7 +86,7 @@ Aws::Utils::Outcome PerformanceTest::Services::DynamoDB::Dyna if (count >= MAX_QUERIES) { return "DynamoDB Setup() - Table did not become active within timeout"; } - return true; + return Aws::NoResult(); } void PerformanceTest::Services::DynamoDB::DynamoDBPerformanceTest::Run() { diff --git a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp index cb0547d73c9..8e58191f587 100644 --- a/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp +++ b/tests/performance-tests/src/services/s3/S3PerformanceTest.cpp @@ -3,6 +3,8 @@ * SPDX-License-Identifier: Apache-2.0. */ +#include +#include #include #include #include @@ -41,7 +43,7 @@ PerformanceTest::Services::S3::S3PerformanceTest::S3PerformanceTest(const Aws::C assert(m_s3 && "S3 client not initialized"); } -Aws::Utils::Outcome PerformanceTest::Services::S3::S3PerformanceTest::Setup() { +Aws::Utils::Outcome PerformanceTest::Services::S3::S3PerformanceTest::Setup() { Aws::S3::Model::CreateBucketRequest cbr; cbr.SetBucket(m_bucketName); @@ -61,7 +63,7 @@ Aws::Utils::Outcome PerformanceTest::Services::S3::S3Performa if (!createOutcome.IsSuccess()) { return "S3 Setup() - CreateBucket failed: " + createOutcome.GetError().GetMessage(); } - return true; + return Aws::NoResult(); } void PerformanceTest::Services::S3::S3PerformanceTest::Run() { From 8ea5f00c5d2b0b877b0908a950ce483e5ce65a9c Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Wed, 16 Jul 2025 15:05:30 -0400 Subject: [PATCH 68/77] update cmake settings and docs --- CMakeLists.txt | 7 +++---- docs/CMake_Parameters.md | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e961c50ff6e..59c9cb14e4b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,7 @@ if (LEGACY_BUILD) option(ENABLE_ZLIB_REQUEST_COMPRESSION "For services that support it, request content will be compressed. On by default if dependency available" ON) option(DISABLE_INTERNAL_IMDSV1_CALLS "Disables IMDSv1 internal client calls" OFF) option(BUILD_BENCHMARKS "Enables building the benchmark executable" OFF) + option(BUILD_PERFORMANCE_TESTS "Enables building the performance test executables" OFF) option(BUILD_OPTEL "Enables building the open telemetry implementation of tracing" OFF) option(AWS_SDK_WARNINGS_ARE_ERRORS "Compiler warning is treated as an error. Try turning this off when observing errors on a new or uncommon compiler" ON) option(BUILD_OPTEL_OTLP_BENCHMARKS "Enables building the benchmark tests with open telemetry OTLP clients" OFF) @@ -341,13 +342,11 @@ if (LEGACY_BUILD) add_sdks() include(tests) - #Performance tests (under tests/performance-tests) - option(BUILD_PERFORMANCE_TESTS "Build AWS C++ performance tests" OFF) - if(BUILD_PERFORMANCE_TESTS) + # Performance tests for services + if (BUILD_PERFORMANCE_TESTS) add_subdirectory(tests/performance-tests) endif() - # for user friendly cmake usage include(setup_cmake_find_module) diff --git a/docs/CMake_Parameters.md b/docs/CMake_Parameters.md index 274911e910e..e2328b73838 100644 --- a/docs/CMake_Parameters.md +++ b/docs/CMake_Parameters.md @@ -129,7 +129,7 @@ You can also tell gcc or clang to pass these linker flags by specifying `-Wl,--g (Defaults to OFF) Enables building the benchmark executable ### BUILD_PERFORMANCE_TESTS -(Defaults to OFF) Enables building performance test executables for S3 and DynamoDB. These tests measure operation latencies and output results to JSON files. Requires S3 and DynamoDB clients to be built. +(Defaults to OFF) Enables building the performance test executables for S3 and DynamoDB. These tests measure operation latencies and output results to JSON files. Requires S3 and DynamoDB clients to be built. ### BUILD_OPTEL (Defaults to OFF) Enables building the open telemetry implementation of tracing From 3fea980bd4aeae2e61e1043ca432fb8745bed857 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Wed, 16 Jul 2025 15:30:59 -0400 Subject: [PATCH 69/77] update run-al2-s3-performance-tests.sh to include az-id --- tools/scripts/build-tests/run-al2-s3-performance-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index b77e447f3a1..833eae122d1 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -46,5 +46,5 @@ export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" cd "${PREFIX_DIR}/al2-build" if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi -./tests/performance-tests/s3-performance-test --region "$REGION" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" +./tests/performance-tests/s3-performance-test --region "$REGION" --az-id "$AZ_ID" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" cat s3-performance-test-results.json \ No newline at end of file From b7187f492eb6725707bc0f26e871cf575f85c1ab Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Wed, 30 Jul 2025 13:07:03 -0400 Subject: [PATCH 70/77] pull memory leak fix from main --- .../reporting/JsonReportingMetrics.h | 16 +++++++++++----- .../src/reporting/JsonReportingMetrics.cpp | 11 +++++++---- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h b/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h index 9320e3caca6..071c8ee42e5 100644 --- a/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h +++ b/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h @@ -37,6 +37,11 @@ struct PerformanceMetricRecord { Aws::Map dimensions; }; +/** + * Context will be shared between monitor invocations. + */ +struct RequestContext; + /** * An implementation of the MonitoringInterface that collects performance metrics * and reports them in a JSON format. @@ -58,17 +63,17 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { ~JsonReportingMetrics() override; /** - * Called when an AWS request is started. Returns context for tracking. + * Called when an AWS request is started. Creates and returns context for tracking. * @param serviceName Name of the AWS service * @param requestName Name of the operation * @param request HTTP request object - * @return Context pointer (always returns nullptr) + * @return Context pointer to newly created RequestContext */ void* OnRequestStarted(const Aws::String& serviceName, const Aws::String& requestName, const std::shared_ptr& request) const override; /** - * Called when an AWS request succeeds. Records performance metrics. + * Called when an AWS request succeeds. Stores latency metrics in context. * @param serviceName Name of the AWS service * @param requestName Name of the operation * @param request HTTP request object @@ -81,7 +86,7 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { const Aws::Monitoring::CoreMetricsCollection& metrics, void* context) const override; /** - * Called when an AWS request fails. Records performance metrics. + * Called when an AWS request fails. Stores latency metrics in context. * @param serviceName Name of the AWS service * @param requestName Name of the operation * @param request HTTP request object @@ -104,7 +109,7 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { const std::shared_ptr& request, void* context) const override; /** - * Called when an AWS request finishes. No action taken. + * Called when an AWS request finishes. Processes stored metrics and cleans up context. * @param serviceName Name of the AWS service * @param requestName Name of the operation * @param request HTTP request object @@ -150,6 +155,7 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { void WriteJsonToFile(const Aws::Utils::Json::JsonValue& root) const; mutable Aws::Vector m_performanceRecords; + mutable Aws::UnorderedMap> m_requestContexts; Aws::Set m_monitoredOperations; Aws::String m_productId; Aws::String m_sdkVersion; diff --git a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp index 997d4d9ec68..213f0af3f95 100644 --- a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp +++ b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp @@ -27,7 +27,8 @@ using namespace PerformanceTest::Reporting; -struct RequestContext { +struct PerformanceTest::Reporting::RequestContext { + Aws::Utils::UUID requestId{Aws::Utils::UUID::RandomUUID()}; Aws::String serviceName; Aws::String requestName; std::shared_ptr request; @@ -107,8 +108,10 @@ void JsonReportingMetrics::AddPerformanceRecord(const Aws::String& serviceName, void* JsonReportingMetrics::OnRequestStarted(const Aws::String&, const Aws::String&, const std::shared_ptr&) const { - auto context = Aws::New("RequestContext"); - return context; + auto context = Aws::MakeUnique("RequestContext"); + auto requestID = context->requestId; + m_requestContexts.emplace(requestID, std::move(context)); + return m_requestContexts[requestID].get(); } void JsonReportingMetrics::OnRequestSucceeded(const Aws::String& serviceName, const Aws::String& requestName, @@ -136,7 +139,7 @@ void JsonReportingMetrics::OnFinish(const Aws::String&, const Aws::String&, cons AddPerformanceRecord(requestContext->serviceName, requestContext->requestName, requestContext->request, requestContext->durationMs); } - Aws::Delete(requestContext); + m_requestContexts.erase(requestContext->requestId); } void JsonReportingMetrics::DumpJson() const { From 6964f3280bb6496474abc42511791216d05d7be1 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Wed, 30 Jul 2025 14:02:40 -0400 Subject: [PATCH 71/77] add build mode as a new dimension for performance tests --- .../reporting/JsonReportingMetrics.h | 9 ++++++-- .../src/reporting/JsonReportingMetrics.cpp | 22 ++++++++++++++----- .../src/services/dynamodb/main.cpp | 6 +++-- .../src/services/s3/main.cpp | 7 ++++-- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h b/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h index 071c8ee42e5..4adb2fac74b 100644 --- a/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h +++ b/tests/performance-tests/include/performance-tests/reporting/JsonReportingMetrics.h @@ -55,10 +55,11 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { * @param sdkVersion SDK version string * @param commitId Git commit identifier * @param outputFilename Path to output file (e.g., "s3-perf-results.json") + * @param buildMode Build mode ("debug" or "release") */ JsonReportingMetrics(const Aws::Set& monitoredOperations = Aws::Set(), const Aws::String& productId = "unknown", const Aws::String& sdkVersion = "unknown", const Aws::String& commitId = "unknown", - const Aws::String& outputFilename = "performance-test-results.json"); + const Aws::String& outputFilename = "performance-test-results.json", const Aws::String& buildMode = "unknown"); ~JsonReportingMetrics() override; @@ -161,6 +162,7 @@ class JsonReportingMetrics : public Aws::Monitoring::MonitoringInterface { Aws::String m_sdkVersion; Aws::String m_commitId; Aws::String m_outputFilename; + Aws::String m_buildMode; }; /** @@ -176,10 +178,12 @@ class JsonReportingMetricsFactory : public Aws::Monitoring::MonitoringFactory { * @param sdkVersion SDK version string * @param commitId Git commit identifier * @param outputFilename Path to output file (e.g., "s3-perf-results.json") + * @param buildMode Build mode ("debug" or "release") */ JsonReportingMetricsFactory(const Aws::Set& monitoredOperations = Aws::Set(), const Aws::String& productId = "unknown", const Aws::String& sdkVersion = "unknown", - const Aws::String& commitId = "unknown", const Aws::String& outputFilename = "performance-test-results.json"); + const Aws::String& commitId = "unknown", const Aws::String& outputFilename = "performance-test-results.json", + const Aws::String& buildMode = "unknown"); ~JsonReportingMetricsFactory() override = default; @@ -195,6 +199,7 @@ class JsonReportingMetricsFactory : public Aws::Monitoring::MonitoringFactory { Aws::String m_sdkVersion; Aws::String m_commitId; Aws::String m_outputFilename; + Aws::String m_buildMode; }; } // namespace Reporting } // namespace PerformanceTest \ No newline at end of file diff --git a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp index 213f0af3f95..a163e30a444 100644 --- a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp +++ b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -37,27 +38,30 @@ struct PerformanceTest::Reporting::RequestContext { }; JsonReportingMetrics::JsonReportingMetrics(const Aws::Set& monitoredOperations, const Aws::String& productId, - const Aws::String& sdkVersion, const Aws::String& commitId, const Aws::String& outputFilename) + const Aws::String& sdkVersion, const Aws::String& commitId, const Aws::String& outputFilename, + const Aws::String& buildMode) : m_monitoredOperations(monitoredOperations), m_productId(productId), m_sdkVersion(sdkVersion), m_commitId(commitId), - m_outputFilename(outputFilename) {} + m_outputFilename(outputFilename), + m_buildMode(buildMode) {} JsonReportingMetrics::~JsonReportingMetrics() { DumpJson(); } JsonReportingMetricsFactory::JsonReportingMetricsFactory(const Aws::Set& monitoredOperations, const Aws::String& productId, const Aws::String& sdkVersion, const Aws::String& commitId, - const Aws::String& outputFilename) + const Aws::String& outputFilename, const Aws::String& buildMode) : m_monitoredOperations(monitoredOperations), m_productId(productId), m_sdkVersion(sdkVersion), m_commitId(commitId), - m_outputFilename(outputFilename) {} + m_outputFilename(outputFilename), + m_buildMode(buildMode) {} Aws::UniquePtr JsonReportingMetricsFactory::CreateMonitoringInstance() const { return Aws::MakeUnique("JsonReportingMetrics", m_monitoredOperations, m_productId, m_sdkVersion, m_commitId, - m_outputFilename); + m_outputFilename, m_buildMode); } void JsonReportingMetrics::StoreLatencyInContext(const Aws::String& serviceName, const Aws::String& requestName, @@ -184,8 +188,14 @@ void JsonReportingMetrics::DumpJson() const { jsonMetric.WithInt64("date", record.date.Seconds()); if (!record.dimensions.empty()) { - Aws::Utils::Array dimensionsArray(record.dimensions.size()); + Aws::Utils::Array dimensionsArray(record.dimensions.size() + 1); size_t dimensionIndex = 0; + + Aws::Utils::Json::JsonValue buildModeDimension; + buildModeDimension.WithString("name", "build-mode"); + buildModeDimension.WithString("value", m_buildMode); + dimensionsArray[dimensionIndex++] = std::move(buildModeDimension); + for (const auto& dim : record.dimensions) { Aws::Utils::Json::JsonValue dimension; dimension.WithString("name", dim.first); diff --git a/tests/performance-tests/src/services/dynamodb/main.cpp b/tests/performance-tests/src/services/dynamodb/main.cpp index 82d5aaf0512..85a29602049 100644 --- a/tests/performance-tests/src/services/dynamodb/main.cpp +++ b/tests/performance-tests/src/services/dynamodb/main.cpp @@ -23,12 +23,14 @@ int main(int argc, char** argv) { cxxopts::Options options("dynamodb-perf-test", "DynamoDB Performance Test"); options.add_options()("r,region", "AWS region", cxxopts::value()->default_value("us-east-1"))( "i,iterations", "Number of iterations", cxxopts::value()->default_value("10"))( - "c,commit-id", "Commit ID", cxxopts::value()->default_value("unknown")); + "c,commit-id", "Commit ID", cxxopts::value()->default_value("unknown"))( + "b,build-mode", "Build mode (debug or release)", cxxopts::value()->default_value("unknown")); auto const result = options.parse(argc, argv); Aws::String const region = Aws::Utils::StringUtils::to_string(result["region"].as()); Aws::String const commitId = Aws::Utils::StringUtils::to_string(result["commit-id"].as()); + Aws::String const buildMode = Aws::Utils::StringUtils::to_string(result["build-mode"].as()); int const iterations = result["iterations"].as(); Aws::SDKOptions sdkOptions; @@ -41,7 +43,7 @@ int main(int argc, char** argv) { } return Aws::MakeUnique( "JsonReportingMetricsFactory", operations, "cpp1", versionStr, commitId, - PerformanceTest::Services::DynamoDB::TestConfig::OutputFilename); + PerformanceTest::Services::DynamoDB::TestConfig::OutputFilename, buildMode); }}; Aws::InitAPI(sdkOptions); diff --git a/tests/performance-tests/src/services/s3/main.cpp b/tests/performance-tests/src/services/s3/main.cpp index 2fe03398823..566208ac6e8 100644 --- a/tests/performance-tests/src/services/s3/main.cpp +++ b/tests/performance-tests/src/services/s3/main.cpp @@ -24,13 +24,15 @@ int main(int argc, char** argv) { options.add_options()("r,region", "AWS region", cxxopts::value()->default_value("us-east-1"))( "a,az-id", "Availability zone ID", cxxopts::value()->default_value("use1-az4"))( "i,iterations", "Number of iterations", cxxopts::value()->default_value("10"))( - "c,commit-id", "Commit ID", cxxopts::value()->default_value("unknown")); + "c,commit-id", "Commit ID", cxxopts::value()->default_value("unknown"))( + "b,build-mode", "Build mode (debug or release)", cxxopts::value()->default_value("unknown")); auto const result = options.parse(argc, argv); Aws::String const region = Aws::Utils::StringUtils::to_string(result["region"].as()); Aws::String const availabilityZoneId = Aws::Utils::StringUtils::to_string(result["az-id"].as()); Aws::String const commitId = Aws::Utils::StringUtils::to_string(result["commit-id"].as()); + Aws::String const buildMode = Aws::Utils::StringUtils::to_string(result["build-mode"].as()); int const iterations = result["iterations"].as(); Aws::SDKOptions sdkOptions; @@ -42,7 +44,8 @@ int main(int argc, char** argv) { operations.insert(operation); } return Aws::MakeUnique( - "JsonReportingMetricsFactory", operations, "cpp1", versionStr, commitId, PerformanceTest::Services::S3::TestConfig::OutputFilename); + "JsonReportingMetricsFactory", operations, "cpp1", versionStr, commitId, PerformanceTest::Services::S3::TestConfig::OutputFilename, + buildMode); }}; Aws::InitAPI(sdkOptions); From 087933f8fc9579e59ca0e22876c166a939361ec1 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Wed, 30 Jul 2025 14:16:15 -0400 Subject: [PATCH 72/77] modify scripts that run perf tests to include build mode --- .../run-al2-dynamodb-performance-tests.sh | 18 +++++++++++++----- .../run-al2-s3-performance-tests.sh | 18 +++++++++++++----- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index 4b11184903b..790cc537e46 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -12,13 +12,19 @@ set -e DEFAULT_REGION="us-east-1" DEFAULT_ITERATIONS=10 -if [ "$#" -lt 1 ]; then - echo "Error: Missing required argument. Usage: ${0} PREFIX_DIR [-r|--region REGION] [-i|--iterations NUM]" +if [ "$#" -lt 2 ]; then + echo "Error: Missing required arguments. Usage: ${0} PREFIX_DIR BUILD_MODE [-r|--region REGION] [-i|--iterations NUM]" exit 1 fi PREFIX_DIR="$1" -shift +BUILD_MODE="$2" +shift 2 + +if [ "$BUILD_MODE" != "debug" ] && [ "$BUILD_MODE" != "release" ]; then + echo "Error: BUILD_MODE must be 'debug' or 'release', got: $BUILD_MODE" + exit 1 +fi REGION="$DEFAULT_REGION" ITERATIONS="$DEFAULT_ITERATIONS" @@ -42,6 +48,8 @@ fi export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" cd "${PREFIX_DIR}/al2-build" -if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi -./tests/performance-tests/dynamodb-performance-test --region "$REGION" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" +if [ "$BUILD_MODE" = "debug" ] && [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then + export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" +fi +./tests/performance-tests/dynamodb-performance-test --region "$REGION" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" --build-mode "$BUILD_MODE" cat dynamodb-performance-test-results.json \ No newline at end of file diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index 833eae122d1..bd4a7c76e44 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -13,13 +13,19 @@ DEFAULT_REGION="us-east-1" DEFAULT_AZ_ID="use1-az4" DEFAULT_ITERATIONS=10 -if [ "$#" -lt 1 ]; then - echo "Error: Missing required argument. Usage: ${0} PREFIX_DIR [-r|--region REGION] [-a|--az-id AZ_ID] [-i|--iterations NUM]" +if [ "$#" -lt 2 ]; then + echo "Error: Missing required arguments. Usage: ${0} PREFIX_DIR BUILD_MODE [-r|--region REGION] [-a|--az-id AZ_ID] [-i|--iterations NUM]" exit 1 fi PREFIX_DIR="$1" -shift +BUILD_MODE="$2" +shift 2 + +if [ "$BUILD_MODE" != "debug" ] && [ "$BUILD_MODE" != "release" ]; then + echo "Error: BUILD_MODE must be 'debug' or 'release', got: $BUILD_MODE" + exit 1 +fi REGION="$DEFAULT_REGION" AZ_ID="$DEFAULT_AZ_ID" @@ -45,6 +51,8 @@ fi export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/" cd "${PREFIX_DIR}/al2-build" -if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi -./tests/performance-tests/s3-performance-test --region "$REGION" --az-id "$AZ_ID" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" +if [ "$BUILD_MODE" = "debug" ] && [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then + export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" +fi +./tests/performance-tests/s3-performance-test --region "$REGION" --az-id "$AZ_ID" --iterations "$ITERATIONS" --commit-id "$COMMIT_ID" --build-mode "$BUILD_MODE" cat s3-performance-test-results.json \ No newline at end of file From c6898fe23fe54027dc80a7194e4542cfe91f166d Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Thu, 31 Jul 2025 11:53:56 -0400 Subject: [PATCH 73/77] update CI scripts --- .../run-al2-dynamodb-performance-tests.sh | 15 ++++++--------- .../build-tests/run-al2-s3-performance-tests.sh | 15 ++++++--------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh index 790cc537e46..642e33ff784 100644 --- a/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-dynamodb-performance-tests.sh @@ -11,28 +11,25 @@ set -e DEFAULT_REGION="us-east-1" DEFAULT_ITERATIONS=10 +DEFAULT_BUILD_MODE="unknown" -if [ "$#" -lt 2 ]; then - echo "Error: Missing required arguments. Usage: ${0} PREFIX_DIR BUILD_MODE [-r|--region REGION] [-i|--iterations NUM]" +if [ "$#" -lt 1 ]; then + echo "Error: Missing required argument. Usage: ${0} PREFIX_DIR [-r|--region REGION] [-i|--iterations NUM] [-b|--build-mode BUILD_MODE]" exit 1 fi PREFIX_DIR="$1" -BUILD_MODE="$2" -shift 2 - -if [ "$BUILD_MODE" != "debug" ] && [ "$BUILD_MODE" != "release" ]; then - echo "Error: BUILD_MODE must be 'debug' or 'release', got: $BUILD_MODE" - exit 1 -fi +shift REGION="$DEFAULT_REGION" ITERATIONS="$DEFAULT_ITERATIONS" +BUILD_MODE="$DEFAULT_BUILD_MODE" while [[ "$#" -gt 0 ]]; do case "$1" in -r|--region) REGION="$2"; shift 2 ;; -i|--iterations) ITERATIONS="$2"; shift 2 ;; + -b|--build-mode) BUILD_MODE="$2"; shift 2 ;; *) echo "Unknown parameter: $1"; exit 1 ;; esac done diff --git a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh index bd4a7c76e44..06674abfa1f 100644 --- a/tools/scripts/build-tests/run-al2-s3-performance-tests.sh +++ b/tools/scripts/build-tests/run-al2-s3-performance-tests.sh @@ -12,30 +12,27 @@ set -e DEFAULT_REGION="us-east-1" DEFAULT_AZ_ID="use1-az4" DEFAULT_ITERATIONS=10 +DEFAULT_BUILD_MODE="unknown" -if [ "$#" -lt 2 ]; then - echo "Error: Missing required arguments. Usage: ${0} PREFIX_DIR BUILD_MODE [-r|--region REGION] [-a|--az-id AZ_ID] [-i|--iterations NUM]" +if [ "$#" -lt 1 ]; then + echo "Error: Missing required argument. Usage: ${0} PREFIX_DIR [-r|--region REGION] [-a|--az-id AZ_ID] [-i|--iterations NUM] [-b|--build-mode BUILD_MODE]" exit 1 fi PREFIX_DIR="$1" -BUILD_MODE="$2" -shift 2 - -if [ "$BUILD_MODE" != "debug" ] && [ "$BUILD_MODE" != "release" ]; then - echo "Error: BUILD_MODE must be 'debug' or 'release', got: $BUILD_MODE" - exit 1 -fi +shift REGION="$DEFAULT_REGION" AZ_ID="$DEFAULT_AZ_ID" ITERATIONS="$DEFAULT_ITERATIONS" +BUILD_MODE="$DEFAULT_BUILD_MODE" while [[ "$#" -gt 0 ]]; do case "$1" in -r|--region) REGION="$2"; shift 2 ;; -a|--az-id) AZ_ID="$2"; shift 2 ;; -i|--iterations) ITERATIONS="$2"; shift 2 ;; + -b|--build-mode) BUILD_MODE="$2"; shift 2 ;; *) echo "Unknown parameter: $1"; exit 1 ;; esac done From 396d7f57d8d6a2727615716b6b82b2eaa9a2a625 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Thu, 31 Jul 2025 11:54:42 -0400 Subject: [PATCH 74/77] update perf test to handle unknown build mode param --- .../src/reporting/JsonReportingMetrics.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp index a163e30a444..a106c1bcc80 100644 --- a/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp +++ b/tests/performance-tests/src/reporting/JsonReportingMetrics.cpp @@ -188,13 +188,15 @@ void JsonReportingMetrics::DumpJson() const { jsonMetric.WithInt64("date", record.date.Seconds()); if (!record.dimensions.empty()) { - Aws::Utils::Array dimensionsArray(record.dimensions.size() + 1); + Aws::Utils::Array dimensionsArray(record.dimensions.size() + (m_buildMode == "unknown" ? 0 : 1)); size_t dimensionIndex = 0; - Aws::Utils::Json::JsonValue buildModeDimension; - buildModeDimension.WithString("name", "build-mode"); - buildModeDimension.WithString("value", m_buildMode); - dimensionsArray[dimensionIndex++] = std::move(buildModeDimension); + if (m_buildMode != "unknown") { + Aws::Utils::Json::JsonValue buildModeDimension; + buildModeDimension.WithString("name", "build-mode"); + buildModeDimension.WithString("value", m_buildMode); + dimensionsArray[dimensionIndex++] = std::move(buildModeDimension); + } for (const auto& dim : record.dimensions) { Aws::Utils::Json::JsonValue dimension; From 0dc9485e2905fb844c195b90a31ec9445df3cb4e Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Mon, 4 Aug 2025 10:44:50 -0400 Subject: [PATCH 75/77] add a script for build-al2 in release mode --- .../build-tests/build-al2-release-default.sh | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100755 tools/scripts/build-tests/build-al2-release-default.sh diff --git a/tools/scripts/build-tests/build-al2-release-default.sh b/tools/scripts/build-tests/build-al2-release-default.sh new file mode 100755 index 00000000000..84d2fad73ec --- /dev/null +++ b/tools/scripts/build-tests/build-al2-release-default.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0. + +# This script is an example of how to build the SDK on Release build-type with minimize on +# Directories created and files are prefixed with PREFIX_DIR argument +# A clone of aws-sdk-cpp is expected to be in ${PREFIX_DIR}/aws-sdk-cpp +# Platform: Amazon Linux 2 + +set -e + +if [ "$#" -ne 1 ]; then + echo "Usage: ${0} PREFIX_DIR" + exit 1 +fi +PREFIX_DIR="$1" + +mkdir "${PREFIX_DIR}/al2-build" +mkdir "${PREFIX_DIR}/al2-install" +cd "${PREFIX_DIR}/al2-build" +cmake -GNinja ../aws-sdk-cpp -DCMAKE_BUILD_TYPE=Release -DMINIMIZE_SIZE=ON -DCMAKE_INSTALL_PREFIX="${PREFIX_DIR}/al2-install" -DBUILD_PERFORMANCE_TESTS=ON +ninja-build -j $(grep -c ^processor /proc/cpuinfo) +ninja-build install From d326084027c22798c9f174f1ab60c01570b46272 Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Mon, 4 Aug 2025 15:22:08 -0400 Subject: [PATCH 76/77] remove release script and add args to debug default sh --- .../build-tests/build-al2-debug-default.sh | 14 +++++++---- .../build-tests/build-al2-release-default.sh | 23 ------------------- 2 files changed, 10 insertions(+), 27 deletions(-) delete mode 100755 tools/scripts/build-tests/build-al2-release-default.sh diff --git a/tools/scripts/build-tests/build-al2-debug-default.sh b/tools/scripts/build-tests/build-al2-debug-default.sh index f3b6408be94..4941298ae12 100755 --- a/tools/scripts/build-tests/build-al2-debug-default.sh +++ b/tools/scripts/build-tests/build-al2-debug-default.sh @@ -2,22 +2,28 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. -# This script is an example of how to build the SDK on Debug build-type with minimize on and address sanitizers +# This script is an example of how to build the SDK with minimize on (debugging information and address sanitizer enabled for Debug builds) # Directories created and files are prefixed with PREFIX_DIR argument # A clone of aws-sdk-cpp is expected to be in ${PREFIX_DIR}/aws-sdk-cpp # Platform: Amazon Linux 2 set -e -if [ "$#" -ne 1 ]; then - echo "Usage: ${0} PREFIX_DIR" +if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then + echo "Usage: ${0} PREFIX_DIR [BUILD_TYPE]" + echo "BUILD_TYPE defaults to Debug if not provided" exit 1 fi PREFIX_DIR="$1" +BUILD_TYPE="${2:-Debug}" mkdir "${PREFIX_DIR}/al2-build" mkdir "${PREFIX_DIR}/al2-install" cd "${PREFIX_DIR}/al2-build" -cmake -GNinja ../aws-sdk-cpp -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-ggdb -fsanitize=address" -DMINIMIZE_SIZE=ON -DCMAKE_INSTALL_PREFIX="${PREFIX_DIR}/al2-install" -DBUILD_PERFORMANCE_TESTS=ON +CMAKE_ARGS="-GNinja ../aws-sdk-cpp -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DMINIMIZE_SIZE=ON -DCMAKE_INSTALL_PREFIX=${PREFIX_DIR}/al2-install -DBUILD_PERFORMANCE_TESTS=ON" +if [ "$BUILD_TYPE" = "Debug" ]; then + CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_CXX_FLAGS='-ggdb -fsanitize=address'" +fi +cmake $CMAKE_ARGS ninja-build -j $(grep -c ^processor /proc/cpuinfo) ninja-build install diff --git a/tools/scripts/build-tests/build-al2-release-default.sh b/tools/scripts/build-tests/build-al2-release-default.sh deleted file mode 100755 index 84d2fad73ec..00000000000 --- a/tools/scripts/build-tests/build-al2-release-default.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0. - -# This script is an example of how to build the SDK on Release build-type with minimize on -# Directories created and files are prefixed with PREFIX_DIR argument -# A clone of aws-sdk-cpp is expected to be in ${PREFIX_DIR}/aws-sdk-cpp -# Platform: Amazon Linux 2 - -set -e - -if [ "$#" -ne 1 ]; then - echo "Usage: ${0} PREFIX_DIR" - exit 1 -fi -PREFIX_DIR="$1" - -mkdir "${PREFIX_DIR}/al2-build" -mkdir "${PREFIX_DIR}/al2-install" -cd "${PREFIX_DIR}/al2-build" -cmake -GNinja ../aws-sdk-cpp -DCMAKE_BUILD_TYPE=Release -DMINIMIZE_SIZE=ON -DCMAKE_INSTALL_PREFIX="${PREFIX_DIR}/al2-install" -DBUILD_PERFORMANCE_TESTS=ON -ninja-build -j $(grep -c ^processor /proc/cpuinfo) -ninja-build install From 15f88256b2a03840496a7ad28a9f9c79f264a4ed Mon Sep 17 00:00:00 2001 From: YUXUAN CHEN Date: Mon, 4 Aug 2025 16:27:28 -0400 Subject: [PATCH 77/77] fix al2 debug build script by using bash array --- tools/scripts/build-tests/build-al2-debug-default.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/scripts/build-tests/build-al2-debug-default.sh b/tools/scripts/build-tests/build-al2-debug-default.sh index 4941298ae12..39ae09d8295 100755 --- a/tools/scripts/build-tests/build-al2-debug-default.sh +++ b/tools/scripts/build-tests/build-al2-debug-default.sh @@ -20,10 +20,10 @@ BUILD_TYPE="${2:-Debug}" mkdir "${PREFIX_DIR}/al2-build" mkdir "${PREFIX_DIR}/al2-install" cd "${PREFIX_DIR}/al2-build" -CMAKE_ARGS="-GNinja ../aws-sdk-cpp -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DMINIMIZE_SIZE=ON -DCMAKE_INSTALL_PREFIX=${PREFIX_DIR}/al2-install -DBUILD_PERFORMANCE_TESTS=ON" +CMAKE_ARGS=(-GNinja ../aws-sdk-cpp -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DMINIMIZE_SIZE=ON -DCMAKE_INSTALL_PREFIX="${PREFIX_DIR}/al2-install" -DBUILD_PERFORMANCE_TESTS=ON) if [ "$BUILD_TYPE" = "Debug" ]; then - CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_CXX_FLAGS='-ggdb -fsanitize=address'" + CMAKE_ARGS+=(-DCMAKE_CXX_FLAGS="-ggdb -fsanitize=address") fi -cmake $CMAKE_ARGS +cmake "${CMAKE_ARGS[@]}" ninja-build -j $(grep -c ^processor /proc/cpuinfo) ninja-build install pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy