零拷贝(Zero-Copy)

1.背景

现在有这样一个场景,我们需要在本地选择一个文件后,然后上传到网络上。
我们再看看文件的内容数据的具体搬运过程:

你会发现,在整个文件搬运的过程中,发生了多次的数据拷贝上下文转换

4次数据拷贝:

  • 第一次:磁盘文件 -> 内核缓存(内核缓冲区,Page Cache),该过程由DMA负责完成,CPU可以执行其他任务。
  • 第二次:内核缓存 -> 用户缓冲区,该过程由CPU负责完成。
  • 第三次:用户缓冲区 -> 内核缓存,该过程由CPU负责完成。
  • 第四次:内核缓存 -> 网卡的设备缓冲区,该过程由DMA负责完成,CPU可以执行其他任务。

4次上下文转换:
每一次的系统调用均会涉及到两次上下文转换:

  • 第一次:用户发起系统调用,上下文将由用户态 -> 内核态
  • 第二次:系统调用执行完成,上下文将由执行时的环境内核态 -> 用户态

而上面的文件搬运过程用到了readwrite这两个系统调用。

通过上面的分析,不难看出,内核态与用户态的交互部分完全没有存在的必要(前提是你不会对加载进用户缓冲区的数据进行二次加工),因此,我们需要去除掉这部分冗余的交互过程。诺,零拷贝这不就登场了嘛。

2.实现方式

2.1 mmap + write

2.1.1 概述

mmap():一个系统调用函数,该函数会将内核缓冲区中的数据直接映射到用户空间,这样做就省去了 内核缓存 -> 用户缓冲区 这一拷贝过程。
write():在发现所要拷贝的数据是内核缓冲区经mmap直接映射过来的,因此,它将直接对应的内核缓存中拷贝数据到Socket缓冲区,但是此过程需要由CPU负责进行数据的拷贝。

2.2.2 评估

通过将read系统调用替换为mmap系统调用,我们减少了一次由内核缓存 -> 用户缓冲区的拷贝过程,但是,我们的系统调用次数没有减少,因此,这种方式还不是最理想的零拷贝方案。

2.2 sendfile

2.2.1 概述

**sendfile()**:一个系统调用函数,它能够代替前面的read()write()这两个系统调用函数,因此,它能够免去两次上下文切换的开销。同时,它也将内核缓存的数据不经过用户缓冲区而直接拷贝到Socket缓冲区(就本场景而言),因此,也能够免去一次内核缓存 -> 用户缓冲区的拷贝过程。

适用环境:Linux 2.1+

2.2.2 评估

该方案同时免去了一次拷贝过程和两次上下文切换所带来的开销,但是,CPU还是参与了一次内存的拷贝,因此这个方案还不是最优解。

2.3 sendfile + SG-DMA

2.3.1 概述

如果网卡支持SG-DMA(可以通过ethtool -k eth0 | grep scatter-gather指令来查看是否支持SG-DMA),拷贝到内核缓存的数据将不再由CPU拷贝至Socket缓冲区了,而是直接由SG-DMA控制器负责直接拷贝至网卡的缓冲区中。

适用环境:Linux 2.4+

2.3.2 评估

CPU全程没有参与到数据的拷贝过程中来,而且系统调用次数也比最初降低了一半,数据拷贝次数也降低了一半,整体执行效率大致提升了一倍!

3.应用

  • Kafka底层大量调用了Java的NIO中的transferTo方法,而该方法又最终发起了sendfile系统调用(如果运行环境支持的话),因此,Kafka在处理海量数据上快如闪电、所向披靡!
  • NGINX目前也支持配置sendfile

4.注意事项

  • 零拷贝技术要求数据不能进行二次加工,如:压缩数据后发送,这种就不能使用零拷贝技术。
  • 零拷贝技术依赖于PageCache(即内核缓存)。

5.大文件传输

51 背景

大文件传输将不走内核缓存。原因如下:

  1. 大文件会占用较多的Page Cache,会挤占热点小(针对于大文件而言)数据的空间,从而使热点数据的命中率下降。
  2. 大文件缓存在Page Cache中,其本身的命中率也不高。

由于大文件传输不走Page Cache,因此前面所说的零拷贝技术它也就用不了了。

5.2 解决方案

