netty 之linux零拷贝

2021/7/27 7:07:25

本文主要是介绍netty 之linux零拷贝,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一、DMA拷贝

Direct Memory Access , 直接内存访问,是一种无须cpu的参与就可以让外设与系统内存进行双向数据传输的硬件机制。

DMA拷贝使系统CPU从实际的IO数据传输中解脱出来,从而大大提高系统吞吐率。在数据传输期间,cpu可以并发的执行其他任务。

img

二、传统IO数据copy

传统的IO数据拷贝需要经历4次copy 和 3次状态切换

四次copy:

1、由硬件 经过DMA ——> 内核buffer

2、内核buffer ——> 用户buffer

3、用户buffer ——> socket buffer

4、socket buffer ——> protocol engine 协议栈

三次切换:

1、用户态 ——> 内核态 (用户上下文 ——> 内核上下文)

2、内核态 ——> 用户态

3、用户态 ——> 内核态

img

三、零拷贝

传统的IO数据传输,经历了4次数据拷贝,而在这里面从 内核缓冲区 到 用户缓冲区 , 再从用户穿冲区到 socket缓冲区,这个过程是没有必要的。零拷贝就是为了解决这个问题 ,零拷贝指的是零CPU拷贝 , DMA拷贝是无法避免的。

实现技术:

1、内存映射 mmap

2、sendFile

3.1、mmap 内存映射

并没有真实的改变传统的IO流程,只不过是使 内核buffer 和 用户buffer 共享了同一块内存,所以相对来讲减少了一次数据拷贝。

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

三次数据copy:

1、由硬件 经过DMA ——> 内核buffer

2、内核buffer(用户buffer 共享了一块内存) ——> socket buffer

3、用户buffer ——> socket buffer

两次切换:

1、用户态 ——> 内核态 (用户上下文 ——> 内核上下文)

2、内核态 ——> 用户态

内存映射共经历了3次数据copy 和 2次状态切换。 并没有实现领copy , 只是减少了copy的次数

img

3.2、sendFile

从linux 内核2.4开始,对于网卡支持SG-DMA技术的情况下,sendFile()系统调用,过程如下:

1、通过DMA将数据拷贝至内核缓冲区

2、缓冲区描述符和数据穿度 copy到socket缓冲区,这个数据量很小,消耗比较低

3、网卡SG-DMA控制器 ,将内核缓冲区copy至 协议栈

img

四、netty的零拷贝

4.1、接收和发送byteBuffer ,使用直接内存进行socket读写,减少了直接内存到堆内存的数据copy

图片

4.2、文件传输调用FileRegion包装的transferTo,直接将文件缓冲区数据发送到目标chuannel , 避免内存copy

4.3、提供了CompositeBytebuf , 将多个buff合并成一个逻辑上的buff

4.4、通过wrap操作将byte数组 、ByteBuf、ByteBuffer 转换为一个byteBuf对象 ,减少内存copy

ByteBuf byteBuf = Unpooled.wrappedBuffer(bytes);

byteBuf对象和 源bytes 共享一块内存,避免copy

4.5、支持slice操作,将一个byteBuf 分解为多个共享一个存储区域的byteBuf,避免内存copy



这篇关于netty 之linux零拷贝的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程