C# 使用Paralell.Foreach()时Diretory.GetFiles()的性能
众所周知,Directory.GetFiles()不是很快。 我想尽快找到一些文件。 我遇到了一些奇怪的结果 我开始使用C# 使用Paralell.Foreach()时Diretory.GetFiles()的性能,c#,performance,getfiles,C#,Performance,Getfiles,众所周知,Directory.GetFiles()不是很快。 我想尽快找到一些文件。 我遇到了一些奇怪的结果 我开始使用Parallel.ForEach并在我的C:\-Drive上迭代所有directory 我实现了3种方法并显示了结果。它们在我过去在目录中深入研究的并行数上有所不同 这是结果 我不明白为什么使用一个并行比使用两个并行更快。。。 我一点也不明白为什么他们发现的文件数量不同 长话短说以下是我的代码: 来电者 private void Start(对象发送方,事件参数e) { 新线
Parallel.ForEach
并在我的C:\-Drive
上迭代所有directory
我实现了3种方法并显示了结果。它们在我过去在目录中深入研究的并行数上有所不同
这是结果
我不明白为什么使用一个并行比使用两个并行更快。。。
我一点也不明白为什么他们发现的文件数量不同
长话短说以下是我的代码:
来电者
private void Start(对象发送方,事件参数e)
{
新线程(()=>
{
秒表=新秒表();
watch.Start();
List files=highperformancefilegetter.GetFilesInDirectory\u DoubleParallel(@“C:\”、“*.txt”、SearchOption.AllDirectories);
看,停;
MessageBox.Show($“在[{watch.appeased.totalms}ms]中找到[{files.Count}]文件=>[{watch.appeased.TotalSeconds}]s”,“双并行”);
}).Start();
新线程(()=>
{
秒表=新秒表();
watch.Start();
List files=highperformancefilegetter.GetFilesInDirectory\u SingleParallell(@“C:\”、“*.txt”、SearchOption.AllDirectories);
看,停;
MessageBox.Show($“在[{watch.appeased.totalmillizes}ms]=>[{watch.appeased.TotalSeconds}]s中找到[{files.Count}]个文件”,“单并行”);
}).Start();
新线程(()=>
{
秒表=新秒表();
watch.Start();
List files=highperformancefilegetter.GetFilesInDirectory\u TripleParallel(@“C:\”、“*.txt”、SearchOption.AllDirectories);
看,停;
MessageBox.Show($“在[{watch.appeased.totalms}ms]中找到[{files.Count}]文件=>[{watch.appeased.TotalSeconds}]s”,“Tripe Parallel”);
}).Start();
}
搜索:
publicstaticlist GetFilesInDirectory\u TripleParallel(stringrootdirectory、stringpattern、System.IO.SearchOption选项)
{
列表结果文件=新列表();
//苏晨:
DirectoryInfo root=新的DirectoryInfo(rootDirectory);
if(root.Exists)
{
//性能:
Parallel.ForEach(root.GetDirectories(),(dir)=>
{
尝试
{
Parallel.ForEach(dir.GetDirectories(),(dir_1)=>
{
尝试
{
Parallel.ForEach(dir_1.GetDirectories(),(dir_2)=>
{
尝试
{
AddRange(dir_2.GetFiles(pattern,option));
}
捕获(异常){}
});
}
捕获(异常){}
});
}
捕获(异常){}
});
返回结果文件;
}
Debug.Fail($“根[{Root.FullName}]不存在”);
返回null;
}
注意:我刚刚发布了三种方法中的一种,但你可以看到有什么不同。这只是我用的平行数
有人知道在性能方面最好的术语是什么,以及为什么文件计数不同吗?不同文件计数的原因是
SearchOption.AllDirectories
。在单并行版本中,如果阅读C:\
,则会得到所有子目录中的所有文件。在你的三重版本中
- 下面所有子目录中的所有文件
`C:
- 加上`C:\dir1´(->重复项)下所有子目录中的所有文件
- 加上下面所有子目录中的所有文件
(->新副本)C:\dir1\dir2
C:\
中的所有文件添加一次,C:\dir1
中的所有文件添加两次,C:\dir1\dir2
中的所有文件添加三次
对于测量的时间:如果从单个硬盘驱动器读取,并行化将没有帮助。这里导致延迟的是I/O系统。即使是一百个线程也要等待硬盘。因此,我实际上希望并行化会因为开销而降低整个操作的速度
有趣的是,三重版本速度最快,尽管它读取目录的频率更高,但这可能是由文件系统的缓存造成的。因此,如果您在一个进程中一个接一个地直接运行所有三个测试,那么您的测试实际上并不正确。不同文件计数的原因是
SearchOption.AllDirectories
。在单并行版本中,如果阅读C:\
,则会得到所有子目录中的所有文件。在你的三重版本中
- 下面所有子目录中的所有文件
`C:
- 加上`C:\dir1´(->重复项)下所有子目录中的所有文件
- 加上下面所有子目录中的所有文件
(->新副本)C:\dir1\dir2
C:\
中的所有文件添加一次,C:\dir1
中的所有文件添加两次,C:\dir1\dir2
中的所有文件添加三次
对于测量的时间:如果从单个硬盘驱动器读取,并行化将没有帮助。这里导致延迟的是I/O系统。即使是一百个线程也要等待硬盘。因此,我实际上希望并行化会因为开销而降低整个操作的速度
有趣的是,三重版本是最快的
private void Start(object sender, EventArgs e)
{
new Thread(() =>
{
Stopwatch watch = new Stopwatch();
watch.Start();
List<FileInfo> files = HighPerformanceFileGettter.GetFilesInDirectory_DoubleParallel(@"C:\", "*.txt", SearchOption.AllDirectories);
watch.Stop();
MessageBox.Show($"Found [{files.Count}] files in [{watch.Elapsed.TotalMilliseconds}ms] => [{watch.Elapsed.TotalSeconds}]s", "Double Parallel");
}).Start();
new Thread(() =>
{
Stopwatch watch = new Stopwatch();
watch.Start();
List<FileInfo> files = HighPerformanceFileGettter.GetFilesInDirectory_SingleParallell(@"C:\", "*.txt", SearchOption.AllDirectories);
watch.Stop();
MessageBox.Show($"Found [{files.Count}] files in [{watch.Elapsed.TotalMilliseconds}ms] => [{watch.Elapsed.TotalSeconds}]s", "Single Parallel");
}).Start();
new Thread(() =>
{
Stopwatch watch = new Stopwatch();
watch.Start();
List<FileInfo> files = HighPerformanceFileGettter.GetFilesInDirectory_TripleParallel(@"C:\", "*.txt", SearchOption.AllDirectories);
watch.Stop();
MessageBox.Show($"Found [{files.Count}] files in [{watch.Elapsed.TotalMilliseconds}ms] => [{watch.Elapsed.TotalSeconds}]s", "Tripe Parallel");
}).Start();
}
public static List<FileInfo> GetFilesInDirectory_TripleParallel(string rootDirectory, string pattern, System.IO.SearchOption option)
{
List<FileInfo> resultFiles = new List<FileInfo>();
//Suchen:
DirectoryInfo root = new DirectoryInfo(rootDirectory);
if (root.Exists)
{
//Performance:
Parallel.ForEach(root.GetDirectories(), (dir) =>
{
try
{
Parallel.ForEach(dir.GetDirectories(), (dir_1) =>
{
try
{
Parallel.ForEach(dir_1.GetDirectories(), (dir_2) =>
{
try
{
resultFiles.AddRange(dir_2.GetFiles(pattern, option));
}
catch (Exception) { }
});
}
catch (Exception) { }
});
}
catch (Exception) { }
});
return resultFiles;
}
Debug.Fail($"Root [{root.FullName}] does not exist");
return null;
}