5.2.1 异步I/O + 直接I/O

传统的数据拷贝过程:

采用异步I/O + 直接I/O下的大文件拷贝过程:

你会发现,我们数据的拷贝不再经过中间的Page Cache,因此这种I/O方式不就是我们在文件系统(二)中所谈到的直接I/O吗?
同时,我们用户进程并没有持续等待I/O操作的完成,而是立刻返回,继续执行其他任务,因此,我们也达到了异步I/O的目的。

5.3 评估

综合前面的解决方案,我们有:

  • 对于小文件传输,尽可能地采用零拷贝技术。
  • 对于大文件传输,尽可能地采用异步I/O + 直接I/O的方式进行加速传输。

参考文档

9.1 什么是零拷贝?

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

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

相关文章

每日一题(5)——StringBuffer操作

编写程序,对StringBuffer对象进行追加,插入和修改缓冲区长度等操作; class StringDemo{public static void main(String[] args){boolean btrue;int i321;long l123456;String s1new String("Hello,world!");StringBuffer s2new S…

Rust一维Vec垂直方向拼接、水平方向拼接,多个二维Vec垂直方向拼接

1.在Rust中&#xff0c;拼接二维Vec通常意味着将多个一维Vec组合成一个二维Vec。假设你想要将多个Vec<T>拼接成一个Vec<Vec<T>>&#xff0c;你可以使用迭代器方法来实现。 下面是一个示例&#xff0c;演示如何将多个一维Vec拼接成一个二维Vec&#xff1a; …

深入探索:移动云服务器的强大之处

文章目录 一 什么是移动云二 移动云服务器的使用三 移动云服务器的优点四 在移动云上部署node.js项目五 移动云服务器的应用场景六 移动云服务器的使用体验总结 一 什么是移动云 移动云是指用户可以通过移动设备访问云端的数据和应用&#xff0c;无需在本地设备上进行存储和处…

单片机LCD1602显示电子时钟设计

基于52单片机电子时钟的设计 摘要 本次设计的多功能时钟系统采用STC89C52单片机为核心器件&#xff0c;利用其定时器/计数器定时和记数的原理&#xff0c;结合液晶显示电路、时钟芯片DS1302电路、电源电路以及按键电路来设计计时器。将软硬件有机地结合起来&#xff0c;使得系…

汇编实现的操作系统

掌握X86汇编语言和GDB程序调试工具对于程序员来说是非常重要的_gdb 查看x86汇编-CSDN博客 掌握编译器和虚拟机的开发有哪些方面的好处-CSDN博客 Ville Mikael Turjanmaan开发的一个操作系统MenuetOS可运行在IA-32, x86-64平台上&#xff0c;完全用 64 位汇编语言编写。功能包…

Oracle23ai新特性case when子句增加多条件判断

Oracle23ai新特性case when子句增加多条件判断&#xff0c;语句更加灵活易用&#xff0c;更好支持SQL标准。 参考官方文档 CASE Expressions https://docs.oracle.com/en/database/oracle/oracle-database/23/lnpls/plsql-language-fundamentals.html#GUID-216F1B33-493F-4CD…

从参数变化解读 MySQL 8.2.0 发版说明

↑ 关注“少安事务所”公众号&#xff0c;欢迎⭐收藏&#xff0c;不错过精彩内容~ 日前&#xff0c;MySQL 8.2.0 创新版本已正式上线&#xff0c;并提供安装包下载&#xff0c;但 docker 镜像尚未更新。 在 MySQL 8.1.0 刚发版时也做过分析&#xff0c;欢迎阅读&#xff1a; 重…

vue框架学习 -- 跨域问题解决之 proxy 配置

在Vue.js项目中&#xff0c;为了在开发环境下解决跨域问题&#xff0c;我们可以利用 vue.config.js 文件中的 devServer.proxy 配置来设置一个代理服务器。这个代理服务器会拦截特定的请求&#xff0c;并将其转发到目标后端服务器。 以下是一个基本的proxy配置详解&#xff1a;…

区块链技术和应用

文章目录 前言 一、区块链是什么&#xff1f; 二、区块链核心数据结构 2.1 交易 2.2 区块 三、交易 3.1 交易的生命周期 3.2 节点类型 3.3 分布式系统 3.4 节点数据库 3.5 智能合约 3.6 多个记账节点-去中心化 3.7 双花问题 3.8 共识算法 3.8.1 POW工作量证明 总结 前言 学习长…

Drone+Gitee自动执行构建、测试和发布工作流

拉取Drone:(至于版本&#xff0c;你可以下载最新的) sudo docker pull drone/drone:2 拉取runner&#xff1a; sudo docker pull drone/drone-runner-docker 在Gitee中添加第三方应用&#xff1a; 进入个人主页&#xff0c;点击设置&#xff1a; 往下翻&#xff0c;找到数…

前缀和,差分算法理解

前缀和是什么&#xff1a; 前缀和指一个数组的某下标之前的所有数组元素的和&#xff08;包含其自身&#xff09;。前缀和分为一维前缀和&#xff0c;以及二维前缀和。前缀和是一种重要的预处理&#xff0c;能够降低算法的时间复杂度 说个人话就是比如有一个数组&#xff1a; …

H3CNE-6-ICMP数据包分析

ICMP&#xff1a;Internet Control Message Protocol ICMP用来传递差错、控制、查询等信息 Wireshark抓包 Wireshark下载国内镜像 ICMP数据包格式 Type&#xff1a;表示ICMP消息类型 Code&#xff1a;表示同一消息类型中的不同信息 ICMP消息类型和编码类型 ICMP应用 &…

Java 反射基础

概述 Java反射&#xff08;Reflection&#xff09;是Java编程语言的一个特性&#xff0c;它允许在运行时对类、接口、字段和方法进行动态查询和操作。反射提供了一种在运行时查看和修改程序行为的能力&#xff0c;这通常用于实现一些高级功能&#xff0c;如框架、ORM&#xff…

亚马逊开店详细教程(6)- 获得商品的评分

1. 为什么要参加 VINE计划 用户在浏览一个新上架的商品时&#xff0c;通常会参照以往买家的对商品的评论&#xff0c;如果你是新全的商品可能没有任何评论信息&#xff0c;这可以会让一部分用户对购买产品有所顾虑&#xff0c;参加亚马逊Vine计划能够帮助新产品快速获得高质量…

vue实现esc关闭div弹窗的自定义指令

弹窗是 div 实现的&#xff08;非el-dialog&#xff09;,效果&#xff1a;按下esc&#xff0c;关闭弹窗 directive/divEscClose/divEscClose.js export default {bind: function (el, binding, vnode) {let keydownHandler; ​const closeModal () > {if (typeof binding.…

【MySQL精通之路】SQL优化(1)-查询优化

SQL优化方案主博客&#xff1a; 【MySQL精通之路】SQL优化(1)-CSDN博客 SELECT查询优化&#xff1a; 以下优化都由MySQL查询优化器自动进行了处理。我们了解的过程中需要知道我们如何编写SQL以使优化器可以优化我们的查询语句。 之所以分成多博客发布&#xff0c;主要是为了…

2024年山东省安全员C证证考试题库及山东省安全员C证试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年山东省安全员C证证考试题库及山东省安全员C证试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特种设备作业人员上岗证考试大…

【Spring MVC】_SpringMVC项目返回数据

目录 1. 注解使用示例 1.1 使用Controller注解 1.2 使用RestController注解 1.3 使用Controller与ResponseBody注解 2. 关于ResponseBody注解 前文已经介绍过使用Controller注解向前端返回一个HTML页面&#xff0c;接下来将介绍向前端返回数据。 关于Controller和RestCon…

QT Qstring转QJson转QbyteArray

QT5.15 QT Qstring转QJson //读取json格式文件 // QByteArray json http_recv_str.toLatin1();//字符串转字节 QByteArray json http_recv_str.toUtf8().data(); //信息带中文&#xff0c;则需要toUtf8() //QByteArray json http_recv_str.toLocal8Bit().data();//…

Volatile的内存语义

1、volatile的特性 可见性&#xff1a;对一个volatile变量的读&#xff0c;总能够看到任意一个线程对这个volatile变量的写入。 原子性&#xff1a;对任意单个volatile变量的读/写具有原子性&#xff0c;但类似于volatile这种复合操作不具有原子性。 接下来我们用程序验证。…