我的问题是关于文件复制性能。我们有一个媒体管理系统,需要将文件系统上的大量文件移动到不同位置,包括同一网络上的 Windows 共享、FTP 站点、AmazonS3 等。当我们都在一个 Windows 网络上时,我们可以使用System.IO.File.Copy(source,destination) 复制文件。由于很多时候我们拥有的只是一个输入流(如 MemoryStream),因此我们尝试抽象复制操作以获取输入流和输出流,但我们发现性能大幅下降。下面是一些用于复制文件以用作讨论点的代码。
public void Copy(System.IO.Stream inStream, string outputFilePath)
{
int bufferSize = 1024 * 64;
using (FileStream fileStream = new FileStream(outputFilePath, FileMode.OpenOrCreate, FileAccess.Write))
{
int bytesRead = -1;
byte[] bytes = new byte[bufferSize];
while ((bytesRead = inStream.Read(bytes, 0, bufferSize)) > 0)
{
fileStream.Write(bytes, 0, bytesRead);
fileStream.Flush();
}
}
}
有谁知道为什么它的执行速度比 File.Copy 慢得多?我可以做些什么来提高性能吗?我是否需要添加特殊逻辑来查看是否从一个窗口位置复制到另一个窗口位置 - 在这种情况下我将只使用 File.Copy 而在其他情况下我将使用流?
请告诉我您的想法以及是否需要其他信息。我尝试过不同的缓冲区大小,似乎 64k 缓冲区大小对于我们的“小”文件来说是最佳的,而 256k+ 对于我们的“大”文件来说是更好的缓冲区大小 - 但在任何一种情况下,它的性能都比 File.Copy( )。提前致谢!
File.Copy 是围绕CopyFileWin32 函数和此函数引起了 MS 人员的极大关注(请记住有关缓慢复制性能的 Vista 相关线程)。
提高方法性能的几个线索:
- 就像许多人之前所说的那样,从循环中删除 Flush 方法。你根本不需要它。
- 增加缓冲区可能会有所帮助,但仅限于文件到文件操作、网络共享或 ftp 服务器,这反而会减慢速度。 60 * 1024 是网络共享的理想选择,至少在 vista 之前是这样。对于 ftp,大多数情况下 32k 就足够了。
- 通过提供缓存策略(在您的情况下顺序读取和写入)来帮助操作系统,使用 FileStream 构造函数重写文件选项参数(顺序扫描)。
- 您可以使用异步模式来加速复制(对于网络到文件的情况特别有用),但不要为此使用线程,而是使用重叠的 io(.net 中的 BeginRead、EndRead、BeginWrite、EndWrite),并且不要忘记在 FileStream 构造函数中设置异步选项(请参阅文件选项)
异步复制模式示例:
int Readed = 0;
IAsyncResult ReadResult;
IAsyncResult WriteResult;
ReadResult = sourceStream.BeginRead(ActiveBuffer, 0, ActiveBuffer.Length, null, null);
do
{
Readed = sourceStream.EndRead(ReadResult);
WriteResult = destStream.BeginWrite(ActiveBuffer, 0, Readed, null, null);
WriteBuffer = ActiveBuffer;
if (Readed > 0)
{
ReadResult = sourceStream.BeginRead(BackBuffer, 0, BackBuffer.Length, null, null);
BackBuffer = Interlocked.Exchange(ref ActiveBuffer, BackBuffer);
}
destStream.EndWrite(WriteResult);
}
while (Readed > 0);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)