Netty之NIO零拷贝

零拷贝:从操作系统角度说是没有cpu拷贝。

零拷贝不仅带来更少的数据复制,还带来其他的性能优势,例如更少的上下文切换,更少的cpu缓存伪共享以及无cpu校验和计算。

java程序中,常用的零拷贝是:内存映射(mmap)和sendFile

NIO零拷贝使用方式:transferTo

java 本身并不具备 IO 读写能力,因此 read 方法调用后,要从 java 程序的用户态切换至内核态,去调用操作系统(Kernel)的读能力,将数据读入内核缓冲区。这期间用户线程阻塞,操作系统使用 DMA(Direct Memory Access)来实现文件读,其间也不会使用 cpu

内核态切换回用户态,将数据从内核缓冲区读入用户缓冲区(即 byte[] buf),这期间 cpu 会参与拷贝,无法利用 DMA

调用 write 方法,这时将数据从用户缓冲区(byte[] buf)写入 **socket 缓冲区**,cpu 会参与拷贝

接下来要向网卡写数据,这项能力 java 又不具备,因此又得从用户态切换至内核态,调用操作系统的写能力,使用 DMA 将 socket 缓冲区的数据写入网卡,不会使用 cpu

用户态与内核态的切换发生了 3 次,这个操作比较重量级

数据拷贝了共 4 次

先看下传统的IO数据读写代码如下:

传统IO模型:

注:DMA(direct memory access)直接内存拷贝不使用CPU

一、mmap优化

mmap通过内存映射,将文件映射到内核缓冲区,同时用户空间可以共享内核空间的数据。在进行网络传输的时候,减少内核空间到用户空间的拷贝次数。

二、sendFile优化

linux2.1版本提供了sendFile函数,数据根本不经过用户态,直接从内核态缓冲区进入到socket buffer,同时由于和用户态完全无关,就减少了一次上下文切换。

linux2.4做了进一步优化,避免从内核缓冲区拷贝到socket buffer的操作,直接拷贝到协议栈,从而再一次减少数据拷贝。

三、mmap和sendFile的对比

1、mmap适合小数据量的读写,sendFile适合大文件的传输

2、mmap需要4次上下文切换,3次数据拷贝;sendFile需要3次上下文切换,最少2次数据拷贝

3、sendFile可以使用DMA方式,减少cpu拷贝。mmap则不能

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值