1

我有以下代码用于上传文件夹表格本地存储到blob存储,包括文件夹名称本身在blob的名称中(代码基于这里找到http://blog.smarx.com/posts/pivot-odata-and-windows-azure-visual-netflix-browsing一些方法):上传文件到Azure BLOB存储 - Parallel.Foreach比Foreach慢

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

重要的是要注意,我正在针对存储模拟器进行开发。
Parallel.Forech显然应该更快。这种差异是否来自存储模拟器的限制(并且在上线时,Parallel会更快),还是我可能做错的其他事情?

回答

4

根据我的经验,存储模拟器告诉你严格地说没有什么关于你应该从实际的Azure存储(或不)的性能。模拟器通常非常慢。

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

+0

您能否更详细地解释I/O绑定和延迟绑定是什么意思,以及我的代码属于哪种情况? (只需提醒一下,我从本地存储上传,以防重要) –

+1

您可以通过使用异步传输获得最大的并行性。 –

+0

@OliverBock你能更具体吗?你的意思是使用Parallel.Foreach并在里面调用什么async api? –