Java基础-零拷贝

文章目录

    • 什么是零拷贝?
      • 传统IO执行过程
      • 零拷贝的意义
      • 零拷贝的主要实现方式
      • 实际应用场景
      • 零拷贝的优势
      • 零拷贝的局限性
    • Java 中的零拷贝实现
      • `FileChannel.transferTo()`
      • `FileChannel.transferFrom()`
    • 相关知识点解释
      • 什么是DMA
      • 内核空间和用户空间
      • 什么是用户态、内核态
      • 什么是上下文切换
      • 虚拟内存

什么是零拷贝?

零拷贝(Zero-copy)是一种计算机编程技术和体系结构设计,旨在减少数据在不同缓冲区或内存区域之间的拷贝次数,从而提高系统性能和效率。零拷贝技术主要用于提高数据传输和处理的速度,特别是在涉及大量数据传输的场景中,如网络通信、文件系统操作和多媒体处理等。

传统IO执行过程

传统IO流程

  • 用户应用进程调用read函数,向操作系统发起IO调用, 上下文从用户态转为内核态(切换1)
  • DMA控制器把数据从磁盘中,读取到内核缓冲区。
  • CPU把内核缓冲区数据,拷贝到用户应用缓冲区, 上下文从内核态转为用户态(切换2),read函数返回
  • 用户应用进程通过write函数,发起IO调用, 上下文从用户态转为内核态(切换3)
  • CPU将用户缓冲区中的数据,拷贝到socket缓冲区
  • DMA控制器把数据从socket缓冲区,拷贝到网卡设备, 上下文从内核态切换回用户态(切换4),write函数返回

零拷贝的意义

传统上,数据在操作系统和应用程序之间传输时通常需要多次拷贝,例如从网络接口卡(NIC)到用户空间的缓冲区,再从用户空间的缓冲区到内核空间的缓冲区,等等。每次拷贝都会消耗 CPU 时间和内存带宽。零拷贝技术试图通过减少这些不必要的拷贝来提高性能。

零拷贝的主要实现方式

零拷贝并不是没有拷贝数据,而是减少用户态/内核态的切换次数以及CPU拷贝的次数。零拷贝实现有多种方式,分别是

    1. mmap+write
    1. sendfile
    1. 带有DMA收集拷贝功能的sendfile
  1. mmap+write 实现方式:
  • 使用 mmap() 系统调用将文件映射到内存,这样应用程序可以直接操作内存中的数据,而无需显式地读取或写入文件。当应用程序对内存进行修改时,这些修改会被自动同步到文件中。
    mmap+write
  • 用户进程通过 mmap方法向操作系统内核发起IO调用, 上下文从用户态切换为内核态。
  • CPU利用DMA控制器,把数据从硬盘中拷贝到内核缓冲区。
  • 上下文从内核态切换回用户态,mmap方法返回。
  • 用户进程通过 write方法向操作系统内核发起IO调用, 上下文从用户态切换为内核态。
  • CPU将内核缓冲区的数据拷贝到的socket缓冲区。
  • CPU利用DMA控制器,把数据从socket缓冲区拷贝到网卡, 上下文从内核态切换回用户态,write调用返回。
    mmap+write实现的零拷贝,I/O发生了4次用户空间与内核空间的上下文切换,以及3次数据拷贝。其中3次数据拷贝中,包括了2次DMA拷贝和1次CPU拷贝。

mmap是将读缓冲区的地址和用户缓冲区的地址进行映射,内核缓冲区和应用缓冲区共享,所以节省了一次CPU拷贝‘’并且用户进程内存是虚拟的,只是映射到内核的读缓冲区,可以节省一半的内存空间。

  1. 发送页面(Sendfile):
  • sendfile() 系统调用可以从一个文件描述符直接将数据发送到另一个文件描述符,通常用于将数据从磁盘文件直接发送到网络套接字,而无需经过用户空间。
    sendfile
  • 用户进程发起sendfile系统调用, 上下文(切换1)从用户态转向内核态
  • DMA控制器,把数据从硬盘中拷贝到内核缓冲区。
  • CPU将读缓冲区中数据拷贝到socket缓冲区
  • DMA控制器,异步把数据从socket缓冲区拷贝到网卡,
  • 上下文(切换2)从内核态切换回用户态,sendfile调用返回。

