0拷贝浅析
发布日期:2021-06-29 13:15:36 浏览次数:2 分类:技术文章

本文共 1904 字,大约阅读时间需要 6 分钟。

0拷贝浅析

 

话不多说,先上维基

 

 

翻译一下吧:

“零复制”描述了计算机操作,其中CPU不执行将数据从一个存储区域复制到另一个存储区域的任务。 通过网络传输文件时,通常用于节省CPU周期和内存带宽。

 

再看看详细描述

 

 

零组件版本的操作系统元素(例如设备驱动程序,文件系统和网络协议栈)极大地提高了某些应用程序的性能,并更有效地利用了系统资源。通过允许CPU继续执行其他任务,同时在计算机的另一部分中并行进行数据复制,可以提高性能。同样,零拷贝操作减少了用户空间和内核空间之间耗时的模式切换次数。系统资源的利用效率更高,因为如果其他较简单的系统组件可以执行复制操作,则使用相对复杂的CPU来执行大量的复制操作(这是一项相对简单的任务)非常浪费。​例如,读取文件然后通过传统方式通过网络发送文件,每个读/写周期需要两个数据副本和两个上下文切换。这些数据副本之一使用CPU。通过零拷贝发送相同的文件将上下文切换减少到两个,并消除所有CPU数据拷贝。​零拷贝协议对于网络链接容量接近或超过CPU处理能力的高速网络尤其重要。在这种情况下,CPU几乎将所有时间都花在复制传输的数据上,因此成为了瓶颈,将通信速率限制在链路容量以下。行业中的经验法则是,处理一位输入的数据大约需要一个CPU时钟周期。

通过阅读上面的原理:可以看到两个关键字“用户空间”、“内核空间”;

上述描述到,在“用户空间”与“内核空间”之间的模式切换是会消耗资源的,那么当文件传输的过程中,需要将文件本身资源,从磁盘中拷贝至内核内存中,再由内存中拷贝至用户内存中,此处用户内存,指程序内存,比如jvm的堆内存,然后程序对其作出处理,然后再将该资源通过socket传输出去。看着是正常的操作,但是是一种低效的操作流程。

 

为何低效呢?我们细细分析一下:(此处举例,一个完整的文件发送操作,先读后写)

(1)首先,读:由用户态切换至内核态,然后将资源的内容,从磁盘中拷贝至内核模式下的buffer中(DMA copy);

(2)在将其内核内存中的数据拷贝至用户内存中(CPU copy)(比如用户程序中的用户内存);

(3)然后,写:将用户内存中的资源复制值内核内存中的buffer中(CPU copy);

(4)然后将该资源由内核内存中复制至网络设备中传输(DMA copy)。这才发出去;

 

我们可以一步步流程看出,总共复制了4次,这就是最初始的拷贝资源传递的流程;并且随着用户态和内核态的切换,都会影响资源的占用;

 

 

那么sendFile()是如何优化的呢?

只需要2步拷贝(注意:此处会有误解,0拷贝并不是指0次拷贝,而是指用户内存和内核内存之间存在0次拷贝);

(1)首先将磁盘中的资源拷贝至内核内存(DMA)

(2)然后应用程序通过transferTo发送指令,实现内核内存拷贝基本数据至socket buffer中

(3)然后直接将资源拷贝至网络设备缓冲区(DMA)实现完整发送流程

所以本质来说,linux只实现了三次拷贝,且三次拷贝都是在内存中实现,并没有接触到用户内存,用户内存中只存在一个映射关系(此处引申一个JVM概念:直接内存);

 

上下文切换由4次减少至2次,拷贝次数由4减少至3次。

那么关于上述的拷贝优化描述应该很清晰,此处不再赘述。

 

 

 

我们聊一聊进一步优化:

在linux2.4版本开始,socket buffer做了优化调整,也就是当cpu内存将资源拷贝至socketbuffer中,至拷贝一些元数据相关,也就是一些资源长度,资源信息等描述符数据拷贝至了socket buffer中。而DMA引擎就直接绕过了socket buffer了,直接拷贝至协议引擎中,从而又减少了一次内存拷贝过程。(此处协议引擎指一些网络设备);

 

 

那么对于此处优化,到底提升多少呢?笔者没有做相关的实际测试,借用网络上其他大佬的测试,可以看出上GB的资源,发送时间耗时基本提升至原来的 4/9,也就是传输时间减少了至少一半,对于小文件,几MB的,基本上降低至原来的1/3以上。

总结:transferTo()极大的提升了IO传输过程中的执行效率。

可见而知,如果减少了用户态与内核态之间的切换次数、资源在CPU上拷贝次数,可以释放很多的cpu占用,极大的提升了性能;

 

 

拓展:

DMA(Direct Memory Access,直接存储器访问) 是所有现代的重要特色,它允许不同速度的硬件装置来沟通,而不需要依赖于的大量中断负载。否则,CPU 需要从来源把每一片段的资料复制到,然后把它们再次写回到新的地方。在这个时间中,CPU 对于其他的工作来说就无法使用。

 

 

转载地址:https://changemax.blog.csdn.net/article/details/112789907 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:记一次线上环境 redis偶尔连接超时报错 解决
下一篇:关于将一个复杂的Java对象 在 网络传输中,导致类型擦除的问题解决

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2024年04月21日 10时32分17秒