零拷贝

3 篇文章 0 订阅
2 篇文章 0 订阅

今日看rocketMQ的设计,读到如何提高broker的发送性能,看到了使用mmp(文件内存映射)的技术,零拷贝,提高了数据从文件到内存再到网络的传输效率。这里有点迷糊,所以详细google了一把。特写下来留作记录。

内容都是来自于已有的东西,都放到后文的参考文档里面,参考文档比我详细多了,有图有解释,有理论,甚至有代码,如果能看参考文档的原文的话,建议看原文。

概念澄清
“零拷贝”:在整个发送数据过程中,数据的复制是必不可少的,这里数据复制分两种类型,一种是CPU参与的一个字节一个字节处理的数据复制,一个是CPU不用参与,通过专有硬件DMA参与的,批量数据复制。自然,不用CPU参与的数据复制性能高。而“零拷贝”所说的拷贝,其实指的是,减少CPU参与的数据拷贝,最好减少到零次,但是各种实现方式里,很多种都只是减少一次两次,并没有直接让CPU参与的数据复制数归零。
为什么要多次拷贝
首先,操作系统是分用户内存空间和内核内存空间的,区分的原因是因为,很多操作系统的指令,安全级别很高,不是随随便便就能调用的,对应的,一部分归操作系统使用的内存空间安全级别也很高,不是随随便便就能访问的,二者都是操作系统才能操作的“内核态”。“内核态”的指令,叫做系统调用,“内核态”的内存空间,成为内核空间。

从硬盘读文件的过程,然后通过网络发送出去,一般的操作,需要经过:

拷贝流程
用户空间->(1. 读文件,系统调用,硬盘文件从硬件缓存复制到内核空间,使用DMA)->内核空间->(2. 用户程序读取文件数据,使用CPU)->用户空间->(3. 通过socket发送文件到网络,系统调用,数据复制回内核空间socket关联的内存,使用DMA)->内核空间->(4. 数据复制到网卡驱动硬件的缓存,系统调用,使用DMA,执行完成).

这样三次切换。更具体和形象的流程,请看参考文档的第一个,里面对这个过程,以及零拷贝优化后的过程,做了详细的图片说明。

每一次切换,数据都需要在内核空间和用户空间之间拷贝。在这个流程中,上述的2,3两步是不经过DMA,需要CPU参与的。

减少拷贝的方式
这里把理论思路和实现方式放到一起说。

mmp 文件内存映射
这是Java NIO实现的一个鼎鼎大名的做法,MappedByteBuffer。思路是将内核空间的数据和用户空间共享,进而减少上述流程中的第2步,内核空间到用户空间的数据拷贝,但是第3步,复制到socket关联的内核空间还是需要的,也就是内核空间之间还要CPU参与,拷贝一次。但是在内核角度看,它不再需要向用户控件拷贝数据了。

sendFile方式
这种方式在Java NIO中也有实现,是FileChannel的transferTo,transferFrom方法。思路是将内核空间内的数据直接拷贝,没用户空间啥事儿,,还是省了上述流程的第2步,但依旧没解决内核空间之间CPU参与的数据拷贝。

优化的sendFile方式
内核空间保留两份数据,之间要相互拷贝是违反直觉的。这个原因在下面的前两个参考文档内都有解答,是因为DMA操作内存要求是整块的内存。内核空间的数据(包括数据和数据对应的描述符)已经不是整块内存存储了,所以不行。

但是这个问题随着内核和硬件的升级也有改善,在新内核,参考文档说是linux kernel 2.4之后,可以支持“零存整取”的DMA,这里“零存整取”是我找的词儿,对应英语是“scatter/gather”,一般被称为“收集拷贝功能”,意为从多个内存块上取数据,然后汇集到另外一块内存块里去。

通过这个特性,在内核空间的一次数据拷贝(上述流程的第3步),也不需要了,内核空间只用保存一份数据,数据的描述符拷贝到网络协议的内核控件去,然后直接通过DMA将二者灌到网卡驱动的缓存里。

参考文档
Zero Copy I: User-Mode Perspective 图文并茂
It’s all about buffers: zero-copy, mmap and Java NIO 结合代码
浅谈 Linux下的零拷贝机制 中文,且补充了上述两个文档的一些内容
--------------------- 
作者:lqadam 
来源:CSDN 
原文:https://blog.csdn.net/lqadam/article/details/85010781 
版权声明:本文为博主原创文章,转载请附上博文链接!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值