【问题标题】:Upload files to Azure BLOB storage - Parallel.Foreach is slower than Foreach将文件上传到 Azure BLOB 存储 - Parallel.Foreach 比 Foreach 慢
【发布时间】:2011-10-10 17:13:54
【问题描述】:

我有以下代码用于将文件夹形式本地存储上传到 blob 存储,在 blob 的名称中包含文件夹名称本身(该代码基于此处找到的一些方法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;
        }

此代码可以正常工作并按预期上传文件夹,但需要花费大量时间才能完成 - 需要 20 秒上传 25 个文件,每个文件 40KB~。所以我厌倦了用像这样的常规循环替换并行循环:

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 秒 大约)。

还需要注意的是,我正在使用 storage emulator 进行开发。
Parallel.Forech 显然应该更快。这种差异是来自存储模拟器的限制(上线时,Parallel 会更快)还是我可能做错了什么?

【问题讨论】:

    标签: azure azure-storage task-parallel-library azure-blob-storage parallel.foreach


    【解决方案1】:

    根据我的经验,存储模拟器不会告诉您任何内容关于您应该期望(或不期望)从实际 Azure 存储中获得的性能。模拟器通常非常慢。

    那么Parallel.Foreach 只会在您的传输碰巧是延迟绑定而不是 I/O 绑定时更快。然后,请注意Parallel.Foreach 只会使用你的 CPU 数量作为默认的并行度。对于延迟受限的进程,您通常应该拥有比这更多的线程,通常每个 CPU 有 4 到 8 个线程 (YMMV)。

    【讨论】:

    • 您能否更详细地解释一下 I/O 限制和延迟限制是什么意思,我的代码属于什么情况? (提醒一下,我是从本地存储上传的,以防万一)
    • 您可以通过使用异步传输获得最大的并行化。
    • @OliverBock 你能更具体一点吗?您的意思是使用 Parallel.Foreach 并在其中调用什么 async api ?
    • @YaronLevi,在正常的 for 循环中调用 CloudBlob.BeginUploadFromStream()。它将负责异步启动和运行上传,并在完成后(从另一个线程)回调您。
    猜你喜欢
    • 2017-01-24
    • 2017-08-19
    • 2019-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-27
    • 2019-08-13
    相关资源
    最近更新 更多