Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么.NET async await file copy比同步file.copy()调用占用更多CPU?_C#_.net_Asynchronous_Io_File Copying - Fatal编程技术网

C# 为什么.NET async await file copy比同步file.copy()调用占用更多CPU?

C# 为什么.NET async await file copy比同步file.copy()调用占用更多CPU?,c#,.net,asynchronous,io,file-copying,C#,.net,Asynchronous,Io,File Copying,为什么下面的代码会导致: 而File.Copy():占用的cpu要少得多: 那么,使用async/await进行文件复制是否还有真正的兴趣呢 我认为保存一个线程以进行复制可能是值得的,但File.Copy windows功能似乎可以轻而易举地在CPU%方面赢得这场战斗。有人会说这是因为真正的DMA支持,但我还是在做任何事情来破坏表演吗?或者,有什么办法可以通过我的异步方法来提高CPU使用率吗?这些都是非常荒谬的性能数字。你根本不是在衡量你认为自己是什么。这不应该超过一个小光点,即缓存文件数据

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

而File.Copy():占用的cpu要少得多:

那么,使用async/await进行文件复制是否还有真正的兴趣呢


我认为保存一个线程以进行复制可能是值得的,但File.Copy windows功能似乎可以轻而易举地在CPU%方面赢得这场战斗。有人会说这是因为真正的DMA支持,但我还是在做任何事情来破坏表演吗?或者,有什么办法可以通过我的异步方法来提高CPU使用率吗?

这些都是非常荒谬的性能数字。你根本不是在衡量你认为自己是什么。这不应该超过一个小光点,即缓存文件数据的简单内存到内存拷贝。就像File.Copy()那样。在配备DDR3 RAM的机器上以每秒35 GB的速度运行,因此所需时间不会超过几十毫秒。即使文件没有缓存,或者机器没有足够的RAM,您仍然无法获得这种CPU负载,您的代码将被阻止等待磁盘


您实际看到的是您安装的反恶意软件产品的性能。当它看到程序操纵可执行文件时,它总是把它的内裤包起来

易于验证、禁用或排除,然后重试。

文件。OpenRead(sourceFileName)
相当于
新文件流(sourceFileName, FileMode.Open, FileAccess.Read, FileShare.Read)
这又相当于
公共文件流(sourceFileName,FileMode.Open,FileAccess.Read,FileShare.Read,4096,false)
,也就是说,对于异步I/O,这与
文件.OpenWrite
是等效的

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

因此,它没有得到异步I/O的好处,并且至少浪费了一个线程。您在I/O上有一个额外的线程阻塞,这是您想要避免的。我通常希望async本身的执行速度比sync稍慢(async通常会牺牲一次性速度以获得更好的可伸缩性),但我肯定希望这比在
Task.Run()
中包装整个任务要好一点(如果有的话)

我仍然不认为它会如此糟糕,但也许反恶意软件正在担心写入一个.exe


希望您能够更好地使用异步流复制非exe文件。

File.Copy似乎可以一次性复制整个文件。 使用FileStreams时,默认缓冲区大小为4096字节,因此它将一次复制4kb

我编写了自己的
async
函数,它不仅仅复制文件(它匹配文件大小并进行清理),下面是通过
VPN
跨50mbps宽带链路复制基准文件的结果

使用默认4096字节my
async
文件副本时:

Copy of 52 files via CopyFileAsync() took 5.6 minutes
vs

文件。复制该文件

Copy of 52 files via File.Copy() took 24 secs, 367 ms
当我将缓冲区大小增加到64KB时,我得到以下结果

Copy of 52 files via CopyFileAsync() took 39 secs, 407 ms

底线是默认的缓冲区大小4096对于现代硬件来说太小了,这就是为什么它通过流复制的速度如此之慢。您需要对将要使用的硬件进行基准测试,以确定最佳缓冲区大小,但一般来说,64K对于internet上的网络流量来说是相当最佳的。

这可能与实现
File.Copy
的一些隐藏方式与基于直接流的方法之间的差异有关使用
File.OpenRead
File.OpenWrite
。我怀疑它与sync vs.async有什么关系。正如我所说,我怀疑它与异步有什么关系,而是与它如何执行复制操作有关。您的异步方法从一个流复制到另一个流,而您的同步方法使用
File.Copy
,它将本机Win32操作包装为更低级的方法。你的问题是:我要求编译器在等待IO操作时生成可以利用CPU的代码;为什么我这样做时CPU利用率更高?当你这样说的时候,这个问题就自己回答了,不是吗?你认为异步是为了什么?这是为了在等待IO时增加CPU的使用量。记住,高CPU利用率是好的。人们说它不好,但高CPU是可怕的。机器所有者支付了CPU的费用;它空闲的每一毫秒都是对资源的浪费;正如其他人所说的,可能你从病毒检测程序或其他东西中获得了一些暂时的效果。特别是因为你的程序在等待的时候似乎什么都没做。但一般来说,当使用异步时,您应该期望看到更好的——更高的——CPU利用率。不要暂停CPU;让它继续工作以解决CPU限制的问题。@TheodorZoulias:是的,正如我在评论中提到的,我们想要的是CPU高效地工作以完成CPU限制的工作。虽然我们很挑剔,但我注意到Windows上的.NET线程需要1MB的已提交虚拟地址空间;操作系统足够聪明,在必要时才将其映射到RAM。最好将其视为1MB交换文件,而不是RAM。同意VS“恶意软件”,但是,我想指出的是,任务管理器仍然表明cpu有一定的增加(加上我廉价笔记本电脑的廉价风扇在使用async Wait时更受折磨)。同样是的,File.Copy的实现当然比I manager更好,它使用isAsync参数将异步实现cpu%降低了大约75%。我要看看GitHub上的corefx代码,因为这对于幕后发生的事情还是有点模糊。无论如何,感谢您对测试环境的介绍。“您实际看到的是您安装的反恶意软件产品的性能。”--
Copy of 52 files via CopyFileAsync() took 39 secs, 407 ms