Пакетная загрузка огромных наборов изображений в хранилище BLOB-объектов Azure

У меня есть около 110 000 изображений различных форматов (jpg, png и gif) и размеров (2-40 КБ), хранящихся локально на моем жестком диске. Мне нужно загрузить их в хранилище BLOB-объектов Azure. При этом мне нужно установить некоторые метаданные и ContentType большого двоичного объекта, но в остальном это прямая массовая загрузка.

В настоящее время я использую следующее для обработки загрузки одного изображения за раз (параллельно для 5-10 одновременных задач).

static void UploadPhoto(Image pic, string filename, ImageFormat format)
{
    //convert image to bytes
    using(MemoryStream ms = new MemoryStream())
    {
        pic.Save(ms, format);
        ms.Position = 0;

        //create the blob, set metadata and properties
        var blob = container.GetBlobReference(filename);
        blob.Metadata["Filename"] = filename;
        blob.Properties.ContentType = MimeHandler.GetContentType(Path.GetExtension(filename));

        //upload!
        blob.UploadFromStream(ms);
        blob.SetMetadata();
        blob.SetProperties();
    }
}

Мне было интересно, есть ли другой метод, который я мог бы использовать для обработки загрузки, чтобы сделать ее как можно быстрее. Этот конкретный проект включает в себя импорт большого количества данных из одной системы в другую и по причинам клиентов это должно произойти как можно быстрее.


person Dusda    schedule 10.10.2011    source источник
comment
Очевидный ответ - найти более быстрое (загрузочное) соединение. Вы можете временно обновить свое соединение или, возможно, попытаться занять или арендовать время (например, через cragislist, местную профессиональную группу и т. Д.).   -  person jdigital    schedule 11.10.2011
comment
У меня линия по 50мб вверх и вниз. Проблема, с которой я столкнулся, - это количество времени, которое требуется для возврата функции UploadFromStream (), и я столкнулся с некоторыми довольно странными проблемами со сборкой мусора с объектами Azure Blob, если я пытаюсь запустить более 10 задач параллельно.   -  person Dusda    schedule 11.10.2011
comment
Я знаю, что Rackspace позволяет вам просто доставить FedEx к ним, и они бесплатно разместят его в своем облаке. Есть ли у Microsoft что-нибудь подобное?   -  person Mike Christensen    schedule 12.10.2011
comment
MS действительно предлагает аналогичную услугу; azure.microsoft.com/en-gb/documentation / article /   -  person pkr2000    schedule 15.08.2016
comment
Одна вещь, которую я сделал для оптимизации очень большой массовой загрузки, - это поместить все на VHD, загрузить его, подключить к виртуальной машине в том же центре обработки данных, а затем запустить инструмент загрузки оттуда. Еще одна вещь в дополнение к другим оптимизациям.   -  person David Betz    schedule 17.10.2016


Ответы (6)


Хорошо, вот что я сделал. Я повозился с запуском BeginUploadFromStream (), затем BeginSetMetadata (), затем BeginSetProperties () в асинхронной цепочке, параллельной 5-10 потокам (комбинация предложений ElvisLive и knightpfhor). Это сработало, но все, что больше 5 потоков, имело ужасную производительность, на завершение каждого потока уходило до 20 секунд (работая на странице с десятью изображениями одновременно).

Итак, чтобы резюмировать различия в производительности:

  • Асинхронный: 5 потоков, каждый из которых выполняет асинхронную цепочку, каждый работает с десятью изображениями одновременно (выгружается по страницам из статистических соображений): ~ 15,8 секунды (на поток).
  • Синхронно: 1 поток, десять изображений за раз (постранично по статистическим причинам): ~ 3,4 секунды

Ладно, это довольно интересно. Один экземпляр, загружающий большие двоичные объекты синхронно, выполнялся в 5 раз лучше, чем каждый поток при другом подходе. Таким образом, даже при оптимальном балансе асинхронности из 5 потоков достигается практически такая же производительность.

Итак, я настроил импорт файла изображения, чтобы разделить изображения по папкам, каждая из которых содержит по 10 000 изображений. Затем я использовал Process.Start () для запуска экземпляра моего загрузчика больших двоичных объектов для каждой папки. У меня 170 000 изображений для работы в этом пакете, это означает 17 экземпляров загрузчика. При запуске всех из них на моем ноутбуке производительность всех из них выровнялась до ~ 4,3 секунды на набор.

Короче говоря, вместо того, чтобы пытаться оптимизировать работу потоков, я просто запускаю экземпляр загрузчика blob для каждых 10 000 изображений, причем все на одной машине одновременно. Общий прирост производительности?

  • Асинхронные попытки: 14–16 часов, исходя из среднего времени выполнения при запуске в течение часа или двух.
  • Синхронно с 17 отдельными экземплярами: ~ 1 час 5 минут.
person Dusda    schedule 12.10.2011

