Java NIO——Zero-copy
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java NIO——Zero-copy,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2523字,纯文字阅读大概需要4分钟。
内容图文
技术介绍
零复制(英语:Zero-copy;也译零拷贝)技术是指计算机执行操作时,CPU不需要先将数据从某处内存复制到另一个特定区域,从而可以减少上下文切换及CPU的拷贝时间,通常用于通过网络传输文件时节省CPU周期和内存带宽。
假如我们要实现这样的功能:将文件中的字节复制到套接字中
read(file, tmp_buf, len);
write(socket, tmp_buf, len);
传统实现方式
过程如下
-
read()函数调用导致了一次用户态到内核态的上下文切换。系统内部的sys_read()调用被用于把数据读取出来。第一次复制是以DMA引擎的方式呈现的,DMA把数据读取出来并存入kernel address space buffer。
-
数据被读取返回后导致了上下文从内核态切换到用户态,现在数据存在user address space buffer中。
-
send()操作再次把上下文从用户态切换到内核态。并且数据被从用户缓存拷贝到kernel address space buffer中。
-
send()操作返回,这时又从内核态返回到用户态,并且发生最后一次数据拷贝,数据从kernel buffer拷贝到protocol engine中。
这个过程当中一共出现了4次数据拷贝和4次用户态-内核态用户态-内核态上下文切换(每一次系统调用都是两次上下文切换:用户态->内核态->用户态)。
Linux 2.4之前的底层实现
仔细检查上面的流程,其实第二次和第三次复制是不必要的(从buffer到应用程序、从应用程序到buffer),应用程序并没有改变数据内容,只是将其返回到socket buffer中。Java中提供了transferTo()方法,可以让你实现数据直接从read buffer输到 socket buffer。
transferTo() 方法将数据从一个文件channel传输到一个可写channel。在内部它依赖于操作系统对 Zero-copy 的支持,在UNIX/Linux系统上, transferTo() 实际会调用 sendfile() 这个系统函数,将数据从一个文件描述符传输到另一个。
下图展示了使用 transferTo()时的数据拷贝情况
过程如下
-
transferTo()调用使文件内容通过DMA的方式被复制到read buffer。然后将数据复制到与输出的socket相关的buffer中。
-
第三次复制发生在DMA将数据复制到protocol engine。
这已经有了改进,我们已将上下文切换次数从四次减少到两次,并将数据拷贝的次数从四次减少到三次(其中只有一次涉及CPU操作)
Linux 2.4之后的底层实现
过程如下
-
transferTo方法调用使文件内容通过DMA引擎被复制到kernel buffer
-
无数据被复制到socket buffer。只是描述了需要被写入的数据的位置和长度。DMA引擎直接把数据从kernel buffer复制到protocol engine
现在整个过程只有两次上下文切换和两次数据拷贝。
在内核为2.4或者以上版本的linux系统上,socket缓冲区描述符将被用来满足这个需求。这个方式不仅减少了内核用户态间的切换,而且也省去了那次需要cpu参与的复制过程。
从用户角度来看依旧是调用transferTo()方法,但是其本质发生了变化:
调用transferTo方法后数据被DMA从文件复制到了内核的一个缓冲区中。
数据不再被复制到socket关联的缓冲区中了,仅仅是将一个描述符(包含了数据的位置和长度等信息)追加到socket关联的缓冲区中。DMA直接将内核中的缓冲区中的数据传输给协议引擎,消除了仅剩的一次需要cpu周期的数据复制。
内容总结
以上是互联网集市为您收集整理的Java NIO——Zero-copy全部内容,希望文章能够帮你解决Java NIO——Zero-copy所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。