学习记录: 深入浅出零拷贝及应用 | 青训营

143 阅读5分钟

第一节:传统文件传输过程

文件传输的常见过程

  • 传统文件传输通常涉及多次拷贝操作。
  • 数据从应用程序缓冲区复制到内核缓冲区,然后再传输到网络设备。

传统拷贝的问题

  • 多次拷贝涉及CPU和内存的频繁交互,造成性能开销。
  • 数据在用户态和内核态之间多次拷贝,影响效率。

Linux传统文件传输过程

image.png

  • 发生了4次用户态与内核态的上下文切换
  • 发生了4次数据拷贝

上下文切换

  • 用户态与内核态
  • 用户空间和内核空间权限不同
  • 数字越小,权限越大
  • 区分用户空间和内核空间的原因:隔离操作系统和应用程序,防止操作系统崩溃。 image.png

CPU拷贝方式

原因:用户态的数据不可信->检查->产生时间窗口->若在窗口期内修改数据则检查无效->需要拷贝进内核空间保证其不变后再检查

I/O轮询

image.png

实现简单,占用CPU全部资源,效率低,时间浪费在等待输入输出的循环检测上。

I/O中断

image.png

一定程度上释放了CPU资源,但是受制于缓冲区的大小,在大数据量传输情况下,CPU会反复中断。

DMA(Direct Memory Access)传输

image.png

简单来说就是加一个中间层,彻底减少了一次CPU拷贝,但是依赖设备硬件支持。

第二节:零拷贝的实现方式

DMA传输

  • 直接内存访问(DMA)允许设备直接访问内存,绕过CPU。
  • 避免了CPU的介入,提高了数据传输速度。

文件描述符传递

  • 文件描述符传递是UNIX系统中实现零拷贝的方式之一。
  • sendfilesplice系统调用是典型的例子。

方案一:mmap(memory map)+write

image.png

mmap本质上是一种进程虚拟内存映射的方法,可以将一个文件或者一段物理内存映射到进程的虚拟内存地址空间,进程可以用指针的方式来读取,不必调用read函数,减少了一次数据拷贝。

方案二:sendfile

image.png

发生在内核空间中,减少了两次上下文切换的时间。

方案三:sendfile+gather

image.png

需要有gatherdma功能,将关于数据的位置和长度等信息de的描述符传递到socket缓冲区中,之后再由dma引擎直接拷贝到设备中。

方案三:splice

image.png 通过管道进行数据传输

所有拷贝实现方式的对比

image.png

第三节:Go语言中的实现

Go语言对零拷贝的支持

  • Go语言通过Fileio.ReaderFrom接口支持零拷贝。
  • 文件和网络操作都可以利用这些接口来实现零拷贝。

使用io.Copy进行拷贝

  • Go语言的io.Copy函数内部优化,可以在合适的条件下实现零拷贝。

第四节:零拷贝的应用

网络传输优化

  • 在网络传输中,零拷贝可以减少数据在用户态和内核态之间的拷贝次数。
  • 改善网络传输性能,降低延迟。

文件读取优化

  • 使用零拷贝技术在文件读取过程中避免中间拷贝。
  • 提升了文件读取操作的效率。

数据库操作优化

  • 零拷贝技术可以优化数据库操作,减少数据在内存中的拷贝次数。
  • 提高了数据库操作的性能。

总结

这份学习笔记简单介绍了零拷贝技术的核心概念和实现方式,以及在不同应用场景中的应用。了解传统文件传输过程和零拷贝技术的区别,以及学会使用零拷贝优化数据传输和文件操作,对于提升系统性能和效率具有重要意义。无论是在网络传输、文件读取还是数据库操作中,零拷贝技术都能够显著改善性能,降低开销。通过对Go语言中的零拷贝实现的了解,你可以在实际开发中更好地应用这一技术,优化代码性能,提升用户体验。

NIO 零拷贝

零拷贝是提升 IO 操作性能的一个常用手段,像 ActiveMQ、Kafka 、RocketMQ、QMQ、Netty 等顶级开源项目都用到了零拷贝。

零拷贝是指计算机执行 IO 操作时,CPU 不需要将数据从一个存储区域复制到另一个存储区域,从而可以减少上下文切换以及 CPU 的拷贝时间。

也就是说,零拷贝主主要解决操作系统在处理 I/O 操作时频繁复制数据的问题。零拷贝的常见实现技术有: mmap+write、sendfile和 sendfile + DMA gather copy 。

下图展示了各种零拷贝技术的对比图:

CPU 拷贝DMA 拷贝系统调用上下文切换
传统方法22read+write4
mmap+write12mmap+write4
sendfile12sendfile2
sendfile + DMA gather copy02sendfile2

可以看出,无论是传统的 I/O 方式,还是引入了零拷贝之后,2 次 DMA(Direct Memory Access) 拷贝是都少不了的。因为两次 DMA 都是依赖硬件完成的。零拷贝主要是减少了 CPU 拷贝及上下文的切换。