什么是零拷贝 维基上是这么描述零拷贝的:零拷贝描述的是CPU不执行拷贝数据从一个存储区域到另一个存储区域的任务,这通常用于通过网络传输一个文件时以减少CPU周期和内存带宽。
零拷贝给我们带来的好处 减少甚至完全避免不必要的CPU拷贝,从而让CPU解脱出来去执行其他的任务 减少内存带宽的占用 通常零拷贝技术还能够减少用户空间和操作系统内核空间之间的上下文切换 零拷贝的实现 零拷贝实际的实现并没有真正的标准,取决于操作系统如何实现这一点。零拷贝完全依赖于操作系统。操作系统支持,就有;不支持,就没有。不依赖Java本身。
广义的实现流程参考图(来源网络):
如果网卡支持 SG-DMA(The Scatter-Gather Direct Memory Access)技术,还可以再去除 Socket 缓冲区的拷贝,这样一共只有 2 次内存拷贝。
java具体如何实现,操作内核态(pageCache)的数据呢:
1.通过MMAP实现,将会经历,3次拷贝: 1次cpu copy,2次DMA copy,以及4次上下文切换(中间,在应用中-用户空间可以操作映射的数据)
2.通过sendfile实现,将会经历,3次拷贝: 1次cpu copy,2次DMA copy,以及2次上下文切换(中间,应用完全不干预数据)
注意:程序进行一次读写=2次上下文切换
扩展:
在某些情况下,PageCache 会不起作用,甚至由于多做了一次内存拷贝,造成性能的降低。高并发场景下,为了防止 PageCache 被大文件占满后不再对小文件产生作用,大文件不应使用 PageCache,进而也不应使用零拷贝技术处理。 高并发场景处理大文件时,应当使用异步 IO 和直接 IO 来替换零拷贝技术