为什么.NET异步等待文件复制比同步File.Copy()调用消耗更多的CPU? [英] Why .NET async await file copy is a lot more CPU consuming than synchronous File.Copy() call?

查看:43
本文介绍了为什么.NET异步等待文件复制比同步File.Copy()调用消耗更多的CPU?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么下面的代码会导致:

 公共静态类Program{公共静态无效的主要(参数字符串[]参数){var sourceFileName = @"C:\ Users \ ehoua \ Desktop \ Stuff \ 800MFile.exe";var destinationFileName = sourceFileName +".bak";FileCopyAsync(sourceFileName,destinationFileName);//下面的行实际上更快,并且CPU消耗少得多//File.Copy(sourceFileName,destinationFileName,true);Console.ReadKey();}公共静态异步void FileCopyAsync(字符串sourceFileName,字符串destinationFileName,int bufferSize = 0x1000,CancellationToken cancelledToken = default(CancellationToken)){使用(var sourceFile = File.OpenRead(sourceFileName)){使用(var destinationFile = File.OpenWrite(destinationFileName)){Console.WriteLine($正在将{sourceFileName}复制到{destinationFileName} ..."));等待sourceFile.CopyToAsync(destinationFile,bufferSize,cancellationToken);Console.WriteLine("Done");}}}} 

同时使用File.Copy():

那么使用async/await进行文件复制仍然有真正的兴趣吗?

我认为保存线程进行复制可能值得,但是File.Copy Windows函数似乎赢得了CPU%的殊荣.有人会说这是因为真正的DMA支持,但我是否仍在做任何破坏演出的事情?还是可以通过我的异步方法来改善CPU使用率?

解决方案

File.OpenRead(sourceFileName)等效于 new FileStream(sourceFileName,FileMode.Open,FileAccess.Read,FileShare.Read)依次等效于 public FileStream(sourceFileName,FileMode.Open,FileAccess.Read,FileShare.Read,4096,false),用 false用于异步I/O.等效于 File.OpenWrite .

因此,任何 XXXAsync 操作都不会使用异步I/O,但会使用线程池线程来伪造它.

因此,它没有获得异步I/O的好处,并且浪费了至少一个线程.您想要避免I/O上的额外线程阻塞.我通常希望异步的性能比同步稍微慢一些(异步通常会牺牲一次性的速度来获得更好的可伸缩性),但是我绝对希望这比将整个东西包装成 Task.Run().

我仍然不希望它这么糟糕,但是也许反恶意软件正在通过写入.exe来担心.

希望您会更好地复制非exe文件并使用异步流.

Why the code below results in:

public static class Program
{
    public static void Main(params string[] args)
    {
        var sourceFileName = @"C:\Users\ehoua\Desktop\Stuff\800MFile.exe";
        var destinationFileName = sourceFileName + ".bak";

        FileCopyAsync(sourceFileName, destinationFileName);

        // The line below is actually faster and a lot less CPU-consuming
        // File.Copy(sourceFileName, destinationFileName, true);

        Console.ReadKey();
    }

    public static async void FileCopyAsync(string sourceFileName, string destinationFileName, int bufferSize = 0x1000, CancellationToken cancellationToken = default(CancellationToken))
    {
        using (var sourceFile = File.OpenRead(sourceFileName))
        {
            using (var destinationFile = File.OpenWrite(destinationFileName))
            {
                Console.WriteLine($"Copying {sourceFileName} to {destinationFileName}...");
                await sourceFile.CopyToAsync(destinationFile, bufferSize, cancellationToken);
                Console.WriteLine("Done");
            }
        }
    }
}

While File.Copy(): https://msdn.microsoft.com/en-us/library/system.io.file.copy(v=vs.110).aspx is a lot less cpu-consuming:

So is there still a real interest using async / await for file copy purposes?

I thought saving a thread for copying might worth it but the File.Copy windows function seems to win the battle hands down in terms of CPU %. Some would argue it's because of the real DMA support but still, am I doing anything to ruin the performances? Or is there anything that can be done to improve the CPU usage with my async method?

解决方案

File.OpenRead(sourceFileName) is equivalent to new FileStream(sourceFileName, FileMode.Open, FileAccess.Read, FileShare.Read) which is in turn equivalent to public FileStream(sourceFileName, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, false) which is to say with false for async I/O. The equivalent is true of the File.OpenWrite.

As such any XXXAsync operations won't use async I/O but will fake it using thread-pool threads.

So it gets none of the benefit of async I/O and wastes at least one thread. You've got an extra thread blocking on I/O which was what you wanted to avoid. I'd generally expect async on its own to perform slightly slower than sync (async generally sacrifices one-off speed for better scalability) but I'd definitely expect this to do little better, if at all, than wrapping the whole thing in Task.Run().

I'd still not expect it to be quite as bad, but maybe anti-malware is being worried by writing to an .exe.

You would hopefully fare better copying a non-exe and with asynchronous streams.

这篇关于为什么.NET异步等待文件复制比同步File.Copy()调用消耗更多的CPU?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