10

我的硬盘上本地存储了大约 110,000 张各种格式(jpg、png 和 gif)和大小(2-40KB)的图像。我需要将它们上传到 Azure Blob 存储。在执行此操作时,我需要设置一些元数据和 blob 的 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();
    }
}

我想知道是否有另一种技术可以用来处理上传,以使其尽可能快。这个特定项目涉及将大量数据从一个系统导入到另一个系统,并且出于客户原因,它需要尽快完成。

4

6 回答 6

7

好的,这就是我所做的。我修改了在异步链中运行 BeginUploadFromStream()、BeginSetMetadata() 和 BeginSetProperties(),并行运行 5-10 个线程(ElvisLive 和 knightpfhor 建议的组合)。这行得通,但任何超过 5 个线程的性能都很糟糕,每个线程(一次处理 10 张图像的页面)需要超过 20 秒才能完成。

因此,总结性能差异:

  • 异步:5 个线程,每个线程运行一个异步链,每个线程一次处理 10 张图像(出于统计原因分页):~15.8 秒(每个线程)。
  • 同步:1 个线程,一次 10 张图像(出于统计原因分页):~3.4 秒

好吧,这很有趣。一个实例同步上传 blob 的性能比另一种方法中的每个线程好 5 倍。因此,即使运行 5 个线程的最佳异步平衡,性能也基本相同

因此,我调整了图像文件的导入,将图像分离到每个包含 10,000 张图像的文件夹中。然后我使用 Process.Start() 为每个文件夹启动我的 blob 上传器实例。我在这批中有 170,000 张图片要处理,这意味着上传器的 17 个实例。在我的笔记本电脑上运行所有这些时,所有这些的性能都稳定在每组约 4.3 秒

长话短说,我没有尝试让线程以最佳方式工作,而是为每 10,000 张图像运行一个 blob 上传器实例,同时在一台机器上运行。整体性能提升?

  • 异步尝试:14-16 小时,基于运行一两个小时的平均执行时间。
  • 与 17 个独立实例同步:约 1 小时 5 分钟。
于 2011-10-12T00:26:42.090 回答
3

您绝对应该在多个流中并行上传(即同时发布多个文件),但是在您进行任何显示(错误地)没有好处的实验之前,请确保您实际上增加了 的值ServicePointManager.DefaultConnectionLimit

ServicePoint 对象允许的最大并发连接数。默认值为 2。

使用默认值 2,您最多可以有两个针对任何目标的未完成的 HTTP 请求。

于 2011-10-12T00:37:24.840 回答
1

由于您上传的文件非常小,我认为您编写的代码可能与您所能获得的一样高效。根据您的评论,您似乎已经尝试并行运行这些上传,这确实是我唯一的其他代码建议。

我怀疑为了获得最大的吞吐量,需要为您的硬件、连接和文件大小找到合适的线程数。你可以尝试使用Azure 吞吐量分析器来更轻松地找到这种平衡。

微软的极限计算小组也有关于提高吞吐量的基准和建议。它侧重于部署在 Azure 上的辅助角色的吞吐量,但它会让您了解您希望达到的最佳效果。

于 2011-10-11T21:03:22.503 回答
1

您可能需要增加 ParallelOperationThreadCount,如下所示。我没有检查最新的 SDK,但在 1.3 中限制为 64。不设置此值会导致并发操作数较低。

CloudBlobClient blobStorage = new CloudBlobClient(config.AccountUrl, creds);
// todo: set this in blob extensions
blobStorage.ParallelOperationThreadCount = 64
于 2011-10-12T21:39:11.553 回答
1

如果并行方法的上传时间是串行方法的 5 倍,那么您要么

  • 有可怕的带宽
  • 电脑很慢
  • 做错事

即使我不使用内存流或任何其他类似的漂亮东西,我的命令行实用程序在并行运行时也会得到相当大的提升,我只是生成文件名的字符串数组,然后使用Parallel.ForEach.

此外,这个Properties.ContentType电话可能会让你退缩很多。就我个人而言,我从不使用它们,我想它们甚至都不重要,除非您想通过直接 URL 在浏览器中直接查看它们。

于 2014-02-01T13:01:18.490 回答
0

您可以随时尝试上传的异步方法。

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

)

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

于 2011-10-11T05:25:21.240 回答