sendfile实现的零拷贝,I/O发生了2次用户空间与内核空间的上下文切换,以及3次数据拷贝。其中3次数据拷贝中,包括了2次DMA拷贝和1次CPU拷贝。那能不能把CPU拷贝的次数减少到0次呢?有的,即带有DMA收集拷贝功能的sendfile!

  1. sendfile+DMA scatter/gather:
    sendfile+DMA scatter/gather
  • 用户进程发起sendfile系统调用, 上下文(切换1)从用户态转向内核态
  • DMA控制器,把数据从硬盘中拷贝到内核缓冲区。
  • CPU把内核缓冲区中的 文件描述符信息(包括内核缓冲区的内存地址和偏移量)发送到socket缓冲区
  • DMA控制器根据文件描述符信息,直接把数据从内核缓冲区拷贝到网卡
  • 上下文(切换2)从内核态切换回用户态,sendfile调用返回。

sendfile+DMA scatter/gather实现的零拷贝,I/O发生了2次用户空间与内核空间的上下文切换,以及2次数据拷贝。其中2次数据拷贝都是包DMA拷贝。这就是真正的 零拷贝(Zero-copy) 技术,全程都没有通过CPU来搬运数据,所有的数据都是通过DMA来进行传输的。

实际应用场景

  1. 网络服务器:
    • 在高性能网络服务器中,零拷贝技术可以显著提高数据传输速度。例如,使用 sendfile() 可以直接将文件内容发送到网络,而无需将其复制到用户空间。
  2. 文件系统:
    • 在文件系统中,使用内存映射技术可以让应用程序直接读写文件,而无需通过传统的读写系统调用。
  3. 数据库系统:
    • 在数据库中,直接 I/O 技术可以用来减少数据页在内存和磁盘之间的拷贝,提高数据库性能。
  4. 多媒体处理:
    • 在视频流媒体服务器或音频处理软件中,零拷贝技术可以减少数据从磁盘到网络传输过程中的延迟。

零拷贝的优势

  • 性能提升: 减少了数据拷贝的次数,降低了 CPU 负载,提高了数据传输速度。
  • 内存带宽节省: 减少内存带宽的占用,提高了系统的整体吞吐量。
  • 降低延迟: 对于实时应用,零拷贝可以显著减少数据处理的延迟。

零拷贝的局限性

  • 适用范围有限: 零拷贝技术并不是在所有场景下都能有效应用,特别是在需要对数据进行复杂处理的情况下。
  • 编程复杂度: 实现零拷贝通常需要更复杂的编程技巧和对底层系统的深入理解。

总的来说,零拷贝技术是一种重要的优化手段,可以显著提高数据密集型应用的性能。

Java 中的零拷贝实现

在 Java 中,零拷贝主要通过 FileChannel.transferTo()FileChannel.transferFrom() 方法来实现。这两个方法允许直接在两个文件通道之间传输数据,而不需要通过中间缓冲区。

FileChannel.transferTo()

