零拷贝

零拷贝

零拷贝是什么

零拷贝包含两个含义:

  • 零:并不是真正意义上的零次,而是比传统的方式更少
  • 拷贝:指数据从一个存储区域复制到另一个存储区域

总结一下:零拷贝是一种 优化技术,用于减少数据在内存和设备之间的复制次数,提高数据传输的效率和性能。

要真正了解零拷贝的含义,首先需要搞懂传统IO的执行流程:

  • 读取:先将数据从外部设备 读取 到内核缓冲区中,再将内核缓冲区的数据 拷贝 到用户缓冲区
  • 写入:先将用户缓冲区设备 拷贝 到内核缓冲区中,再将内核缓冲区的数据 写入 到外部设备中

传统的IO过程经过4次CPU上下文切换

  1. 读取过程中将内核缓冲区的数据拷贝到用户缓冲区时,需要进行系统调用,先从用户态切换到内核态,等内核处理完任务之后,再从内核态切换到用户态
  2. 写入过程中将用户缓冲区数据拷贝到内核缓冲区时,需要进行系统调用,先从用户态切换到内核态,等内核处理完任务之后,再从内核态切换到用户态

传统的IO过程经过4次数据拷贝

  1. 读取过程中,将外部设备数据拷贝到内核缓冲区中(DMA拷贝)
  2. 读取过程中,将内核缓冲区数据拷贝到用户缓冲区中(CPU拷贝)
  3. 写入过程中,将用户缓冲区数据拷贝到内核缓冲区中(CPU拷贝)
  4. 写入过程中,将内核缓冲区数据拷贝到外部设备中(DMA拷贝)

CPU拷贝:用户缓冲区和内核缓冲区之间的数据拷贝通过CPU拷贝实现,CPU通过指令执行将数据从一个地址空间复制到另一个地址空间,如果CPU拷贝涉及到内核空间,则需要进行系统调用从用户态切换到内核态。

DMA拷贝:内核缓冲区和外部设备之间的数据拷贝通过DMA拷贝实现,DMA是一种特殊的硬件技术,允许外部设备直接访问系统的内存,从而实现数据的直接传输。DMA控制器可以在不占用CPU资源的情况下,直接将数据从内存传输到外部设备,或者从外部设备传输到内存。

零拷贝实现方式

IO操作是非常消耗系统性能的,主要是因为IO操作会进行 用户态与内核态的上下文切换内存拷贝,想要提高IO操作的效率,就要 减少 用户态和内核态的上下文切换和内存拷贝的次数。

实现零拷贝主要有以下几种方式:

  • mmap/write 方式
  • sendfile 方式
  • 带有 scatter/gather 的 sendfile 方式
  • splice 方式

mmap/write方式

mmap/write 方式实现零拷贝后的IO操作利用虚拟内存特性,使得内核缓冲区和用户缓冲区共享一内存,read 操作时 不需要将内核缓冲区数据拷贝到用户缓冲区,从而 减少一次CPU拷贝

mmap/write 方式实现零拷贝后的 write 操作并没有减少CPU拷贝,还是需要将数据从用户缓存区拷贝到内核缓冲区中,再将内核缓冲区写入到外部设备。

mmap/write 方式原理:利用操作系统的 Page 来实现文件到物理内存的直接映射,完成映射后对物理内存的操作会被 同步 到硬盘上。

mmap/write 方式缺点:不可靠,写到 mmap 中的数据并没有被真正的写到磁盘,操作系统会再程序主动调用 flush 的时候才把数据真正写到磁盘。

总结:mmap/write 方式实现零拷贝的IO操作 没有减少 用户态和内核态的上下文切换的次数,也 没有减少 write 操作时的CPU拷贝,只减少了 read 操作时的CPU拷贝

sendfile 方式

sendfile 方式:可以直接再内核中将文件数据发送到网络套接字,无需通过用户空间进行数据拷贝,避免数据从用户空间到内核空间的中间拷贝,从而减少了系统调用的次数以及减少一次CPU拷贝。

sendfile缺点:只能用于将文件数据发送到网络套接字,不能适用于其他类型的IO操作

总结:sendfile 方式只有三次数据复制(其中只有一次 CPU拷贝)以及2次用户态和内核态上下文切换

带有 scatter/gather 的 sendfile 方式

带有 scatter/gather 的 sendfile 方式:在内核空间中不做数据复制,而是将内存地址、偏移量记录到相应的内核空间中,其本质和虚拟内存的解决办法思路一致,就是记录内存地址。

带有 scatter/gather 的 sendfile 方式缺点:需要硬件支持

总结:带有 scatter/gather 的 sendfile 方式只有两次数据拷贝(DMA拷贝)和两次用户态和内核态的上下文切换。

splice 方式

splice方式:splice方式和sendfile方式非常类似,应用程序必须拥有两个已经打开的文件描述符,一个表示输入设备,一个表示输出设备。并且允许文件和socket进行数据传输。

零拷贝总结

DMA拷贝依赖于硬件完成,所以对于零拷贝来说也是必须的,零拷贝的优化只能减少CPU拷贝和用户态内核态的上下文切换次数。

CPU拷贝 DMA拷贝 系统调用 上下文切换
传统方法 2 2 read/write 4
mmap/write 1 2 mmap/write 4
sendfile 1 2 sendfile 2
scatter/gather sendfile 0 2 sendfile 2
splice 0 2 splice 0
相关推荐
程序员岳焱6 小时前
Java 与 MySQL 性能优化:Java 实现百万数据分批次插入的最佳实践
后端·mysql·性能优化
麦兜*6 小时前
Spring Boot启动优化7板斧(延迟初始化、组件扫描精准打击、JVM参数调优):砍掉70%启动时间的魔鬼实践
java·jvm·spring boot·后端·spring·spring cloud·系统架构
大只鹅7 小时前
解决 Spring Boot 对 Elasticsearch 字段没有小驼峰映射的问题
spring boot·后端·elasticsearch
ai小鬼头7 小时前
AIStarter如何快速部署Stable Diffusion?**新手也能轻松上手的AI绘图
前端·后端·github
IT_10247 小时前
Spring Boot项目开发实战销售管理系统——数据库设计!
java·开发语言·数据库·spring boot·后端·oracle
bobz9657 小时前
动态规划
后端
stark张宇8 小时前
VMware 虚拟机装 Linux Centos 7.9 保姆级教程(附资源包)
linux·后端
亚力山大抵9 小时前
实验六-使用PyMySQL数据存储的Flask登录系统-实验七-集成Flask-SocketIO的实时通信系统
后端·python·flask
超级小忍9 小时前
Spring Boot 中常用的工具类库及其使用示例(完整版)
spring boot·后端
CHENWENFEIc9 小时前
SpringBoot论坛系统安全测试实战报告
spring boot·后端·程序人生·spring·系统安全·安全测试