#azure #azure-storage #task-parallel-library #azure-blob-storage #parallel.foreach
#azure #azure-хранилище #задача-параллельная-библиотека #azure-blob-storage #parallel.foreach
Вопрос:
У меня есть следующий код для загрузки папки из локального хранилища в хранилище больших двоичных объектов, включая само имя папки в имени большого двоичного объекта (код основан на некоторых методах, найденных здесь http://blog.smarx.com/posts/pivot-odata-and-windows-azure-visual-netflix-browsing ) :
public static void UploadBlobDir(CloudBlobContainer container, string dirPath)
{
string dirName = new Uri(dirPath).Segments.Last();
Parallel.ForEach(enumerateDirectoryRecursive(dirPath), file =>
{
string blobName = Path.Combine(dirName, Path.GetFullPath(file)).Substring(dirPath.Length - dirName.Length);
container.GetBlobReference(blobName).UploadFile(file);
});
}
и :
private static IEnumerable<string> enumerateDirectoryRecursive(string root)
{
foreach (var file in Directory.GetFiles(root))
yield return file;
foreach (var subdir in Directory.GetDirectories(root))
foreach (var file in enumerateDirectoryRecursive(subdir))
yield return file;
}
Этот код работает и загружает папку по назначению, но для его завершения требуется очень много времени — для загрузки 25 файлов по 40 КБ ~ каждый требуется 20 секунд. Итак, я устал заменять параллельный цикл обычным, например :
foreach (var file in enumerateDirectoryRecursive(i_DirPath))
{
string blobName = Path.Combine(dirName, Path.GetFullPath(file)).Substring(i_DirPath.Length - dirName.Length);
container.GetBlobReference(blobName).UploadFile(file);
}
Теперь загрузка завершается мгновенно (примерно за 3 секунды).
Также важно отметить, что я работаю с эмулятором хранилища для разработки.
Параллель.Очевидно, что Forech должен быть быстрее. Возникает ли эта разница из-за ограничений эмулятора хранилища (и при запуске в режиме реального времени Parallel будет быстрее) или это что-то еще, что я могу делать неправильно?
Ответ №1:
По моему опыту, эмулятор хранилища ничего не сообщает вам о производительности, которую вы должны ожидать (или нет) от фактического хранилища Azure. Эмулятор обычно работает очень медленно.
Тогда Parallel.Foreach
будет быстрее, только если ваша передача связана с задержкой, а не с вводом-выводом. Тогда, пожалуйста, обратите внимание, что Parallel.Foreach
в качестве степени распараллеливания по умолчанию будет использоваться только ваше количество процессоров. Для процессов, связанных с задержкой, у вас обычно должно быть намного больше потоков, обычно от 4 до 8 потоков на процессор (YMMV).
Комментарии:
1. Можете ли вы более подробно объяснить, что вы подразумеваете под привязкой ввода-вывода и задержкой, и к какому регистру относится мой код? (Просто напоминаю, я загружаю из локального хранилища, если это имеет значение)
2. Вы можете добиться максимального распараллеливания, используя асинхронные передачи.
3. @OliverBock Вы можете быть более конкретными? Вы имеете в виду параллельное использование. Foreach и внутри него вызывают какой асинхронный API?
4. @YaronLevi, вызовите CloudBlob . BeginUploadFromStream() в обычном цикле for . Он позаботится о запуске и выполнении загрузки асинхронно и перезвонит вам (из другого потока) по завершении.