Netty 系列 二 NIO 零拷贝

传统的IO操作流程

 

这里好多人说有4次上下文的切换,这个我感觉不是很重要,次数主要是看开始的状态和最后结束的状态,上图中程序在数据到网络时就结束了,其实这之后还有一次内核到进程的切换,开始和结束都是在进程状态

 

NIO实现零拷贝方式一transferTo()

这个流程涉及到3次数据的拷贝 内核态与用户态上下文的切换次数比传统的模式少了2次

直接在内核态完成数据的传输 数据不进入进程 在操作系统的角度来看,数据只是在自己这里传输没有拷贝到进程内所以叫做零拷贝.

NIO 中的 FileChannel 对象有一个

transferTo(long position, long count,WritableByteChannel target) 利用这个方法实现零拷贝
     

这个方法是依赖底层的操作系统 linux sendFile()方法来实现的

这种方式适用场景 : 大文件的传输  且 文件不需要修改直接传递 

 

NIO实现零拷贝方式二   mmap 内存映射

 

3次数据的拷贝 用户态到内核态的转化跟传统io没有区别 只是少了一次数据的拷贝

直接内存(mmap技术)将文件直接映射到内核空间的内存,返回一个操作地址(address),它解决了文件数据需要拷贝到JVM才能进行操作的窘境。而是直接在内核空间直接进行操作,省去了内核空间拷贝到用户空间这一步操作。

NIO中用来做内存映射的对象

HeapByteBuffer

在调用ByteBuffer.allocate()时使用。 它被称为堆,因为它保存在JVM的堆空间中,因此你可以获得所有优势,如GC支持和缓存优化。 但是,它不是页面对齐的,这意味着如果你需要通过JNI与本地代码交谈,JVM将不得不复制到对齐的缓冲区空间。

DirectByteBuffer

在调用ByteBuffer.allocateDirect()时使用。 JVM将使用malloc()在堆空间之外分配内存空间。 因为它不是由JVM管理的,所以你的内存空间是页面对齐的,不受GC影响,这使得它成为处理本地代码的完美选择。 然而,你要C程序员一样,自己管理这个内存,必须自己分配和释放内存来防止内存泄漏。

MappedByteBuffer

在调用FileChannel.map()时使用。 与DirectByteBuffer类似,这也是JVM堆外部的情况。 它基本上作为OS mmap()系统调用的包装函数,以便代码直接操作映射的物理内存数据。
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值