高效IO之零拷贝技术

简介: 高效IO之零拷贝技术

高效IO之零拷贝技术

这种技术是出现在 IO 操作上的, IO 操作会大量消耗 CPU 的性能,为什么说 IO 操作很容易成为性能瓶颈呢,每一个的 IO 操作都会涉及到操作系统的内核空间和用户空间的转换,真正执行的 IO 操作实际上是在操作系统的内核空间进行。无论是 文件IO ,还是 网络IO ,最后都可以统一为用户空间和内核空间数据的交换。计算机中内存和 CPU 都是非常稀有的资源,应该尽可能提高这些资源的使用效率。 IO 操作经常需要与磁盘就行交互,所以 IO 操作相比于 CPU 的速度要慢好几个数量级。利用这两者之间的速度差异,就可以实现不同种类的 IO 方式,也就是俗称的 IO模型

常见IO模型

常见 IO模型 也就是同步和异步的

同步IO模型

  • 阻塞 BIO
  • 非阻塞 NIO
  • IO多路复用:poll、epoll、select
  • 信号驱动IO

异步IO模型

  • Linux AIO

这里说明一下:IO模型 虽然有些号称是不阻塞的,那是指在等待数据就绪的过程中是不阻塞的,但是在接收数据的时候,依然还是阻塞的AIO 是这些 IO 模型中真正实现完全不阻塞, AIO 在被调用之后直接返回,连接收数据的阶段也是非阻塞的,等到数据接收完成之后,内核才会返回一个通知,也就是说当用户进程接收到通知时,数据已经接收完成。在 Linux 中提供了 AIO 的实现,但是实际上使用的并不多,更多还是使用独立的异步 IO 库,比如 libeventlibevlibuv

一般文件操作是咋样?

场景:将一个文件复制到另一个文件

public static void copyFileByStream(File source, File dest) throws
        IOException {
    try (InputStream is = new FileInputStream(source);
         OutputStream os = new FileOutputStream(dest);){
        byte[] buffer = new byte[1024];
        int length;
        while ((length = is.read(buffer)) > 0) {
            os.write(buffer, 0, length);
        }
    }
 }

正常我们就可以编写出如上代码,但是这些代码在操作系统上执行了哪些动作呢?如果不知道原理是没法找出优化点的,所以我们要探索一下拷贝的实现机制

拷贝实现机制分析

首先,你需要理解用户态空间(User Space)内核态空间(Kernel Space),这是操作系统层面的基本概念,操作系统内核、硬件驱动等运行在内核态空间,具有相对高的特权;而用户态空间,则是给普通应用和服务使用。

当我们使用输入输出流进行读写时,实际上是进行了多次上下文切换,比如应用读取数据时,先在内核态将数据从磁盘读取到内核缓存,再切换到用户态将数据从内核缓存读取到用户缓存。

写入操作也是类似,仅仅是步骤相反,你可以参考下面这张图。

流程:

  • 将需要拷贝的数据拷贝到内核空间中,于是产生了一次用户空间到内核空间的上下文切换
  • 数据读取后返回后导致上下文从内核空间切换到了用户空间(这两步完成了读操作)
  • 将读取的数据要写入到IO设备中,执行写入操作把用户空间切换到内核空间上下文中,并将数据写入到内核空间
  • 将内核数据写入到目标IO设备中,然后写入操作返回结果,从内核空间返回到用户空间上下文中(这两步完成了写操作)

这个过程当中一共出现了4次数据拷贝和4次用户态-内核态的上下文切换(每一次系统调用都是两次上下文切换:用户态->内核态->用户态)。

所以,这种方式会带来一定的额外开销,可能会降低 IO 效率。

而基于 NIO transferTo 的实现方式,在 LinuxUnix 上,则会使用到零拷贝技术数据传输并不需要用户态参与,省去了上下文切换的开销和不必要的内存拷贝,进而可能提高应用拷贝性能。注意, transferTo 不仅仅是可以用在文件拷贝中,与其类似的,例如读取磁盘文件,然后进行 Socket 发送,同样可以享受这种机制带来的性能和扩展性提高。

