NIO与零拷贝

3 篇文章 0 订阅

JAVA后端开发知识总结(持续更新…)


NIO与零拷贝



一、零拷贝

1.1 概述

零拷贝

  从OS的角度来看,文件的传输不存在CPU的拷贝,只存在DMA拷贝。在内核缓冲中,不存在重复数据(即只有kernel buffer中存在数据)。在Java程序中,常用的零拷贝有 mmap(内存映射)和 sendFile。零拷贝是网络编程和性能优化的关键。

  零拷贝不仅带来更少的数据复制,还能减少线程的上下文切换,减少CPU缓存伪共享以及无CPU校验和计算。

1.2 拷贝方式

  • 传统IO读写

4次拷贝,4次上下文(内核态和用户态)切换。

  • mmap优化
  • mmap通过内存映射,将文件映射到内核缓冲区,同时,用户空间可以共享内存空间的数据。
  • 即,用户缓冲区和内核读缓冲区的内存地址为同一内存地址,也就是说不需要CPU再把数据从内核读缓冲区复制到用户缓冲区。
  • 在进行网络传输时,就可以减少内核空间到用户空间的拷贝次数。
  • 需要进行4次上下文切换,3次拷贝。
  • 适合小数据量的读写。
  • sendFile优化
  • Linux2.1 版本提供了 sendFile 函数,其基本原理如下:数据不经过用户态,直接从内核缓冲区进入到SocketBuffer,同时,由于和用户态完全无关,就减少了一次上下文切换。
  • Linux 在 2.4 版本做了一些修改,避免了从内核缓冲区拷贝到 SocketBuffer 的操作,直接拷贝到协议栈,从而再一次减少了数据拷贝。
  • 在 2.4 版本中其实有一次CPU拷贝,kernel buffer -> socket buffer。但是拷贝的信息很少,只拷贝了数据的长度、偏移量等关键信息,消耗低,可以忽略不计。
  • 需要3次上下文切换和最少2次拷贝。
  • 适合大文件的传输。

Linux 2.1
在这里插入图片描述

Linux 2.4
在这里插入图片描述

NIO零拷贝

  • transferTo 底层使用到零拷贝:
  • 通过系统调用sendfile()(当然这是Linux中的系统调用,Windows中系统调用有所不同)。
  • 在Linux下,一个 transferTo 方法就可以完成传输。
  • 在Windows 下一次调用 transferTo 只能发送 8M数据,就需要分段传输文件。

参考文档

《JavaNIO和零拷贝(Zero Copy)》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值