Java基础-零拷贝

news2024/11/15 4:31:18

文章目录

    • 什么是零拷贝?
      • 传统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.coloradmin.cn/o/2157954.html

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

相关文章

2012年408考研真题-数据结构

8.【2012统考真题】求整数n(n≥0)的阶乘的算法如下&#xff0c;其时间复杂度是(&#xff09;。 int fact(int n){ if(n<1) return 1; return n*fact (n-1); } A. O(log2n) B. O(n) C. O(nlog2n) D. O(n^2) 解析&#xff1a; 观察代码&#xff0c;我们不…

如何在openKylin中配置ssh服务并实现远程连接开放麒麟系统(1)

文章目录 前言1. 安装SSH服务2. 本地SSH连接测试3. openKylin安装Cpolar4. 配置 SSH公网地址5. 公网远程SSH连接6. 固定SSH公网地址7. SSH固定地址连接 前言 本文主要介绍如何在openKlyin系统中设置ssh连接&#xff0c;并结合cpolar内网穿透工具实现远程也可以ssh连接本地局域…

功能 接口测试,详解从抓包 +linux 日志 + 数据库的 bug 定位!

我在跟很多测试人员交流中发现&#xff0c;很大一部分测试工程师在进行功能和接口测试过程中&#xff0c;对于发现的bug很少去进行定位&#xff0c;只是将bug基于业务操作上如何出现的&#xff0c;进行描述&#xff1b;至于bug产生的原因&#xff0c;开发自己排查去吧。本文中&…

多语言文本 AI 纠错格式化 API 数据接口

多语言文本 AI 纠错格式化 API 数据接口 AI / 文本处理 AI 模型智能纠正 语法纠错 / 文本格式化。 1. 产品功能 支持多语言文本的语法纠错&#xff1b;自动识别并纠正拼写错误、语法错误和标点符号使用不当&#xff1b;优化文本格式&#xff0c;提高可读性&#xff1b;基于AI…

《李·斯莫林讲量子引力》:在不断运动的宇宙中探究离散的时空

可能是斯莫林的书读得并不多&#xff0c;感觉他讲故事的能力不如讲物理定律的能力。前半部分纯知识的可读性要好于后面讲述理论的创造过程的故事。如作者所说现代科学没有任何领域是单打独斗&#xff0c;而是不断探索&#xff0c;在团队中&#xff0c;前人和其他专业领域专家合…

vue使用PDF.JS踩的坑--部署到服务器上显示pdf.mjs viewer.mjs找不到资源

之前项目使用的pdf.js 是2.15.349版本&#xff0c;最近换了一个4.6.82的版本&#xff0c;在本地上浏览文件运行的好好的&#xff0c;但是发布到服务器&#xff08;IIS&#xff09;上打不开文件&#xff0c;控制台提示找不到pdf.mjs viewer.mjs。 之前使用的2.15.349pdf和viewer…

76、Python之函数式编程:柯里化都不懂,别说你会函数式编程

引言 很多时候&#xff0c;我们在定义函数处理比较复杂的业务逻辑时&#xff0c;首先是想着遵照“单一职能原则&#xff08;SRP&#xff09;”&#xff0c;尽量拆分为功能单一、足够精简的函数&#xff0c;以便保证代码的可读性和可扩展性。但是&#xff0c;有些逻辑就是没法拆…

2024年双十一有什么好物值得买呢?双十一必买好物清单

双十一买什么犒劳自己既不会浪费钱又可以增添生活的幸福感&#xff1f;以下就整理了五款更适合与秋冬独自生活相伴的好物&#xff0c;精致增加生活氛围感&#xff0c;热爱生活的同时更好的爱自己&#xff01;努力工作和生活当然也要更好的享受生活&#xff0c;给生活创造更多美…

Vue(14)——组合式API①

setup 特点&#xff1a;执行实际比beforeCreate还要早&#xff0c;并且获取不到this <script> export default{setup(){console.log(setup函数);},beforeCreate(){console.log(beforeCreate函数);} } </script> 在setup函数中提供的数据和方法&#xff0c;想要在…

数据结构和算法之树形结构(2)

