如何更快地使我的应用程序复制文件

时间:2009-08-17 06:01:25

标签: c# file-io

我已经从负载均衡服务器创建了常规下载文件的Windows应用程序,目前速度约为30MB /秒。但是,我尝试使用FastCopy或TeraCopy,它可以以大约100MB /秒的速度复制。我想知道如何提高我的复制速度,使其能够比当前更快地复制文件。

6 个答案:

答案 0 :(得分:4)

使用流时的一个常见错误是一次复制一个字节,或者使用一个小缓冲区。将数据写入磁盘所花费的大部分时间用于搜索,因此使用更大的缓冲区将减少每个字节的平均搜索时间。

操作系统将文件写入群集中的磁盘。这意味着当您将单个字节写入磁盘时,Windows实际上会写入512字节到64 kb大小的块。通过使用64kb的整数倍的缓冲区,您可以获得更好的磁盘性能。

此外,您可以通过使用缓冲区来获得提升,该缓冲区是CPU内存页面大小的倍数。对于x86 / x64机器,可以设置为4kb或4mb。

所以你想使用4mb的整数倍。

此外,如果使用异步IO,则可以充分利用大缓冲区大小。

class Downloader
{
    const int size = 4096 * 1024;
    ManualResetEvent done = new ManualResetEvent(false);
    Socket socket;
    Stream stream;

    void InternalWrite(IAsyncResult ar)
    {
        var read = socket.EndReceive(ar);
        if (read == size)
            InternalRead();
        stream.Write((byte[])ar.AsyncState, 0, read);
        if (read != size)
            done.Set();
    }

    void InternalRead()
    {
        var buffer = new byte[size];
        socket.BeginReceive(buffer, 0, size, System.Net.Sockets.SocketFlags.None, InternalWrite, buffer);
    }

    public bool Save(Socket socket, Stream stream)
    {
        this.socket = socket;
        this.stream = stream;

        InternalRead();
        return done.WaitOne();
    }
}

bool Save(System.Net.Sockets.Socket socket, string filename)
{
    using (var stream = File.OpenWrite(filename))
    {
        var downloader = new Downloader();
        return downloader.Save(socket, stream);
    }
}

答案 1 :(得分:2)

可能您的应用程序可以执行多线程以使用多个线程获取文件,但带宽仅限于传输内容的设备的速度

答案 2 :(得分:1)

最简单的方法是以原始/二进制模式打开文件(即C语言不确定C#等价物是什么)并且一次读写非常大的块(几MB)。

答案 3 :(得分:1)

TeraCopy使用的技巧是使读写异步。这意味着可以在读取另一个数据块时写入数据块。

你必须摆弄块的数量和这些块的大小,以便为你的情况提供最佳选择。我使用这种方法使用C ++,对我们来说,当从网络共享复制到本地磁盘时,最佳使用了四个256KB的块。

此致

Sebastiaan

答案 4 :(得分:1)

如果您运行Process Monitor,则可以看到Windows资源管理器或TeraCopy正在使用的块大小。

在Vista中,本地网络的默认块大小为2 MB,这使得在大型管道上复制文件的速度要快得多。

答案 5 :(得分:0)

为什么重新发明轮子?

如果您的情况允许,您可能最好不要尝试自己编写一个现有的“快速”复制实用程序。有许多非明显的边缘情况需要处理,并且获得始终如一的良好性能需要大量的试验 - 结束错误实验。