到底什么是零拷贝?

        在一些中间件中,比如:Kafka、Netty、Rocketmq、Nginx,总是频繁的提到零拷贝技术,而与零拷贝关联的词汇往往是高性能,那么我们就来看看零拷贝怎么做到高性能。

        在讲零拷贝之前,我们先明确几个概念:

  • 零拷贝使用中的内存模型,比如网络IO模型

 

磁盘的数据先进入文件缓冲区,然后进入应用程序的缓冲区,当应用程序处理完相关的数据后,会把数据发送到socket缓冲区。这里注意一下内核态和用户态的切换。

  • DMA技术

直接存储器访问。CPU是计算机的大脑,当需要把数据从一个设备拷贝到另一个设备时,早期的计算机需要CPU参与,造成CPU中断。我们知道IO操作是很耗费时间的,CPU长时间的不可用会造成其他程序无法响应。而数据的拷贝和传输是一个耗时但是不那么复杂的操作。所以就有了DMA技术,建立自己的通路去传输数据而不需要CPU的参与,从而把CPU解放出来。

了解完以上概念之后我们来看一下一个典型的场景:把磁盘上的数据加载的应用程序后,应用程序处理加工,最后通过网络发送数据。

基本流程如下:

总计四次拷贝:

两次DMA拷贝,两次CPU拷贝。 

总计四次用户/内核态切换:

用户读取数据:用户态切换到内核态

数据读取完:内核态切换到用户态

用户发送数据:用户态切换到内核态

数据发送完毕:内核态切换到用户态

那么我们来看下Linux等操作系统中的零拷贝技术:

  • MMAP

 将磁盘上的文件位置和应用程序缓冲区进行映射,根据映射关系将文件直接拷贝到应用程序缓冲区。在读取阶段只进行了一次拷贝。

总计三次拷贝:

两次DMA拷贝,一次CPU拷贝

总计四次用户/内核态切换

  • SendFile

 当磁盘文件dma拷贝到文件缓冲区中后,CPU可以直接将内容拷贝到socket buffer。注意,这里如果dma设备支持,可以将文件的起始位置和大小直接传递给协议引擎,这样就少了一次拷贝,但是需要dma硬件设备的支持。

总计三次拷贝:

两次DMA拷贝,一次CPU拷贝

总计两用户/内核态切换:

发送阶段用户态切换到内核态,发送完毕后内核态切换回用户态。

  • Slice

linux2.6之后,可以不用硬件支持,原理是文件缓冲区和socket buffer直接建立管道pipeline,也就是共享内存区域。

这样经过最后一次cpu拷贝也省去了,最终经历了2次上下文切换和2次DMA拷贝。

java生态中的零拷贝技术:

Kafka:

主要有两点:

  1. Producer生产的数据存到broker
  2. Consumer从broker读取数据

对于1,broker使用mmap文件映射,再加上顺序写入,可以快速把消息保存到磁盘

对于2,broker使用sendfile,可以快速读取磁盘文件,发送到socket buffer。

在加上顺序读写,效率非常高。

NIO:

MappedByteBuffer,底层使用linxu的mmap()实现。

FileChannel,transferTo 和 transferFrom 两个方法,使用sendFile可以直接拷贝到socketBuffer。

Netty:

ByteBuf支持slice 操作,因此可以将ByteBuf分解为多个共享同一个存储区域的ByteBuf,避免了内存的拷贝。

Netty 的通过FileRegion包装的FileChannel.tranferTo实现文件传输。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值