简体   繁体   English

如何提高或保持复制文件的启动速度

[英]How to increase or keep starting speed of copying a file

I am using these codes to copy a big file:我正在使用这些代码来复制一个大文件:

const int CopyBufferSize = 64 * 1024;

string src = @"F:\Test\src\Setup.exe";
string dst = @"F:\Test\dst\Setup.exe";

public void CopyFile()
{
        Stream input = File.OpenRead(src);
        long length = input.Length;
        byte[] buffer = new byte[CopyBufferSize];
        Stopwatch swTotal = Stopwatch.StartNew();

        Invoke((MethodInvoker)delegate
        {
            progressBar1.Maximum = (int)Math.Abs(length / CopyBufferSize) + 1;
        });


        using (Stream output = File.OpenWrite(dst))
        {
            int bytesRead = 1;
            // This will finish silently if we couldn't read "length" bytes.
            // An alternative would be to throw an exception
            while (length > 0 && bytesRead > 0)
            {
                bytesRead = input.Read(buffer, 0, Math.Min(CopyBufferSize, buffer.Length));
                output.Write(buffer, 0, bytesRead);
                length -= bytesRead;

                Invoke((MethodInvoker)delegate
                {
                    progressBar1.Value++;
                    label1.Text = (100 * progressBar1.Value / progressBar1.Maximum).ToString() + " %";
                    label3.Text = ((int)swTotal.Elapsed.TotalSeconds).ToString() + " Seconds";
                });
            }

            Invoke((MethodInvoker)delegate
            {
                progressBar1.Value = progressBar1.Maximum;
            });
        }

        Invoke((MethodInvoker)delegate
        {
            swTotal.Stop();
            Console.WriteLine("Total time: {0:N4} seconds.", swTotal.Elapsed.TotalSeconds);
            label3.Text += ((int)swTotal.Elapsed.TotalSeconds - int.Parse(label3.Text.Replace(" Seconds",""))).ToString() + " Seconds";
        });
    }

The file size is about 4 GB.文件大小约为 4 GB。

In the first 7 seconds it can copy up to 400 MB then this hot speed calms down.在最初的 7 秒内,它最多可以复制 400 MB,然后这个炙手可热的速度就会平静下来。

What happen and how to keep this hot speed or even increase it?会发生什么以及如何保持这种热速度甚至增加它?

Another question is here: When the file copied, windows is still working on destination file(about 10 seconds).另一个问题是:复制文件时,Windows 仍在处理目标文件(大约 10 秒)。

Copy Time: 116 seconds复制时间:116 秒

extra time: 10-15 seconds or even more加时:10-15秒甚至更多

How to remove or decrease this extra time?如何消除或减少这个额外的时间?

What happens?发生什么了? Caching, mostly.缓存,主要是。

The OS pretends you copied 400 MiB in seven seconds, but you didn't.操作系统假装您在 7 秒内复制了 400 MiB,但您没有。 You just sent 400 MiB to the OS (or file system) to write in the future, and that's as much as the buffer can take.您刚刚向操作系统(或文件系统)发送了 400 MiB 以供将来写入,这与缓冲区可以容纳的一样多。 If you try to write a 400 MiB file and you pull the plug as soon as it's "done", your file will not be written.如果您尝试编写一个 400 MiB 的文件,并且在“完成”后立即拔掉插头,则不会写入您的文件。 The same thing deals with the "overtime" - your application has sent all it has to the buffer, but the buffer isn't yet written to the drive itself (either its buffer, or even slower, the actual physical platter).同样的事情处理“超时” - 您的应用程序已将其所有内容发送到缓冲区,但缓冲区尚未写入驱动器本身(其缓冲区,甚至更慢的实际物理盘片)。

This is especially visible with USB flash drives, which tend to use caching heavily.这在 USB 闪存驱动器中尤为明显,它们往往会大量使用缓存。 This makes working with the (usually very slow) drive much more pleasant, with the trade-off that you have to wait for the OS to finish writing everything before pulling the drive out (that's why you get the "Safe remove" icon).这使得使用(通常非常慢)驱动器变得更加愉快,权衡你必须等待操作系统完成在拉出驱动器之前写完所有内容(这就是为什么你得到“安全删除”图标)。

So it should be obvious that you can't really make the total time shorter.所以很明显,你不能真正缩短时间。 All you can do is try and make the user interface reflect reality a bit better, so that the user doesn't see the "first 400 MiB are so fast!"你所能做的就是尝试让用户界面更好地反映现实,这样用户就不会看到“前 400 MiB 太快了!” thing... but it doesn't really work well.事情......但它并不能很好地工作。 In any case, your read->write speed is ~30 MiB/s.无论如何,您的读取-> 写入速度约为 30 MiB/s。 The OS just hides the peaks to make it easier to deal with the slow hard drive - very useful when you're dealing with lots of small files, worthless when dealing with files bigger than the buffer.操作系统只是隐藏了峰值,以便更轻松地处理缓慢的硬盘驱动器 - 当您处理大量小文件时非常有用,而在处理大于缓冲区的文件时则毫无价值。

You have a bit of control over this when you use the FileStream constructor directly, instead of using File.OpenWrite - you can use FileOptions.WriteThrough to instruct the OS to avoid any caching and write directly to disk[1], giving you a better idea of the real write speed.当您直接使用FileStream构造函数而不是使用File.OpenWrite ,您可以FileOptions.WriteThrough进行一些控制 - 您可以使用FileOptions.WriteThrough来指示操作系统避免任何缓存并直接写入磁盘 [1],为您提供更好的真实写入速度的想法。 Do note that this usually makes the total time larger, though, and it may make concurrent access even worse.请注意,这通常会使时间变长,并且可能使并发访问变得更糟。 You definitely don't want to use it for small files.您绝对不想将它用于小文件。

[1] - Haha, right. [1] - 哈哈,对了。 The drive usually has caching of its own, and some ignore the OS' pleas.驱动器通常有自己的缓存,有些会忽略操作系统的请求。 Tough luck.倒霉。

One thing you could try is to increase the buffer size.您可以尝试的一件事是增加缓冲区大小。 This really matters when the write cache can no longer keep up (as discussed in other answer).当写缓存无法再跟上时,这真的很重要(如其他答案中所述)。 Writing a lot of small blocks is often slower than writing a few large blocks.写很多小块通常比写几个大块慢。 Instead of 64 kB, try 1 MB, 4 MB or even bigger:尝试使用 1 MB、4 MB 甚至更大的内存,而不是 64 kB:

const int CopyBufferSize = 1 * 1024 * 1024;   // 1 MB
// or
const int CopyBufferSize = 4 * 1024 * 1024;   // 4 MB

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM