Netty学习——NIO的零拷贝

1 篇文章 0 订阅
NIO的零拷贝

零拷贝(zero-copy)是一种目前只有在使用 NIO 和 Epoll 传输时才可使用的特性。零拷贝 指不是不拷贝,而且不是使用CPU拷贝。带来了更少的数据复制,更新的上下文切换,更少的CPU缓存等

详细参考 NIO和零拷贝

  1. 传统I/O拷贝
    在这里插入图片描述
    当执行read() 和 write() 操作的时候 如何使用变化的

    1. (切换)当执行read操作的时候,会从 用户态(user context) 切换成 内核态(kernel context)
    2. (拷贝)然后通过DMA(Direct memory access,直接内存拷贝,不使用CPU)拷贝,被数据从硬盘(hard drive) 拷贝到 内核缓冲区(kernel buffer)
    3. (切换)系统在从 内核态(kernel context) 切换成 用户态(user context)
    4. (拷贝)在 使用 CPU 把数据从 内核缓冲区(kernel buffer) 拷贝到 用户缓冲区(user buffer),数据在用户缓冲区进行修改。
    5. (拷贝)在 使用 CPU 把数据从 用户缓冲区(user buffer)拷贝到 Socket缓冲区(Socket buffer)
    6. (切换)系统在从 用户态(user context) 切换成 内核态(kernel context)
    7. (拷贝)在使用DMA从 Socket缓冲区(Socket buffer) 拷贝到协议栈(protocol engine)
    8. (切换)系统在从 内核态(kernel context) 切换成 用户态(user context)
      传统IO 一共进过了 4次切换,4次拷贝,两次DMA拷贝 两次CPU拷贝
  2. 内存映射方式I/O (mmap优化)

mmap 通过内存映射优化,将文件映射到内核缓冲区,同时用户空间可以共享内核的数据,这样就减少了一次CPU拷贝 。

也就是少了传统I/O拷贝中的第4步,不在 使用 CPU 把数据从 内核缓冲区(kernel buffer) 拷贝到 用户缓冲区(user buffer)。因为内核缓冲区和用户缓冲区的数据是共享的
在这里插入图片描述
内存映射方式一共进过了 4次切换,3次拷贝,两次DMA拷贝 一次CPU拷贝

  1. 内核空间内部传输I/O (sendFile)

    Linux 2.1 版本提供了sendFile函数,其基本原理是:数据根本不进过用户态,直接从内核缓冲区进入到 SocketBuffer。同时因为和用户态无关系,所以就减少了一次上下文切换
    在这里插入图片描述

    1. (切换)sendfile()的时候,会从 用户态(user context) 切换成 内核态(kernel context)
    2. (拷贝)然后通过DMA(Direct memory access,直接内存拷贝,不使用CPU)拷贝,被数据从硬盘(hard drive) 拷贝到 内核缓冲区(kernel buffer)
    3. (切换)系统在从 内核态(kernel context) 切换成 用户态(user context)
    4. (拷贝)在 使用 CPU 把数据从 内核缓冲区(kernel buffer)拷贝到 Socket缓冲区(Socket buffer)
    5. 在使用DMA从 Socket缓冲区(Socket buffer) 拷贝到协议栈(protocol engine)

内核空间内部传输I/O (sendFile) 进行了 2次切换,3次拷贝,两次DMA拷贝 一次CPU拷贝

  1. 升级版-内核空间内部传输I/O (sendFile优化)
    在这里插入图片描述

    1. (切换)sendfile()的时候,会从 用户态(user context) 切换成 内核态(kernel context)
    2. (拷贝)然后通过DMA(Direct memory access,直接内存拷贝,不使用CPU)拷贝,被数据从硬盘(hard drive) 拷贝到 内核缓冲区(kernel buffer)
    3. (切换)系统在从 内核态(kernel context) 切换成 用户态(user context)
    4. (拷贝 可忽略不计)在 使用 CPU 把少量关键数据从 内核缓冲区(kernel buffer)拷贝到 Socket缓冲区(Socket buffer)
    5. (拷贝)在使用DMA从 内核缓冲区(kernel buffer) 拷贝到协议栈(protocol engine)

    升级版-内核空间内部传输I/O (sendFile) 进行了 2次切换,2次拷贝,两次DMA拷贝 一次CPU拷贝可忽略不计

  2. 总结

    • mmap 适合小数据量的读写,sendFile适合大文件传输
    • mmap需要4次上下文切换,3次数据拷贝。而sendFile只需要3次上下文切换,2次数据拷贝
    • sendFile利用DMA方式,较少了CPU拷贝。而mmap则必须要走socker缓冲区
  3. 举例

    	// 直接使用了transferTo()进行通道间的数据0拷贝
    	fileChannel.transferTo(0, fileChannel.size(), socketChannel);
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值