diff --git a/sdk/core/perf/CMakeLists.txt b/sdk/core/perf/CMakeLists.txt index 4ae4155be..db23c8f12 100644 --- a/sdk/core/perf/CMakeLists.txt +++ b/sdk/core/perf/CMakeLists.txt @@ -6,6 +6,11 @@ project(azure-perf LANGUAGES CXX) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED True) +set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake-modules") + +include(AzureTransportAdapters) set( AZURE_PERFORMANCE_HEADER diff --git a/sdk/storage/azure-storage-blobs/test/perf/CMakeLists.txt b/sdk/storage/azure-storage-blobs/test/perf/CMakeLists.txt index 3a61e2574..49fbb4672 100644 --- a/sdk/storage/azure-storage-blobs/test/perf/CMakeLists.txt +++ b/sdk/storage/azure-storage-blobs/test/perf/CMakeLists.txt @@ -7,10 +7,17 @@ project(azure-storage-blobs-perf LANGUAGES CXX) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED True) +if(BUILD_TRANSPORT_CURL) + set(DOWNLOAD_WITH_LIBCURL inc/azure/storage/blobs/test/download_blob_transport_only.hpp) +endif() + set( AZURE_STORAGE_BLOBS_PERF_TEST_HEADER inc/azure/storage/blobs/test/blob_base_test.hpp + inc/azure/storage/blobs/test/download_blob_from_sas.hpp + inc/azure/storage/blobs/test/download_blob_pipeline_only.hpp inc/azure/storage/blobs/test/download_blob_test.hpp + ${DOWNLOAD_WITH_LIBCURL} inc/azure/storage/blobs/test/list_blob_test.hpp inc/azure/storage/blobs/test/upload_blob_test.hpp ) diff --git a/sdk/storage/azure-storage-blobs/test/perf/inc/azure/storage/blobs/test/blob_base_test.hpp b/sdk/storage/azure-storage-blobs/test/perf/inc/azure/storage/blobs/test/blob_base_test.hpp index 7a506ff7e..93437b4d3 100644 --- a/sdk/storage/azure-storage-blobs/test/perf/inc/azure/storage/blobs/test/blob_base_test.hpp +++ b/sdk/storage/azure-storage-blobs/test/perf/inc/azure/storage/blobs/test/blob_base_test.hpp @@ -25,13 +25,35 @@ namespace Azure { namespace Storage { namespace Blobs { namespace Test { * */ class BlobsTest : public Azure::Perf::PerfTest { + private: + std::shared_ptr m_keyCredential; + protected: std::string m_containerName; std::string m_blobName; std::string m_connectionString; + std::unique_ptr m_serviceClient; std::unique_ptr m_containerClient; std::unique_ptr m_blobClient; + std::string GetSasToken() + { + // Generate SaS Token + auto sasStartsOn = std::chrono::system_clock::now() - std::chrono::minutes(5); + auto sasExpiresOn = std::chrono::system_clock::now() + std::chrono::minutes(60); + + Sas::BlobSasBuilder blobSasBuilder; + blobSasBuilder.Protocol = Sas::SasProtocol::HttpsAndHttp; + blobSasBuilder.StartsOn = sasStartsOn; + blobSasBuilder.ExpiresOn = sasExpiresOn; + blobSasBuilder.BlobContainerName = m_containerName; + blobSasBuilder.BlobName = m_blobName; + blobSasBuilder.Resource = Sas::BlobSasResource::Blob; + blobSasBuilder.SetPermissions(Sas::BlobSasPermissions::All); + + return blobSasBuilder.GenerateSasToken(*m_keyCredential); + } + public: /** * @brief Creat the container client @@ -48,12 +70,15 @@ namespace Azure { namespace Storage { namespace Blobs { namespace Test { m_blobName = "blob" + Azure::Core::Uuid::CreateUuid().ToString(); // Create client, container and blobClient + m_serviceClient = std::make_unique( + Azure::Storage::Blobs::BlobServiceClient::CreateFromConnectionString(m_connectionString)); m_containerClient = std::make_unique( - Azure::Storage::Blobs::BlobContainerClient::CreateFromConnectionString( - m_connectionString, m_containerName)); + m_serviceClient->GetBlobContainerClient(m_containerName)); m_containerClient->CreateIfNotExists(); m_blobClient = std::make_unique( m_containerClient->GetBlockBlobClient(m_blobName)); + + m_keyCredential = _internal::ParseConnectionString(m_connectionString).KeyCredential; } void Cleanup() override { m_containerClient->DeleteIfExists(); } diff --git a/sdk/storage/azure-storage-blobs/test/perf/inc/azure/storage/blobs/test/download_blob_from_sas.hpp b/sdk/storage/azure-storage-blobs/test/perf/inc/azure/storage/blobs/test/download_blob_from_sas.hpp new file mode 100644 index 000000000..b96a19bc5 --- /dev/null +++ b/sdk/storage/azure-storage-blobs/test/perf/inc/azure/storage/blobs/test/download_blob_from_sas.hpp @@ -0,0 +1,95 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// SPDX-License-Identifier: MIT + +/** + * @file + * @brief Test the performance of downloading a block blob using SaS token. + * + */ + +#pragma once + +#include +#include + +#include "azure/storage/blobs/test/blob_base_test.hpp" + +#include +#include +#include +#include + +namespace Azure { namespace Storage { namespace Blobs { namespace Test { + + /** + * @brief A test to measure downloading a blob using SaS token. + * + */ + class DownloadBlobSas : public Azure::Storage::Blobs::Test::BlobsTest { + private: + std::unique_ptr> m_downloadBuffer; + std::unique_ptr m_blobClientSas; + + public: + /** + * @brief Construct a new DownloadBlobSas test. + * + * @param options The test options. + */ + DownloadBlobSas(Azure::Perf::TestOptions options) : BlobsTest(options) {} + + /** + * @brief The size to upload on setup is defined by a mandatory parameter. + * + */ + void Setup() override + { + // Call base to create blob client + BlobsTest::Setup(); + + long size = m_options.GetMandatoryOption("Size"); + + m_downloadBuffer = std::make_unique>(size); + + auto rawData = std::make_unique>(size); + auto content = Azure::Core::IO::MemoryBodyStream(*rawData); + m_blobClient->Upload(content); + + m_blobClientSas = std::make_unique( + m_blobClient->GetUrl() + GetSasToken()); + } + + /** + * @brief Define the test + * + */ + void Run(Azure::Core::Context const&) override + { + m_blobClientSas->DownloadTo(m_downloadBuffer->data(), m_downloadBuffer->size()); + } + + /** + * @brief Define the test options for the test. + * + * @return The list of test options. + */ + std::vector GetTestOptions() override + { + // TODO: Merge with base options + return {{"Size", {"--size"}, "Size of payload (in bytes)", 1, true}}; + } + + /** + * @brief Get the static Test Metadata for the test. + * + * @return Azure::Perf::TestMetadata describing the test. + */ + static Azure::Perf::TestMetadata GetTestMetadata() + { + return {"DownloadBlobSas", "Download a blob.", [](Azure::Perf::TestOptions options) { + return std::make_unique(options); + }}; + } + }; + +}}}} // namespace Azure::Storage::Blobs::Test diff --git a/sdk/storage/azure-storage-blobs/test/perf/inc/azure/storage/blobs/test/download_blob_pipeline_only.hpp b/sdk/storage/azure-storage-blobs/test/perf/inc/azure/storage/blobs/test/download_blob_pipeline_only.hpp new file mode 100644 index 000000000..3ba318a21 --- /dev/null +++ b/sdk/storage/azure-storage-blobs/test/perf/inc/azure/storage/blobs/test/download_blob_pipeline_only.hpp @@ -0,0 +1,117 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// SPDX-License-Identifier: MIT + +/** + * @file + * @brief Test the performance of downloading a block blob using SaS token and with the http core + * pipeline directly. + * + */ + +#pragma once + +#include +#include +#include + +#include "azure/storage/blobs/test/blob_base_test.hpp" + +#include +#include +#include +#include + +namespace Azure { namespace Storage { namespace Blobs { namespace Test { + + /** + * @brief A test to measure downloading a blob using SaS token and with the http core pipeline + * directly. + * + */ + class DownloadBlobWithPipelineOnly : public Azure::Storage::Blobs::Test::BlobsTest { + private: + std::unique_ptr> m_downloadBuffer; + std::unique_ptr m_pipeline; + std::unique_ptr m_request; + + public: + /** + * @brief Construct a new DownloadBlobWithPipelineOnly test. + * + * @param options The test options. + */ + DownloadBlobWithPipelineOnly(Azure::Perf::TestOptions options) : BlobsTest(options) {} + + /** + * @brief The size to upload on setup is defined by a mandatory parameter. + * + */ + void Setup() override + { + // Call base to create blob client + BlobsTest::Setup(); + + long size = m_options.GetMandatoryOption("Size"); + bool bufferResponse = m_options.GetMandatoryOption("Buffer"); + + m_downloadBuffer = std::make_unique>(size); + + auto rawData = std::make_unique>(size); + auto content = Azure::Core::IO::MemoryBodyStream(*rawData); + m_blobClient->Upload(content); + + auto requestUrl = m_blobClient->GetUrl() + GetSasToken(); + + m_request = std::make_unique( + Azure::Core::Http::HttpMethod::Get, Azure::Core::Url(requestUrl), bufferResponse); + + Azure::Core::_internal::ClientOptions options; + std::vector> perRetry; + std::vector> perOperation; + m_pipeline = std::make_unique( + options, "perfTest", "x.x", std::move(perRetry), std::move(perOperation)); + } + + /** + * @brief Define the test + * + */ + void Run(Azure::Core::Context const& context) override + { + // Transport policy resolved the buffer option. If buffer is ON on the request, the response + // will contain the payload directly. When it is OFF, the response will contain the stream to + // the network. + auto response = m_pipeline->Send(*m_request, context); + } + + /** + * @brief Define the test options for the test. + * + * @return The list of test options. + */ + std::vector GetTestOptions() override + { + // TODO: Merge with base options + return { + {"Size", {"--size"}, "Size of payload (in bytes)", 1, true}, + {"Buffer", {"--buffer"}, "Whether to buffer the response", 1, true}}; + } + + /** + * @brief Get the static Test Metadata for the test. + * + * @return Azure::Perf::TestMetadata describing the test. + */ + static Azure::Perf::TestMetadata GetTestMetadata() + { + return { + "DownloadBlobWithPipelineOnly", + "Download a blob using the curl transport adapter directly. No SDK layer.", + [](Azure::Perf::TestOptions options) { + return std::make_unique( + options); + }}; + } + }; + +}}}} // namespace Azure::Storage::Blobs::Test diff --git a/sdk/storage/azure-storage-blobs/test/perf/inc/azure/storage/blobs/test/download_blob_transport_only.hpp b/sdk/storage/azure-storage-blobs/test/perf/inc/azure/storage/blobs/test/download_blob_transport_only.hpp new file mode 100644 index 000000000..e576b1d1c --- /dev/null +++ b/sdk/storage/azure-storage-blobs/test/perf/inc/azure/storage/blobs/test/download_blob_transport_only.hpp @@ -0,0 +1,116 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// SPDX-License-Identifier: MIT + +/** + * @file + * @brief Test the performance of downloading a block blob using SaS token and with transport + * adapter directly. + * + */ + +#pragma once + +#include +#include +#include + +#include "azure/storage/blobs/test/blob_base_test.hpp" + +#include +#include +#include +#include + +namespace Azure { namespace Storage { namespace Blobs { namespace Test { + + /** + * @brief A test to measure downloading a blob using SaS token and with transport adapter + * directly. + * + */ + class DownloadBlobWithTransportOnly : public Azure::Storage::Blobs::Test::BlobsTest { + private: + std::unique_ptr> m_downloadBuffer; + std::unique_ptr m_curlTransport; + bool m_bufferResponse = false; + std::unique_ptr m_request; + + public: + /** + * @brief Construct a new DownloadBlobWithTransportOnly test. + * + * @param options The test options. + */ + DownloadBlobWithTransportOnly(Azure::Perf::TestOptions options) : BlobsTest(options) {} + + /** + * @brief The size to upload on setup is defined by a mandatory parameter. + * + */ + void Setup() override + { + // Call base to create blob client + BlobsTest::Setup(); + + long size = m_options.GetMandatoryOption("Size"); + m_bufferResponse = m_options.GetMandatoryOption("Buffer"); + + m_downloadBuffer = std::make_unique>(size); + + auto rawData = std::make_unique>(size); + auto content = Azure::Core::IO::MemoryBodyStream(*rawData); + m_blobClient->Upload(content); + + auto requestUrl = m_blobClient->GetUrl() + GetSasToken(); + + m_curlTransport = std::make_unique(); + m_request = std::make_unique( + Azure::Core::Http::HttpMethod::Get, Azure::Core::Url(requestUrl), m_bufferResponse); + } + + /** + * @brief Define the test + * + */ + void Run(Azure::Core::Context const& context) override + { + auto response = m_curlTransport->Send(*m_request, context); + + if (m_bufferResponse) + { + // if test request the response stream to be read completely. + *m_downloadBuffer = response->ExtractBodyStream()->ReadToEnd(); + } + } + + /** + * @brief Define the test options for the test. + * + * @return The list of test options. + */ + std::vector GetTestOptions() override + { + // TODO: Merge with base options + return { + {"Size", {"--size"}, "Size of payload (in bytes)", 1, true}, + {"Buffer", {"--buffer"}, "Whether to buffer the response", 1, true}}; + } + + /** + * @brief Get the static Test Metadata for the test. + * + * @return Azure::Perf::TestMetadata describing the test. + */ + static Azure::Perf::TestMetadata GetTestMetadata() + { + return { + "DownloadBlobWithTransportOnly", + "Download a blob using the curl transport adapter directly. No SDK layer.", + [](Azure::Perf::TestOptions options) { + return std::make_unique( + options); + }}; + } + }; + +}}}} // namespace Azure::Storage::Blobs::Test diff --git a/sdk/storage/azure-storage-blobs/test/perf/src/azure_storage_blobs_perf_test.cpp b/sdk/storage/azure-storage-blobs/test/perf/src/azure_storage_blobs_perf_test.cpp index cdd8219d0..04fd4018e 100644 --- a/sdk/storage/azure-storage-blobs/test/perf/src/azure_storage_blobs_perf_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/perf/src/azure_storage_blobs_perf_test.cpp @@ -3,7 +3,14 @@ #include +#include "azure/storage/blobs/test/download_blob_from_sas.hpp" +#include "azure/storage/blobs/test/download_blob_pipeline_only.hpp" #include "azure/storage/blobs/test/download_blob_test.hpp" + +#if defined(BUILD_CURL_HTTP_TRANSPORT_ADAPTER) +#include "azure/storage/blobs/test/download_blob_transport_only.hpp" +#endif + #include "azure/storage/blobs/test/list_blob_test.hpp" #include "azure/storage/blobs/test/upload_blob_test.hpp" @@ -11,10 +18,17 @@ int main(int argc, char** argv) { // Create the test list - std::vector tests{ - Azure::Storage::Blobs::Test::DownloadBlob::GetTestMetadata(), - Azure::Storage::Blobs::Test::UploadBlob::GetTestMetadata(), - Azure::Storage::Blobs::Test::ListBlob::GetTestMetadata()}; + std::vector tests + { + Azure::Storage::Blobs::Test::DownloadBlob::GetTestMetadata(), + Azure::Storage::Blobs::Test::UploadBlob::GetTestMetadata(), + Azure::Storage::Blobs::Test::ListBlob::GetTestMetadata(), + Azure::Storage::Blobs::Test::DownloadBlobSas::GetTestMetadata(), +#if defined(BUILD_CURL_HTTP_TRANSPORT_ADAPTER) + Azure::Storage::Blobs::Test::DownloadBlobWithTransportOnly::GetTestMetadata(), +#endif + Azure::Storage::Blobs::Test::DownloadBlobWithPipelineOnly::GetTestMetadata() + }; Azure::Perf::Program::Run(Azure::Core::Context::ApplicationContext, tests, argc, argv);