transferTo() 方法用于将一个文件通道中的数据直接传输到另一个文件通道。这种方法适用于从文件读取数据并直接发送到网络的情况。

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;public class ZeroCopyExample {public static void main(String[] args) throws Exception {// 打开文件输入流和输出流FileInputStream fileInputStream = new FileInputStream("input.txt");FileOutputStream fileOutputStream = new FileOutputStream("output.txt");// 获取文件通道FileChannel inputChannel = fileInputStream.getChannel();FileChannel outputChannel = fileOutputStream.getChannel();// 使用 transferTo() 方法直接传输数据long transferred = inputChannel.transferTo(0, inputChannel.size(), outputChannel);System.out.println("Transferred bytes: " + transferred);// 关闭资源inputChannel.close();outputChannel.close();}
}

在这个例子中,transferTo() 方法直接将 input.txt 文件的内容传输到了 output.txt 文件中,而不需要先读取到内存缓冲区再写入。

FileChannel.transferFrom()

transferFrom() 方法用于将一个文件通道中的数据直接传输到另一个文件通道。这种方法适用于从网络接收数据并直接写入文件的情况。

import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;
import java.net.Socket;public class ZeroCopyReceiveExample {public static void main(String[] args) throws Exception {// 连接到服务器Socket socket = new Socket("hostname", 1234);SocketChannel socketChannel = socket.getChannel();// 打开文件输出流FileOutputStream fileOutputStream = new FileOutputStream("received.txt");FileChannel fileChannel = fileOutputStream.getChannel();// 使用 transferFrom() 方法直接传输数据long transferred = fileChannel.transferFrom(socketChannel, 0, Long.MAX_VALUE);System.out.println("Transferred bytes: " + transferred);// 关闭资源fileChannel.close();socketChannel.close();}
}

在这个例子中,transferFrom() 方法直接将从网络接收到的数据写入到 received.txt 文件中,而不需要先读取到内存缓冲区再写入。

相关知识点解释

什么是DMA

DMA(Direct Memory Access,直接存储器访问)是一种让外设(如硬盘、网络接口卡等)与计算机内存之间直接进行数据传输的技术,而不需要通过CPU来传输每一个数据块。这意味着,在DMA操作期间,数据可以直接在内存和外设之间复制,从而减轻了CPU的负担,并提高了数据传输的速度和效率。

DMA通常用于高速设备的数据传输,例如磁盘控制器、声卡、图形卡和其他需要大量数据传输的硬件设备。当一个设备请求DMA时,它会暂时接管总线并直接与内存通信,这样CPU就可以处理其他任务或者等待DMA操作完成的通知。

DMA操作一般分为几个步骤:

  1. 请求:外设向DMA控制器发出DMA请求。
  2. 响应:DMA控制器如果可以接受请求,则会向CPU申请总线控制权。
  3. 暂停CPU:CPU暂停当前的工作,释放总线控制权给DMA控制器。
  4. 数据传输:DMA控制器接管总线后,直接在外设和内存之间传输数据。
  5. 恢复CPU控制:当数据传输完成后,DMA控制器释放总线控制权,CPU恢复执行。

DMA技术对于提高系统的整体性能非常重要,尤其是在处理大量数据传输的情况下。

内核空间和用户空间

我们电脑上跑着的应用程序,其实是需要经过操作系统,才能做一些特殊操作,如磁盘文件读写、内存的读写等等。因为这些都是比较危险的操作,不可以由应用程序乱来,只能交给底层操作系统来。

因此,操作系统为每个进程都分配了内存空间,一部分是用户空间,一部分是内核空间。内核空间是操作系统内核访问的区域,是受保护的内存空间,而用户空间是用户应用程序访问的内存区域。 以32位操作系统为例,它会为每一个进程都分配了4G(2的32次方)的内存空间。

  • 内核空间:主要提供进程调度、内存分配、连接硬件资源等功能
  • 用户空间:提供给各个程序进程的空间,它不具有访问内核空间资源的权限,如果应用程序需要使用到内核空间的资源,则需要通过系统调用来完成。进程从用户空间切换到内核空间,完成相关操作后,再从内核空间切换回用户空间。

什么是用户态、内核态

  • 如果进程运行于内核空间,被称为进程的内核态
  • 如果进程运行于用户空间,被称为进程的用户态。

什么是上下文切换

  • 什么是CPU上下文?

CPU 寄存器,是CPU内置的容量小、但速度极快的内存。而程序计数器,则是用来存储 CPU 正在执行的指令位置、或者即将执行的下一条指令位置。它们都是 CPU 在运行任何任务前,必须的依赖环境,因此叫做CPU上下文。

  • 什么是 CPU上下文切换?

它是指,先把前一个任务的CPU上下文(也就是CPU寄存器和程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务。

一般我们说的上下文切换,就是指内核(操作系统的核心)在CPU上对进程或者线程进行切换。进程从用户态到内核态的转变,需要通过系统调用来完成。系统调用的过程,会发生CPU上下文的切换。

CPU 寄存器里原来用户态的指令位置,需要先保存起来。接着,为了执行内核态代码,CPU 寄存器需要更新为内核态指令的新位置。最后才是跳转到内核态运行内核任务。

上下文切换

虚拟内存

现代操作系统使用虚拟内存,即虚拟地址取代物理地址,使用虚拟内存可以有2个好处:

  • 虚拟内存空间可以远远大于物理内存空间
  • 多个虚拟内存可以指向同一个物理地址

虚拟内存

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/147442.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

前端——实现时钟 附带小例子

创建日期对象 toLocaleDateString() 获取日期 console.log(date.toLocaleDateString()) toLocaleTimeString() 获取时间 console.log(date.toLocaleTimeString()) toLocaleString() 获取日期和时间 console.log(date.toLocaleString()) date.getDay() 获取星期几 周日为…

计算机毕业设计选题推荐-基于python+Django的全屋家具定制服务平台

精彩专栏推荐订阅:在下方主页👇🏻👇🏻👇🏻👇🏻 💖🔥作者主页:计算机毕设木哥🔥 💖 文章目录 一、全屋家具定制…

H264参考帧列表管理

P/SP/B帧的参考帧列表的初始化 参考H.264标准文档的8.2.4.2章节,暂不研究场编码。在初始化P/SP帧或B帧的参考帧列表过程中,DPB中至少要存在一个有效的、即被标记为“用于短期或长期参考”的参考帧。 P/SP Slice 参考帧列表初始化 P/SP Slice参考帧列表…

《算法岗面试宝典》正式发布

大家好,历时半年完善,《算法岗面试宝典》 终于可以跟大家见面了。 最近 ChatGPT 爆火,推动了技术圈对大模型算法场景落地的热情,就业市场招聘人数越来越多,算法岗一跃成为竞争难度第一的岗位。 岗位方向 从细分方向…

汽车总线之----CAN总线

Introduction 早期的车辆网络是点对点的模式,臃肿繁杂且效率低下 现在是以总线的模式,很明显线路简洁清爽了很多。 高速CAN可以支持1M/s的速率,低速CAN可以支持125k/s的速率 CAN节点的内部结构图(Structure of CAN-Bus and electronic C…

*C++:list

一.list简介 1. list 是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。 2. list 的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素…

redisson 延迟队列实现任务过期监听

一、需求: 任务超过一个小时以后,如果还为待执行状态,则自动转为结束状态。 二、实现: 创建延迟队列的监听任务RedisDelayedQueueListener,消费延迟队列;创建新增延迟队列的类,用于创建延迟队列&#xf…

ACM MM24 | Hi3D: 3D生成领域再突破!新视角生成和高分辨率生成双SOTA(复旦智象等)

文章链接:https://arxiv.org/pdf/2409.07452 Github 链接:https://github.com/yanghb22-fdu/Hi3D-Official 亮点直击 本文提出了高分辨率图像到3D模型(Hi3D),这是一种基于视频扩散的新范式,将单个图像重新定…

Codeforces Round 974 (Div. 3) G. Milky Days

题目 题解 #include<bits/stdc.h> using namespace std; #define int long long #define ll long long #define ld long double #define pb push_back #define fi first #define se second #define pii pair<int, int> #define lson p << 1 #define rson p …

Mapper核心配置文件

文章目录 environment 数据库环境typeAlias 起别名 environment 数据库环境 typeAlias 起别名

PMBOK® 第六版 估算活动持续时间

目录 读后感—PMBOK第六版 目录 在项目管理中&#xff0c;尤其是在软件开发这样的复杂项目中&#xff0c;工作内容是多种多样的。从需求分析、设计、编码到测试和部署&#xff0c;每个阶段都有其独特的挑战和不确定性。 没有人能独自完成所有估算工作并做到绝对精准。估算涉及…

股指期货交割方式是什么?

说起股指期货&#xff0c;这可是个高大上的金融玩意儿。咱们平时买卖股票&#xff0c;那是看准了哪只股就下手&#xff0c;赚了就卖&#xff0c;赔了就扛&#xff0c;挺直接的。但股指期货呢&#xff0c;它玩的是未来的预期&#xff0c;就像是你跟人打赌明天天气好不好&#xf…

开源推理库介绍:ZML,Distributed Llama,EXO | LeetTalk Daily

“LeetTalk Daily”&#xff0c;每日科技前沿&#xff0c;由LeetTools AI精心筛选&#xff0c;为您带来最新鲜、最具洞察力的科技新闻。 开源推理库的出现为机器学习模型的部署、监控和扩展提供了强大的支持。我们介绍三个重要的开源推理库&#xff1a;ZML、Distributed Llama …

机器人速度雅可比矩阵求解(2自由度平面关节机器人)

关节速度和末端速度空间的映射需要计算雅可比矩阵的逆矩阵,在博途PLC里如何计算一个方阵的逆矩阵,大家可以参考下面这篇文章: 博途PLC矩阵求逆 矩阵求逆 博图SCL_博图矩阵运算-CSDN博客文章浏览阅读839次。本文介绍如何用C语言实现矩阵求逆的过程,详细解析了相关代码,适…

Spring实战——入门讲解

​ 博客主页: 南来_北往 系列专栏&#xff1a;Spring Boot实战 Spring介绍 Spring实战的入门讲解主要涵盖了Spring框架的基本概念、核心功能以及应用场景。以下是关于Spring实战入门的具体介绍&#xff1a; Spring框架概述&#xff1a;Spring是一个轻量级的Java开发框架…

【有啥问啥】探索累计推理(Cumulative Reasoning, CR)——大型语言模型中的复杂推理新框架

探索累计推理&#xff08;Cumulative Reasoning, CR&#xff09;——大型语言模型中的复杂推理新框架 引言 随着人工智能&#xff08;AI&#xff09;的快速发展&#xff0c;大型语言模型&#xff08;LLMs&#xff09;在自然语言处理上的表现令人瞩目。然而&#xff0c;LLMs在…

【HTTPS】—— HTTPS协议原理详解

目录 &#xff08;一&#xff09;Https是什么 1.1 什么是加密 1.2 为什么要加密 1.3 常见的加密方式 1.4 数据摘要 && 数据指纹 &#xff08;二&#xff09;Https工作过程研究 方案一&#xff1a;只使用对称秘钥 方案二&#xff1a;只使用非对称秘钥 方案三&a…

14年数据结构

第一题 解析&#xff1a; 求时间复杂度就是看程序执行了多少次。 假设最外层执行了k次&#xff0c;我们看终止条件是kn&#xff0c;则&#xff1a; 有, 内层是一个j1到jn的循环&#xff0c;显然执行了n次。 总的时间复杂度是内层外层 答案选C。 第二题 解析&#xff1a; 一步一…

如何用ChatGPT制作一款手机游戏应用

有没有想过自己做一款手机游戏&#xff0c;并生成apk手机应用呢&#xff1f;有了人工智能&#xff0c;这一切就成为可能。今天&#xff0c;我们就使用ChatGPT来创建一个简单的井字棋游戏&#xff08;Tic-Tac-Toe&#xff09;&#xff0c;其实这个过程非常轻松且高效。 通过Cha…

【Linux】常用指令【更详细,带实操】

Linux全套讲解系列&#xff0c;参考视频-B站韩顺平&#xff0c;本文的讲解更为详细 目录 一、文件目录指令 1、cd【change directory】指令 ​ 2、mkdir【make dir..】指令​ 3、cp【copy】指令 ​ 4、rm【remove】指令 5、mv【move】指令 6、cat指令和more指令 7、less和…