关于零拷贝

什么是DMA

在了解零拷贝之前,我们先要了解一个概念叫做DMA,详情百度-DMA

Direct Memory Access,直接存储器访问
CPU将地址总线、数据总线、有关控制的总线的数据权交给DMA引擎

它允许不同速度的硬件装置来沟通,而不需要依赖于 CPU 的大量中断负载。否则,CPU 需要从来源把每一片段的资料复制到暂存器,然后把它们再次写回到新的地方。在这个时间中,CPU 对于其他的工作来说就无法使用(cpu与DMA分时使用内存)

  1. 停止CPU访问内存;
  2. 周期挪用;
  3. DMA与CPU交替访问内存

普通拷贝

在这里插入图片描述
普通拷贝涉及到4次数据拷贝、4次上下文切换

  1. read 调用导致用户态到内核态的一次变化,同时,第一次复制开始:DMA(Direct Memory Access,直接内存存取,即不使用 CPU 拷贝数据到内存,而是 DMA 引擎传输数据到内存,用于解放 CPU) 引擎从磁盘读取 index.html 文件,并将数据放入到内核缓冲区。
  2. 发生第二次数据拷贝,即:将内核缓冲区的数据拷贝到用户缓冲区,同时,发生了一次用内核态到用户态的上下文切换。
  3. 发生第三次数据拷贝,我们调用 write 方法,系统将用户缓冲区的数据拷贝到 Socket 缓冲区。此时,又发生了一次用户态到内核态的上下文切换。
  4. 第四次拷贝,数据异步的从 Socket 缓冲区,使用 DMA 引擎拷贝到网络协议引擎。这一段,不需要进行上下文切换。
  5. write 方法返回,再次从内核态切换到用户态。

mmap

mmap 通过内存映射,将文件映射到内核缓冲区,同时,用户空间可以共享内核空间的数据。这样,在进行网络传输时,就可以减少内核空间到用户控件的拷贝次数。

在这里插入图片描述

mmap拷贝时共设计3次数据拷贝、4次上下文切换

  1. DMA引擎传输数据到内核缓冲区(用户态->内核态)
  2. 此时内核缓冲区与用户缓冲区共享数据(内核态->用户态)
  3. 调用write方法,将用户缓冲区(共享)的数据拷贝到Socket缓冲区(用户态->内核态)
  4. 数据异步的从Socket缓冲区使用DMA引擎拷贝到网络协议引擎
  5. write方法返回(内核态->用户态)

sendFile

Linux2.1版本提供了sendFile函数,拷贝数据时不经过用户态,直接将数据从内核缓冲区拷贝到Socket缓冲区。
在这里插入图片描述
拷贝时共涉及3次数据拷贝、3次上下文切换

  1. DMA引擎传输数据到内核缓冲区(用户态->内核态)
  2. 调动wirte方法直接从内核缓冲区进入socket(内核态)
  3. socket->网络协议栈
  4. wirte方法返回(内核态->用户态)

Linux2.4版本中可以直接从内核缓冲区拷贝到网络协议栈从而再一次减少了一次拷贝.
在这里插入图片描述

  1. 使用 DMA 引擎从文件拷贝到内核缓冲区
  2. 从内核缓冲区将数据拷贝到网络协议栈;内核缓存区只会拷贝一些 offset 和 length 信息到 SocketBuffer,基本无消耗。
  3. socket->网络协议栈

不是说零拷贝吗?为什么还是要 2 次拷贝?

首先我们说零拷贝,是从操作系统的角度来说的。因为内核缓冲区之间,没有数据是重复的(只有 kernel buffer 有一份数据,sendFile 2.1 版本实际上有 2 份数据,算不上零拷贝)。
例如我们刚开始的例子,内核缓存区和 Socket 缓冲区的数据就是重复的。

而零拷贝不仅仅带来更少的数据复制,还能带来其他的性能优势,例如更少的上下文切换,更少的 CPU 缓存伪共享以及无 CPU 校验和计算。

mmap 和 sendFile 的区别。

mmap 适合小数据量读写,sendFile 适合大文件传输。
mmap 需要 4 次上下文切换,3 次数据拷贝;sendFile 需要 3 次上下文切换,最少 2 次数据拷贝。
sendFile 可以利用 DMA 方式,减少 CPU 拷贝,mmap 则不能(必须从内核拷贝到 Socket 缓冲区)。

在这个选择上:rocketMQ 在消费消息时,使用了 mmap。kafka 使用了 sendFile。

总结

使用mmap + write方式

优点:即使频繁调用,使用小块文件传输,效率也很高

缺点:不能很好的利用DMA方式,会比sendfile多消耗CPU,内存安全性控制复杂,需要避免JVM Crash问题。

使用sendfile方式

优点:可以利用DMA方式,消耗CPU较少,大块文件传输效率高,无内存安全新问题。

缺点:小块文件效率低于mmap方式,只能是BIO方式传输,不能使用NIO。RocketMQ选择了第一种方式,mmap+write方式,因为有小块数据传输的需求,效果会比sendfile更好。

参考

Zero Copy I: User-Mode Perspective

RocketMQ 开发指南

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值