文章出处&#xff1a;数据结构和算法之树形结构(2) 关注码农爱刷题&#xff0c;看更多技术文章&#xff01;&#xff01; 三、二叉查找树(接前篇) 二叉查找树&#xff0c;又称二叉搜索树或二叉排序树&#xff0c;是在普通二叉树基础上为了实现快速查找而设计出来的一种树形结…

Fyne ( go跨平台GUI )中文文档-绘图和动画(三)

本文档注意参考官网(developer.fyne.io/) 编写, 只保留基本用法 go代码展示为Go 1.16 及更高版本, ide为goland2021.2 这是一个系列文章&#xff1a; Fyne ( go跨平台GUI )中文文档-入门(一)-CSDN博客 Fyne ( go跨平台GUI )中文文档-Fyne总览(二)-CSDN博客 Fyne ( go跨平台GUI…

继电器测试负载箱的维护和保养方法有哪些?

继电器测试负载箱是用于模拟各种电气负载的设备&#xff0c;广泛应用于继电器、接触器等电气元件的测试和校验。在日常使用中&#xff0c;为确保其正常运行和准确性&#xff0c;以下是一些常见的维护和保养方法&#xff1a; 1. 电源问题&#xff1a;如果电源电压不稳定或波动过…

PD 取电快充协议芯片 支持广泛应用,最高取电电压100W

XSP06是一款支持多协议的受电端取电快充芯片&#xff0c;支持PD2.0/3.0、QC2.0/3.0、华为FCP、三星AFC快充协议。它允许设备通过与快充适配器通信&#xff0c;有效地从适配器或车充等电源诱骗出所需要的电压为自身供电。 特性&#xff1a; 支持电压档位&#xff1a;XSP06支持触…

根据一级分类Id获取专辑标签(内连接,一对多)

文章目录 base_attributebase_attribute_value 1、BaseAttribute2、BaseAttributeValue3、BaseCategoryApiController --》findAttribute()4、BaseCategoryServiceImpl --》findAttribute()5、BaseAttributeMapper6、BaseAttributeMapper.xml 当选择完专辑分类之后&#xff0c;…

如何进行Ubuntu磁盘空间深度清理?

近期使用AutoDL算力云&#xff0c;发现系统盘只有30G&#xff0c;数据盘只有50G&#xff0c;跑一个稍微大一点的模型&#xff0c;马上空间就拉爆了&#xff0c;现在做一个磁盘深度清理操作&#xff0c;看看效果。 清理前磁盘占用如下&#xff1a; 在 Ubuntu 系统中进行磁盘深度…

二、MySQL环境搭建

文章目录 1. MySQL的卸载步骤1&#xff1a;停止MySQL服务步骤2&#xff1a;软件的卸载步骤3&#xff1a;残余文件的清理步骤4&#xff1a;清理注册表&#xff08;选做&#xff09;步骤5&#xff1a;删除环境变量配置 2. MySQL的下载、安装、配置2.1 MySQL的4大版本2.2 软件的下…

Linux环境的JDK安装

1.搜索可用的jdk yum search jdk/(或者是要安装的版本java-11)2.安装需要的版本 yum install java-11-openjdk.x86_643.验证是否安装成功 java -version4.配置环境变量 通过yum安装的默认路径为&#xff1a;/usr/lib/jvm cd /etc/profile.d/ touch java_home.sh vim java_…

Linux线程同步与互斥

&#x1f30e;Linux线程同步与互斥 文章目录&#xff1a; Linux线程同步与互斥 Linux线程互斥 线程锁       互斥量Mutex         初始化互斥量的两种方式         申请锁方式         解除与销毁锁 问题解决及线程饥饿       互斥锁的底…

线性调频信号脉冲压缩并非是一个门信号

如果是频域是门信号&#xff0c;时域是sinc信号&#xff0c;时间越长震荡只会越小。图象是线性卷积做的&#xff0c;肯定没错。

如何写出高收录词的listing文案,先做好这一点

在亚马逊上&#xff0c;关键词是连接买家搜索与产品之间的桥梁&#xff0c;超过80%的购买行为都是通过搜索关键词开始的。因此&#xff0c;文案中包含的精准关键词越多&#xff0c;Listing越能匹配买家的需求&#xff0c;从而提高自然排名并优化广告效果。 亚马逊的收录分为静…