Add Storage Performance tests for DownloadTo API (#2987)
Adding 3 new tests for Storage Performance The next tests are expected to find out the overhead between each layer of the Azure SDK client while performing a download operation. The current performance test is measuring the client + azure core pipeline + http transport. The next tests removes authentication policy and then each layer up to the HTTP transport adapter directly. DownloadBlobSas Generates a SaS token to download a blob. This way the authentication policy "sharedKey" won't run in the pipeline. DownloadBlobWithPipelineOnly Use the SaS token as well but send the request without the BlobClient. Instead it uses the Azure Core Pipeline directly DownloadBlobWithTransportOnly Same as before, the SaS token is used to download the blob but consuming only the libcurl-transport adapter. This option skips the HttpPipeline. The only elements used from Azure Core are the HttpRequest and the Azure::Context Note porting tests from the .NET equivalent: https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/storage/Azure.Storage.Blobs/perf/Azure.Storage.Blobs.Perf/Scenarios/DownloadSasUriBlobClient.cs https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/storage/Azure.Storage.Blobs/perf/Azure.Storage.Blobs.Perf/Scenarios/DownloadSasUriHttpClient.cs https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/storage/Azure.Storage.Blobs/perf/Azure.Storage.Blobs.Perf/Scenarios/DownloadSasUriHttpPipeline.cs
This commit is contained in:
parent
3fdf66bb55
commit
f90ab8a9b5
@ -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
|
||||
|
||||
@ -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
|
||||
)
|
||||
|
||||
@ -25,13 +25,35 @@ namespace Azure { namespace Storage { namespace Blobs { namespace Test {
|
||||
*
|
||||
*/
|
||||
class BlobsTest : public Azure::Perf::PerfTest {
|
||||
private:
|
||||
std::shared_ptr<Azure::Storage::StorageSharedKeyCredential> m_keyCredential;
|
||||
|
||||
protected:
|
||||
std::string m_containerName;
|
||||
std::string m_blobName;
|
||||
std::string m_connectionString;
|
||||
std::unique_ptr<Azure::Storage::Blobs::BlobServiceClient> m_serviceClient;
|
||||
std::unique_ptr<Azure::Storage::Blobs::BlobContainerClient> m_containerClient;
|
||||
std::unique_ptr<Azure::Storage::Blobs::BlockBlobClient> 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>(
|
||||
Azure::Storage::Blobs::BlobServiceClient::CreateFromConnectionString(m_connectionString));
|
||||
m_containerClient = std::make_unique<Azure::Storage::Blobs::BlobContainerClient>(
|
||||
Azure::Storage::Blobs::BlobContainerClient::CreateFromConnectionString(
|
||||
m_connectionString, m_containerName));
|
||||
m_serviceClient->GetBlobContainerClient(m_containerName));
|
||||
m_containerClient->CreateIfNotExists();
|
||||
m_blobClient = std::make_unique<Azure::Storage::Blobs::BlockBlobClient>(
|
||||
m_containerClient->GetBlockBlobClient(m_blobName));
|
||||
|
||||
m_keyCredential = _internal::ParseConnectionString(m_connectionString).KeyCredential;
|
||||
}
|
||||
|
||||
void Cleanup() override { m_containerClient->DeleteIfExists(); }
|
||||
|
||||
@ -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 <azure/core/io/body_stream.hpp>
|
||||
#include <azure/perf.hpp>
|
||||
|
||||
#include "azure/storage/blobs/test/blob_base_test.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
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<std::vector<uint8_t>> m_downloadBuffer;
|
||||
std::unique_ptr<Azure::Storage::Blobs::BlockBlobClient> 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<long>("Size");
|
||||
|
||||
m_downloadBuffer = std::make_unique<std::vector<uint8_t>>(size);
|
||||
|
||||
auto rawData = std::make_unique<std::vector<uint8_t>>(size);
|
||||
auto content = Azure::Core::IO::MemoryBodyStream(*rawData);
|
||||
m_blobClient->Upload(content);
|
||||
|
||||
m_blobClientSas = std::make_unique<Azure::Storage::Blobs::BlockBlobClient>(
|
||||
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<Azure::Perf::TestOption> 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<Azure::Storage::Blobs::Test::DownloadBlobSas>(options);
|
||||
}};
|
||||
}
|
||||
};
|
||||
|
||||
}}}} // namespace Azure::Storage::Blobs::Test
|
||||
@ -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 <azure/core/http/curl_transport.hpp>
|
||||
#include <azure/core/io/body_stream.hpp>
|
||||
#include <azure/perf.hpp>
|
||||
|
||||
#include "azure/storage/blobs/test/blob_base_test.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
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<std::vector<uint8_t>> m_downloadBuffer;
|
||||
std::unique_ptr<Azure::Core::Http::_internal::HttpPipeline> m_pipeline;
|
||||
std::unique_ptr<Azure::Core::Http::Request> 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<long>("Size");
|
||||
bool bufferResponse = m_options.GetMandatoryOption<bool>("Buffer");
|
||||
|
||||
m_downloadBuffer = std::make_unique<std::vector<uint8_t>>(size);
|
||||
|
||||
auto rawData = std::make_unique<std::vector<uint8_t>>(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::Request>(
|
||||
Azure::Core::Http::HttpMethod::Get, Azure::Core::Url(requestUrl), bufferResponse);
|
||||
|
||||
Azure::Core::_internal::ClientOptions options;
|
||||
std::vector<std::unique_ptr<Azure::Core::Http::Policies::HttpPolicy>> perRetry;
|
||||
std::vector<std::unique_ptr<Azure::Core::Http::Policies::HttpPolicy>> perOperation;
|
||||
m_pipeline = std::make_unique<Azure::Core::Http::_internal::HttpPipeline>(
|
||||
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<Azure::Perf::TestOption> 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<Azure::Storage::Blobs::Test::DownloadBlobWithPipelineOnly>(
|
||||
options);
|
||||
}};
|
||||
}
|
||||
};
|
||||
|
||||
}}}} // namespace Azure::Storage::Blobs::Test
|
||||
@ -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 <azure/core/http/curl_transport.hpp>
|
||||
#include <azure/core/io/body_stream.hpp>
|
||||
#include <azure/perf.hpp>
|
||||
|
||||
#include "azure/storage/blobs/test/blob_base_test.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
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<std::vector<uint8_t>> m_downloadBuffer;
|
||||
std::unique_ptr<Azure::Core::Http::CurlTransport> m_curlTransport;
|
||||
bool m_bufferResponse = false;
|
||||
std::unique_ptr<Azure::Core::Http::Request> 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<long>("Size");
|
||||
m_bufferResponse = m_options.GetMandatoryOption<bool>("Buffer");
|
||||
|
||||
m_downloadBuffer = std::make_unique<std::vector<uint8_t>>(size);
|
||||
|
||||
auto rawData = std::make_unique<std::vector<uint8_t>>(size);
|
||||
auto content = Azure::Core::IO::MemoryBodyStream(*rawData);
|
||||
m_blobClient->Upload(content);
|
||||
|
||||
auto requestUrl = m_blobClient->GetUrl() + GetSasToken();
|
||||
|
||||
m_curlTransport = std::make_unique<Azure::Core::Http::CurlTransport>();
|
||||
m_request = std::make_unique<Azure::Core::Http::Request>(
|
||||
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<Azure::Perf::TestOption> 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<Azure::Storage::Blobs::Test::DownloadBlobWithTransportOnly>(
|
||||
options);
|
||||
}};
|
||||
}
|
||||
};
|
||||
|
||||
}}}} // namespace Azure::Storage::Blobs::Test
|
||||
@ -3,7 +3,14 @@
|
||||
|
||||
#include <azure/perf.hpp>
|
||||
|
||||
#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<Azure::Perf::TestMetadata> tests{
|
||||
Azure::Storage::Blobs::Test::DownloadBlob::GetTestMetadata(),
|
||||
Azure::Storage::Blobs::Test::UploadBlob::GetTestMetadata(),
|
||||
Azure::Storage::Blobs::Test::ListBlob::GetTestMetadata()};
|
||||
std::vector<Azure::Perf::TestMetadata> 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);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user