Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is FileStream and CopyFile so much slower than Windows Explorer?

I'm trying to a copy a file across a network (Windows Server 2008 R2 to Windows 7 SP1 Enterprise) and when I drag-and-drop using Windows Explorer, I'm getting about 4.5 MB/s. (It's a WAN connection)

However, when I use FileStream.Read(), I'm only getting around 1.5 MB/s. I've tried different buffer-sizes ranging from 1 KB to 4 MB. I've also tried using CopyFile() and CopyFileEx() but I am getting the same results.

What might be going on here and how can I fix my code?

EDIT: I've also tried using TeraCopy (3rd party tool) and it is also only getting 1.5 MB/s.

like image 245
SofaKng Avatar asked Jan 13 '23 10:01

SofaKng


2 Answers

I don't know if you are still experiencing this issue or not, but I have been wrestling with this issue for days so I thought I would post this. I finally found a solution that is up to par with the Explorer copy routine. I do not know if this works for FileStream, but I was able to use CopyFile or CopyFileEx to get the same performance. In my case, CopyFileEx was a better choice because I wanted a progress callback. After using Process Monitor to examine the copy process, I noticed that the system was resetting the stream position (even though it hadn't moved) before every single read and write operation for each 32k chunk copy (hence the poor performance). The key, in either case, is to set IO permissions on the source and destination files using FileIOPermission before starting the copy operation.

Here's the relevant excerpt from my code:

new FileIOPermission(FileIOPermissionAccess.Read, SourcePath).Demand();
new FileIOPermission(FileIOPermissionAccess.Write, DestinationPath).Demand();

if (!NativeCopy.CopyFileEx(SourcePath, DestinationPath,
    new NativeCopy.CopyProgressRoutine(this.CopyProgressHandler), GCHandle.ToIntPtr(hArgs),
    ref pbCancel, flags))
{
    throw new IOException(new System.ComponentModel.Win32Exception().Message);
}

Hopes this helps. It drove me crazy trying to figure out what was going on.

like image 144
Michael Mims Avatar answered Feb 01 '23 12:02

Michael Mims


The solution for me was to disable the COPY_FILE_RESTARTABLE flag for CopyFileEx. I got about 4-5x the speed once that flag was removed.

See MSDN's description of that flag here.

Progress of the copy is tracked in the target file in case the copy fails... This can significantly slow down the copy operation as the new file may be flushed multiple times during the copy operation.

like image 22
Matt Schroeder Avatar answered Feb 01 '23 14:02

Matt Schroeder