概述
零复制(英语:zero-copy;也叫做零拷贝)技术是指计算机执行操作时,cpu
不需要先将数据从某处内存复制到另外一个特定区域。这种技术通常通过网络传输文件时节省CPU
周期和带宽。
传统IO传输模型
传统IO分析
在Java当中IO存在这三个对象,一个是user space
用户空间,一个是kernel space
内核空间,还有一个是hardware
磁盘对象
- 当
jvm
发起了一次读取事件时,首先会通过内核空间对磁盘进行一次DAM的IO操作,将磁盘中的数据写入到内核空间当中。 - 再将内核空间中的数据进行一次拷贝,将数据拷贝到用户空间当中
- 当
jvm
发起一次写入事件时,先将用户空间中的数据拷贝到内核空间中 - 再通过内核空间将数据写入到磁盘中
这种拷贝我们进行了四次拷贝
和四次上下文切换
,这种拷贝和上下文切换极大的消耗时间和性能
网络IO改进版本
其实这种模型他也是一种零拷贝,但是它在内核当中多做了一步拷贝过程,将内核空间中的数据拷贝到了socket buffer
当中,这是这个模型的一个大缺陷。
它总共进行了两次上下文的切换
,和三次拷贝过程
真正的零拷贝
- 在
JVM
发起读取文件请求时,将文件操作完全交给了系统内核来操作 - 通过
DMA
拷贝将数据读取到内核空间当中,再将内核当中的数据头信息(比如:文件名称,文件长度等信息拷贝到socket Buffer中 当然这个过程时间我们可以忽略不记)再将kemel buffer
中的数据通过文件引擎,配合socket buffer
中的信息一起写入到文件磁盘当中。 - 当然这种拷贝需要系统支持
scatter-and-gather
Java NIO中实现零拷贝的几种方式
DirectByteBuffer
在调用ByteBuffer.allocateDirect()
方法获得。JVM将使用malloc()
方法在堆内存之外分配内存空间。因为它不是由JVM
管理,所以你的内存空间是页面对其的,不受GC影响 ,这使得它成为处理本地代码的完美选择。然而你需要像C程序员一样,自己管理内存。
MappedByteBuffer
零拷贝是操作系统底层的一种实现,我们在网络编程中,利用操作系统这一特性,可以大大提高数据传输的效率。这也是目前网络编程框架中都会采用的方式,理解好零拷贝,有助于我们进一步学习Netty等网络通信框架的底层原理。