transferTo 的传输过程是:

仔细检查之前的流程,其实第二次和第三次的复制没有必要(就是将在内核空间中的数据返回到用户空间和用户空间数据写入到内核空间中)

流程改变为:

  • 从用户态切换到内核态 transferTo() 调用使文件内容通过 DMA 的方式被复制到内核空间中。DMA 引擎直接把数据从内核空间 复制到目标IO设备
  • 任务完成之后,切换回来。

可以理解为内核态空间与磁盘之间的数据传输,不需要再经过用户态空间,只需要2次切换、2次拷贝。

目录
相关文章
|
7月前
|
存储 Java 数据处理
|
7月前
|
缓存 Java API
IO流【IO流技术介绍、 IO流的经典写法、 IO流新语法经典写法、Java中流的概念细分 】(一)-全面详解(学习总结---从入门到深化)
IO流【IO流技术介绍、 IO流的经典写法、 IO流新语法经典写法、Java中流的概念细分 】(一)-全面详解(学习总结---从入门到深化)
115 0
|
2月前
|
安全 NoSQL Java
一文搞懂网络通信的基石✅IO模型与零拷贝
【10月更文挑战第1天】本文深入探讨了网络通信中的IO模型及其优化方法——零拷贝技术。首先介绍了IO模型的概念及五种常见类型:同步阻塞、同步非阻塞、多路复用、信号驱动和异步IO模型。文章详细分析了每种模型的特点和适用场景,特别是多路复用和异步IO在高并发场景中的优势。接着介绍了零拷贝技术,通过DMA直接进行数据传输,避免了多次CPU拷贝,进一步提升了效率。最后总结了各种模型的优缺点,并提供了相关的代码示例和资源链接。
一文搞懂网络通信的基石✅IO模型与零拷贝
|
2月前
|
人工智能 Cloud Native Java
云原生技术深度解析:从IO优化到AI处理
【10月更文挑战第24天】在当今数字化时代,云计算已经成为企业IT架构的核心。云原生作为云计算的最新演进形态,旨在通过一系列先进的技术和实践,帮助企业构建高效、弹性、可观测的应用系统。本文将从IO优化、key问题解决、多线程意义以及AI处理等多个维度,深入探讨云原生技术的内涵与外延,并结合Java和AI技术给出相应的示例。
112 1
|
7月前
|
数据采集 异构计算
LabVIEW编程LabVIEW开发高级数据采集技术 操作数字IO 例程与相关资料
LabVIEW编程LabVIEW开发高级数据采集技术 操作数字IO 例程与相关资料
99 22
|
6月前
|
IDE Linux 程序员
技术经验解读:【转】IO空间,IO端口,MMIO
技术经验解读:【转】IO空间,IO端口,MMIO
340 0
|
6月前
|
存储 运维 算法
Python文件处理(IO 技术)-2
Python文件处理(IO 技术)
|
2月前
|
运维 Cloud Native 持续交付
云原生技术解析:从IO出发,以阿里云原生为例
【10月更文挑战第24天】随着互联网技术的不断发展,传统的单体应用架构逐渐暴露出扩展性差、迭代速度慢等问题。为了应对这些挑战,云原生技术应运而生。云原生是一种利用云计算的优势,以更灵活、可扩展和可靠的方式构建和部署应用程序的方法。它强调以容器、微服务、自动化和持续交付为核心,旨在提高开发效率、增强系统的灵活性和可维护性。阿里云作为国内领先的云服务商,在云原生领域有着深厚的积累和实践。
71 0
|
3月前
|
网络协议 Java Linux
高并发编程必备知识IO多路复用技术select,poll讲解
高并发编程必备知识IO多路复用技术select,poll讲解
|
5月前
|
NoSQL
共识协议的技术变迁问题之WPaxos理常态下的IO请求处理如何解决
共识协议的技术变迁问题之WPaxos理常态下的IO请求处理如何解决
164 55