Вопрос или проблема
Я интегрировал Azure SDK для CPP в свое приложение, и по сравнению с старым Azure SDK наблюдается значительное замедление. После обновления для загрузки параллелизма Azure-sdk-for-cpp загрузка работает лучше, но загрузка все еще ОЧЕНЬ МЕДЛЕННАЯ.
Это можно воспроизвести на простом примере, просто попытавшись загрузить файл размером 1 Гб из хранилища Azure на локальную файловую систему.
- Старый SDK ~1 минута
- Новый SDK ~5 минут
Старый SDK использовал CPP REST, который использовал concurrency::streams::istream m_stream; В новом SDK этого нет, кроме TransferOptions.Concurrency, который почти ничего не делает. Есть ли какая-то идея, как ускорить DownloadTo? Или параллелизм должен быть реализован поверх библиотеки?
// Авторские права (c) Microsoft Corporation.
// Лицензировано по лицензии MIT.
#include <azure/storage/blobs.hpp>
#include <cstdio>
#include <iostream>
#include <stdexcept>
std::string GetConnectionString()
{
const static std::string ConnectionString = "";
if (!ConnectionString.empty())
{
return ConnectionString;
}
const static std::string envConnectionString = std::getenv("AZURE_STORAGE_CONNECTION_STRING");
if (!envConnectionString.empty())
{
return envConnectionString;
}
throw std::runtime_error("Не удалось найти строку подключения.");
}
int main()
{
using namespace Azure::Storage::Blobs;
const std::string containerName = "sample-container";
const std::string blobName = "sample-blob";
const std::string blobContent = "Привет, Azure!";
auto containerClient
= BlobContainerClient::CreateFromConnectionString(GetConnectionString(), containerName);
containerClient.CreateIfNotExists();
BlockBlobClient blobClient = containerClient.GetBlockBlobClient(blobName);
std::vector<uint8_t> buffer(blobContent.begin(), blobContent.end());
blobClient.UploadFrom(buffer.data(), buffer.size());
Azure::Storage::Metadata blobMetadata = {{"key1", "value1"}, {"key2", "value2"}};
blobClient.SetMetadata(blobMetadata);
auto properties = blobClient.GetProperties().Value;
for (auto metadata : properties.Metadata)
{
std::cout << metadata.first << ":" << metadata.second << std::endl;
}
// Мы знаем, что размер блоба небольшой, поэтому здесь безопасно приводить тип.
buffer.resize(static_cast<size_t>(properties.BlobSize));
blobClient.DownloadTo(buffer.data(), buffer.size());
std::cout << std::string(buffer.begin(), buffer.end()) << std::endl;
return 0;
}
Ответ или решение
Замедление функции DownloadTo в Azure SDK для C++
При использовании Azure SDK для C++ в вашем приложении может возникнуть довольно ощутимое замедление по сравнению с предыдущей версией SDK. В вашем случае, вы отметили, что функции загрузки работают быстрее после обновления, однако время скачивания 1 Гб файла возросло практически в пять раз. Давайте подробно разберем возможные причины этого замедления и предложим пути оптимизации.
1. Сравнение старой и новой архитектуры SDK
Старая версия SDK использовала CPP REST
и предоставляла concurrency::streams::istream
, что позволяло реализовать асинхронные операции и увеличивало производительность через конкурентное использование потоков. Новая версия SDK достаточно значительно изменила свою архитектуру и вместо этого фокусируется на TransferOptions.Concurrency
, что, к сожалению, не дает желаемого результата в вашем случае.
2. Причины замедления
-
Стратегия передачи: Отсутствие параллелизма в скачивании данных может быть одной из основных причин замедления. В новой версии SDK функционал параллельных загрузок может быть ограничен. Возможно, стоит рассмотреть реализацию параллелизма на уровне приложения.
-
Фрагментация данных: В новой архитектуре SDK может отсутствовать поддержка разбивки больших файлов на более мелкие части для параллельной загрузки. Это может привести к замедлению в сравнении с более оптимизированной старой версией.
-
Настройка сети: Убедитесь, что ваша сеть не является узким местом. Возможно, стоит протестировать скачивание из другой сети или с помощью других инструментов для сравнения.
3. Рекомендации по оптимизации
Чтобы ускорить процесс загрузки в Azure SDK для C++, вы можете рассмотреть следующие подходы:
-
Имплементация пользовательского параллелизма: Если функциональность "Concurrency" не дает нужного эффекта, возможно, вам стоит реализовать параллельные запросы для скачивания файла. Вы можете разбить файл на несколько частей и загружать их параллельно, а затем объединить их на локальной машине.
-
Использование потоков: Рассмотрите возможность использования стандартных библиотек C++ для управления многопоточностью, чтобы организовать параллельные загрузки и соответственно увеличить производительность.
-
Настройка TransferOptions: Попробуйте поэкспериментировать с параметрами, которые предоставляет
TransferOptions
, и установите более высокие уровни параллелизма, если это поддерживается. -
Мониторинг и отладка: Используйте инструменты мониторинга для анализа времени выполнения загрузок, чтобы понять, на каком этапе возникают задержки. Это может помочь идентифицировать узкие места.
4. Пример кода с параллельной загрузкой
Вот базовая структура, как можно подойти к задаче реализации параллельного скачивания:
#include <future>
#include <vector>
#include <azure/storage/blobs.hpp>
void DownloadBlobPart(const Azure::Storage::Blobs::BlockBlobClient &blobClient, size_t offset, size_t size, std::vector<uint8_t> &buffer) {
// Реализуйте логику скачивания части файла с использованием blobClient
}
void ParallelDownload(const Azure::Storage::Blobs::BlockBlobClient &blobClient, size_t blobSize, size_t partSize) {
std::vector<std::future<void>> futures;
size_t numParts = (blobSize + partSize - 1) / partSize;
std::vector<uint8_t> buffer(blobSize);
for (size_t i = 0; i < numParts; ++i) {
size_t offset = i * partSize;
size_t size = std::min(partSize, blobSize - offset);
futures.emplace_back(std::async(std::launch::async, DownloadBlobPart, blobClient, offset, size, std::ref(buffer)));
}
for (auto &f : futures) {
f.get();
}
}
Заключение
Проблема медленного скачивания файла с использованием нового Azure SDK для C++ требует особого внимания, планирования и возможной доработки кода на уровне приложения. Используя предложенные методы, вы сможете улучшить производительность загрузки. Оставайтесь в курсе обновлений и возможностей от Microsoft, так как будущие обновления SDK могут включать улучшения, которые могут устранить текущие недостатки.
Если у вас есть дополнительные вопросы или проблемы, не стесняйтесь обращаться за помощью.