Вы обязательно должны загружать параллельно в несколько потоков (т. Е. Размещать несколько файлов одновременно), но прежде чем проводить какой-либо эксперимент, показывающий (ошибочно), что нет никакой выгоды, убедитесь, что вы действительно увеличили значение _ 1_:

Максимальное количество одновременных подключений, разрешенное объектом ServicePoint. Значение по умолчанию - 2.

При значении по умолчанию 2 у вас может быть не более двух невыполненных HTTP-запросов к любому месту назначения.

person Remus Rusanu    schedule 12.10.2011
comment
... Я не знал об этой настройке. Удивительно, что я ни разу не нашел упоминания об этом ни в одном из материалов по асинхронному хранилищу BLOB-объектов, которые я читал. Я уже выполнил свое решение и у меня нет времени попробовать это, но я обязательно учту его в будущем. Вероятно, это было основным узким местом. /ярость. - person Dusda; 12.10.2011
comment
msdn.microsoft.com/en-us/ library / 7af54za5% 28v = VS.100% 29.aspx. Значение по умолчанию 2 соответствует спецификациям HTTP / 1.1, но обычно упускается из виду, что любой стоящий на его счету сервер на самом деле находится за балансировщиком чистой нагрузки, и вы фактически нацелены на возможные сотни «серверов» с одним URL-адресом. (Конечно, в случае с хранилищем BLOB-объектов Azure) - person Remus Rusanu; 12.10.2011
comment
Установка этого значения таким образом влияет на все HTTP-соединения для сборки ... вы можете настроить диспетчер точек обслуживания только для соединения, с которым вы имеете дело. - person halfbit; 13.10.2011

Поскольку файлы, которые вы загружаете, довольно малы, я думаю, что написанный вами код, вероятно, настолько эффективен, насколько это возможно. Судя по вашему комментарию, похоже, что вы пробовали запускать эти загрузки параллельно, что на самом деле было единственным предложением кода, которое у меня было.

Я подозреваю, что для получения максимальной пропускной способности нужно найти правильное количество потоков для вашего оборудования, вашего соединения и размера вашего файла. Вы можете попробовать использовать Анализатор пропускной способности Azure, чтобы упростить поиск этого баланса.

Группа Microsoft Extreme Computing также имеет тесты и предложения по повышению пропускной способности . Он ориентирован на пропускную способность рабочих ролей, развернутых в Azure, но даст вам представление о том, на что вы можете надеяться.

person knightpfhor    schedule 11.10.2011
comment
В итоге я запустил кучу отдельных экземпляров загрузчика, сфокусированных на разных наборах изображений (10000 за раз). Спасибо за указатели, я все равно проголосовал за ваш ответ :). - person Dusda; 12.10.2011

Вы можете увеличить ParallelOperationThreadCount, как показано ниже. Я не проверял последний SDK, но в 1.3 ограничение было 64. Отсутствие этого значения привело к снижению количества одновременных операций.

CloudBlobClient blobStorage = new CloudBlobClient(config.AccountUrl, creds);
// todo: set this in blob extensions
blobStorage.ParallelOperationThreadCount = 64
person halfbit    schedule 12.10.2011

Если параллельный метод требует в 5 раз больше загрузки, чем последовательный, то вы либо

  • иметь ужасную пропускную способность
  • у меня очень медленный компьютер
  • сделать что-то не так

Моя утилита командной строки значительно улучшается при параллельной работе, хотя я не использую потоки памяти или другие подобные вещи, я просто генерирую строковый массив имен файлов, а затем загружаю их с помощью Parallel.ForEach.

Вдобавок вызов Properties.ContentType, вероятно, вас немного отбросит. Лично я никогда их не использую и полагаю, что они не должны иметь никакого значения, если только вы не хотите просматривать их прямо в браузере по прямым URL-адресам.

person bviktor    schedule 01.02.2014

Вы всегда можете попробовать асинхронные методы загрузки.

public override IAsyncResult BeginUploadFromStream (
Stream source,
AsyncCallback callback,
Object state

)

http://msdn.microsoft.com/en-us/library/windowsazure/ee772907.aspx

person ElvisLives    schedule 11.10.2011
comment
Пробовал это. Он работает, но имеет серьезные проблемы с производительностью. По какой-то причине загрузка Blob-объектов в параллельных потоках потребляет много ресурсов ЦП и выполняется довольно медленно, превышая 5 потоков. См. Мой ответ, чтобы узнать о моем возможном подходе. - person Dusda; 12.10.2011
comment
Еще одно продолжение ... Вы вообще пытались отключить алгоритм Нэгла? Я полностью разместил это раньше :) blogs.msdn.com/b/windowsazurestorage/archive/2010/06/25/ - person ElvisLives; 12.10.2011
comment
Вау, это выглядит безумно. У меня нет времени использовать это для этого решения (это одно из тех, которые должны быть быстрыми, но будут запускаться только один раз в истории всех проектов), но я добавил его в закладки для будущего импорта. делать. Спасибо чувак! - person Dusda; 12.10.2011