C#中的高性能文件复制?
我有一个大约500k jpg文件的庞大目录,我想归档所有早于某个日期的文件。 目前,该脚本需要数小时才能运行。
这与GoGrid的存储服务器非常糟糕的性能有很大关系,但与此同时,我确信有一种方法可以更有效地实现Ram / Cpu,以实现我正在做的事情。
这是我的代码:
var dirInfo = new DirectoryInfo(PathToSource); var fileInfo = dirInfo.GetFiles("*.*"); var filesToArchive = fileInfo.Where(f => f.LastWriteTime.Date = StopThresholdInDays.Days().Ago().Date ); foreach (var file in filesToArchive) { file.CopyTo(PathToTarget+file.Name); }
Days()。Ago()的东西只是语法糖。
虽然.NET 4.0提供了惰性Directory.EnumerateFiles
,但您现在可以在.NET 3.5上执行此操作:
我认为你可以改进的唯一部分是dirInfo.GetFiles("*.*")
。 在.NET 3.5及更早版本中,它返回一个包含所有文件名的数组,这需要时间来构建并使用大量RAM。 在.NET 4.0中,有一个新的Directory.EnumerateFiles
方法,它返回一个IEnumerable
,并在从磁盘读取结果时立即获取结果。 这可以提高性能,但不要指望奇迹……
您应该考虑使用第三方实用程序为您执行复制。 像robocopy这样的东西可能会显着加快你的处理速度。 另请参见https://serverfault.com/questions/54881/quickest-way-of-moving-a-large-number-of-files
我会记住80/20规则并注意,如果减速的大部分是 file.CopyTo
,并且这种减速远远超过LINQ查询的性能,那么我不担心。您可以通过删除 file.CopyTo
行并将其替换为Console.WriteLine
操作来测试此操作。与真实副本相比的时间。 你会发现GoGrid与其余操作的开销。 我的预感是你不会有任何现实的大收获 。
编辑 :好的,所以80%是GetFiles
操作,如果实际上目录中有一百万个文件,这并不奇怪。 您最好的选择可能是直接开始使用Win32 API(如FindFirstFile和系列 )和P / Invoke :
[DllImport("kernel32.dll", CharSet=CharSet.Auto)] static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);
如果可能的话,我还建议改变目录结构以减少每个目录的文件数量。 这将极大地改善这种情况。
EDIT2 :我还考虑从GetFiles("*.*")
更改为GetFiles()
。 既然你要求一切,那么在每一步都应用全局规则是没有意义的。
您可以尝试使用(有限数量的)线程来执行CopyTo()。 目前整个操作仅限于1个核心。
如果它现在受CPU限制,这只会提高性能。 但如果它在RAID上运行,它可能会起作用。
听听这个Hanselminutes播客 。 斯科特与Banshee媒体播放器的作者Aaron Bockover谈话,他们讨论了这个问题并在播客的8:20谈论它。
如果您可以使用.Net 4.0,那么请使用Thomas Levesque提到的Directory.EnumerateFiles。 如果没有,那么您可能需要编写自己的目录行走代码,就像使用本机Win32 API在Mono.Posix中一样。
上述就是C#学习教程:C#中的高性能文件复制?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1008140.html