DMA 和 零拷贝技术 到 网络大文件传输优化

news2024/11/14 10:34:57

文章目录

  • DMA 控制器的发展
    • 无 DMA 控制器 IO 过程
    • DMA 控制器
  • 传统文件传输性能有多糟糕?
    • 如何优化文件传输性能
    • 零拷贝技术
      • mmap + write
      • sendfile
        • SG-DMA(The Scatter-Gather Direct Memory Access)
      • 零拷贝技术的应用
  • 大文件传输应该用什么方式
    • PageCache(内核缓冲区) 的作用
    • 直接 I/O
      • 直接 I/O 适用场景
    • 综上所述
    • Nginx 中的零拷贝技术和直接 I/O
  • 个人简介

DMA 控制器的发展

无 DMA 控制器 IO 过程

  • 用户进程发起 read 调用,向操作系统发送 I/O 请求,进程进入阻塞状态;
  • 操作系统收到请求后,CPU 发出对应的控制指令给磁盘控制器, CPU 释放执行其它任务。
  • 磁盘控制器收到指令后,开始准备数据并将数据放入磁盘控制器的内部缓冲区,然后产生一个中断。
  • CPU 收到中断信号后,将磁盘控制器缓冲区的数据读入寄存器,再从寄存器写入到内核缓冲区,这个过程 CPU 无法处理其它的事情。
  • 当内核缓冲区中有足够多的数据后,CPU 将内核缓冲区的数据拷贝到用户缓冲区中。

DMA 控制器

  • 如果 CPU 搬运的数据很小,那么问题并不大,但是如果需要拷贝大量数据肯定是不行的,因为 CPU 的资源十分宝贵。为了解决这个问题,于是出现了 DMA(Direct Memory Access,直接内存访问) 技术。
  • 简单来说就是:在进行 I/O 设备和内存的数据传输的时候,数据搬运的工作全部交给 DMA 控制器,而 CPU 不再参与任何与数据搬运相关的事情,这样 CPU 就可以去处理别的事务。
  • 使用 DMA 控制器后,数据传输过程如下:

  • 用户进程发起 read 调用,向操作系统发送 I/O 请求,进程进入阻塞状态;
  • 操作系统收到请求后,CPU 发送一个请求给 DMA , CPU 释放执行其它任务。
  • DMA 进一步将 I/O 请求发送磁盘控制器,磁盘控制器收到指令后,开始准备数据并将数据放入磁盘控制器的内部缓冲区,然后产生一个中断。
  • DMA 收到中断信号后将磁盘控制器缓冲区的数据拷贝到内核缓存区(此时不占用 CPU 资源,CPU 可以执行其它任务)。
  • 当 DMA 读取到足够多的数据到内核缓冲区后,发送中断信号给 CPU ,CPU 将内核缓冲区的数据拷贝到用户缓冲区中。
注:早期 DMA 只存在于主板上,现在 I/O 设备越来越多,数据传输需求也越来越复杂,所以每个 I/O 设备中都有自己的 DMA 控制器。

传统文件传输性能有多糟糕?

  • 现在,大家思考一下,如果我们服务器需要提供文件传输功能,应该怎么做?最简单的方式就是将磁盘上的文件读取出来,然后通过网络协议发送给客户端。通常涉及以下两个系统调用:
read(file, tmp_buf, len);
write(socket, tmp_buf, len);
  • 具体流程图如下:

  • 我们来看看整个过程发生了什么,发生了 2 次系统调用(4 次上下文切换),4 次数据拷贝(2 次 CPU 拷贝,2 次 DMA 拷贝)。
  • 虽然一次上下文切换的时间很短,几十纳秒到几微秒,但在高并发场景下,很容易影响性能。同时我们发现我们虽然只是传输了一份数据,但却拷贝了 4 次,毫无疑问过多的数据拷贝将会占用我们的 CPU 资源。
  • 因此,如果我们想要优化整个文件传输过程,那么主要的优化思路就是减少用户态和内核态的上下文切换以及减少数据拷贝。

如何优化文件传输性能

  • 上面我们说到想要优化整个文件传输过程,主要的优化思路是减少用户态和内核态的上下文切换以及减少数据拷贝。
  • 我们知道上下文切换其实是由于系统调用产生,因此减少系统调用就可以减少上下文切换。同时在文件传输场景中,我们用户进程并不会对数据进行加工,那么我们是不是可以不用将数据拷贝到用户空间呢?答案是可以,因此文件传输下,用户缓冲区没有存在的必要。

零拷贝技术

  • 基于上述两点优化,发展出来了零拷贝技术,零拷贝技术一般有以下两种实现方案,下面我们就具体谈一谈它如何减少上下文切换和数据拷贝次数:
mmap + write
sendfile

mmap + write

  • 在传统的文件 IO 过程中,我们需要使用 read 调用将内核缓冲区的数据读到用户缓存区,为了减少这一步的复制开销,我们使用 mmap() 代替 read():
buf = mmap(file, len);
write(sockfd, buf, len);

  • 用户进程调用 mmap() 方法后,DMA 将数据从磁盘拷贝到内核缓冲区,用户进程和内核共享这个缓冲区。
  • 用户进程调用 read() 方法后,CPU 将数据从内核缓冲区拷贝到 Socket 缓冲区。

sendfile

  • 上面整个过程虽然减少了 2 次数据拷贝,但仍然存在 4 次上下文切换。
  • 在 Linux 内核版本 2.1 中,提供了一个专门发送文件的系统调用函数 sendfile(),函数形式如下,可以进一步减少系统调用:
#include <sys/socket.h>
// 前两个参数分别是目的端和源端的文件描述符,后面两个参数是源端的偏移量和复制数据的长度,返回值是实际复制数据的长度
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

企业微信截图_16924179656803.png

  • 这样,我们一次文件传输,只需要 3 次数据拷贝和 2 次上下文切换。
SG-DMA(The Scatter-Gather Direct Memory Access)
  • 如果网卡支持 SG-DMA(The Scatter-Gather Direct Memory Access)技术(和普通的 DMA 有所不同),sendfile() 调用还会进一步优化,去掉了 CPU 把内核缓冲区里的数据拷贝到 socket 缓冲区的过程,将数据直接从内核缓冲区拷贝到网卡中。

企业微信截图_16924183044145.png

  • 这就是真正的零拷贝技术(zero-copy),因为我们全程没有使用 CPU 拷贝数据,而是通过 DMA 来进行传输。

零拷贝技术的应用

  • 我们比较常用的 kafka 就使用了零拷贝技术,从而大幅提高了 I/O 的吞吐率,这也是 kafka 能处理海量数据的原因之一。
  • kafka 传输部分实现底层调用 Java NIO 库里的 transferTo 方法,如果 Linux 系统支持 sendfile() 系统调用,那么 transferTo() 实际上最后就会使用到 sendfile() 系统调用函数。
@Overridepublic 
long transferFrom(FileChannel fileChannel, long position, long count) throws IOException { 
    return fileChannel.transferTo(position, count, socketChannel);
}
  • 在同样的硬件条件下,传统文件传输和零拷拷贝文件传输的性能差异测试,使用了零拷贝技术接近缩短了 65% 的时间,能够大幅提升我们的吞吐量:
    零拷贝测试数据.png

大文件传输应该用什么方式

  • 在了解这个问题前,我们先了解两个概念 PageCache 和 直接 I/O。

PageCache(内核缓冲区) 的作用

  • Write Buffer:写入数据时内核 I/O 算法会尽可能缓存更多的 I/O 请求在 PageCahe 中,最后合并为一个更大的 I/O 请求给磁盘,减少磁盘的寻址操作。
  • Read Cache:内核会预读相邻的数据内容并缓存一些热点数据在 PageCahe 中,减少对磁盘的访问,提到访问速度。

直接 I/O

企业微信截图_16924185437690.png

直接 I/O 适用场景

  • 应用本身已经实现了磁盘数据缓存,那么就可以不需要 PageCahe ,减少内核缓冲区的复制带来的消耗。比如在 MySQL 数据库中就可以开启直接 I/O,默认不开启。
  • 数据本身过大,难以命中 PageCahe 缓存,同时会占满 PageCahe,导致其它热点数据失效,带来额外的性能开销。

综上所述

  • 从上面两点我们可以看出:
  • 对于小文件传输,我们可以使用零拷贝技术减少上下文的切换和数据拷贝次数提高性能。
疑问:小文件是否可以直接走用户缓存区不使用内核缓存区
答:
1、使用内核缓冲区 当从磁盘缓冲区拷贝数据可以使用 DMA
2、数据到达用户缓存区,理论上比数据到内核缓冲区的代价更大
  • 但对于大文件,已经不适合使用基于 PageCahe 的零拷贝技术,而是应该使用直接 I/O 的方式,同时为了避免大文件直接 I/O 带来的长时间阻塞,我们可以使用 直接 I/O + 异步 I/O 的方式传输大文件。

Nginx 中的零拷贝技术和直接 I/O

  • 在 nginx 中,既支持 零拷贝技术,也支持 直接 I/O 我们可以根据文件大小这样配置:
location /file/ { 
    sendfile on; 
    aio on; 
    directio 1024m; 
}
  • 当文件大小小于 1024M 时使用零拷贝技术,当大于时使用直接 IO 技术。

个人简介

👋 你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.

🚀 我对技术的热情是我不断学习和分享的动力。我的博客是一个关于Java生态系统、后端开发和最新技术趋势的地方。

🧠 作为一个 Java 后端技术爱好者,我不仅热衷于探索语言的新特性和技术的深度,还热衷于分享我的见解和最佳实践。我相信知识的分享和社区合作可以帮助我们共同成长。

💡 在我的博客上,你将找到关于Java核心概念、JVM 底层技术、常用框架如Spring和Mybatis 、MySQL等数据库管理、RabbitMQ、Rocketmq等消息中间件、性能优化等内容的深入文章。我也将分享一些编程技巧和解决问题的方法,以帮助你更好地掌握Java编程。

🌐 我鼓励互动和建立社区,因此请留下你的问题、建议或主题请求,让我知道你感兴趣的内容。此外,我将分享最新的互联网和技术资讯,以确保你与技术世界的最新发展保持联系。我期待与你一起在技术之路上前进,一起探讨技术世界的无限可能性。

📖 保持关注我的博客,让我们共同追求技术卓越。

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

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

相关文章

C# 使用 SapNwRfc 调用SAP RFC

好久没写过相关代码&#xff0c;今天又来贡献一篇 C# 使用 SapNwRfc 调用SAP RFC。用VS2022的WINFORM应用程序&#xff0c;使用NuGet中的SapNwRfc类库&#xff0c;call SAP系统中的RFC&#xff0c;传入7个参数&#xff0c;得到RFC返回的2张表的数据。 一、VS2022中新建WINFORM…

三数之和----双指针

https://leetcode.cn/problems/3sum/description/?envType=study-plan-v2&envId=top-100-liked “三数之和”在某些人的口中被叫做“程序员之梦破碎的地方”。既然如此,这个题肯定是有难度的,尤其是其中的细节,很多,很细。 其中nums代表给定的数组,numsSize代表给定数…

短视频矩阵系统软件(源头独立开发)技术php7.40版本开发

短视频矩阵功能构建&#xff1a; 1. 关键词批量比距生成&#xff08;区域词行业词产品词&#xff09; 2. 多平台多账号一站式运营管理 3. 视频内容批量复制生成 4. 视频内容批量多平台投放 5. 视频数据分析及粉丝画像分布统计 6. 智能客服响应 7. 智能私域化线索收集 功…

第七篇【传奇开心果】beeware的toga开发移动应用示例:gui工具包介绍和常用组件使用方法示例

传奇开心果博文系列 系列博文目录beeware的toga开发移动应用示例系列博文目录一、beeware和toga介绍二、Toga常用组件使用方法示例三、归纳总结系列博文目录 beeware的toga开发移动应用示例系列 博文目录 一、beeware和toga介绍 1.BeeWare介绍 BeeWare是一个可以让Python开…

SPA单页面的讲解(超级详细)

目录 一、什么是SPA 二、SPA和MPA的区别 单页应用与多页应用的区别 单页应用优缺点 三、实现一个SPA 原理 实现 hash 模式 history模式 四、题外话&#xff1a;如何给SPA做SEO SSR服务端渲染 静态化 使用Phantomjs针对爬虫处理 一、什么是SPA SPA&#xff08;sin…

JS进阶-深入对象(二)

拓展&#xff1a;深入对象主要介绍的是Js的构造函数&#xff0c;实例成员&#xff0c;静态成员&#xff0c;其中构造函数和Java种的构造函数用法相似&#xff0c;思想是一样的&#xff0c;但静态成员和实例成员和java种的有比较大的差别&#xff0c;需要认真理解 • 创建对象三…

立创EDA学习:设计收尾工作

布线整理 ShiftM&#xff0c;关闭铺铜显示 调整结束后再使用快捷键”ShiftM“打开铺铜 过孔 在空白区域加上一些GND过孔&#xff0c;连接顶层与底层的铺铜。放置好”过孔“后&#xff0c;隐藏铺铜&#xff0c;观察刚才放置的过孔有没有妨碍到其他器件 调整铺铜 先打开铺铜区&…

C++初阶入门之命名空间和缺省参数的详细解析

个人主页&#xff1a;点我进入主页 专栏分类&#xff1a;C语言初阶 C语言进阶 数据结构初阶 Linux C初阶 欢迎大家点赞&#xff0c;评论&#xff0c;收藏。 一起努力&#xff0c;一起奔赴大厂 目录 一.前言 二.命名空间 2.1命名冲突的例子 2.2解决方案 2.3命…

机器学习---无偏估计

1. 如何理解无偏估计 无偏估计&#xff1a;就是我认为所有样本出现的概率⼀样。 假如有N种样本我们认为所有样本出现概率都是 1/N。然后根据这个来计算数学期望。此时的数学期望就是我们平常讲 的平均值。数学期望本质就 是平均值。 2. 无偏估计为何叫做“无偏”&#xff1…

设计模式-生成器设计模式

什么是生成器设计模式 众所周知我们设计代码的时候要将代码设计出模块化的&#xff0c;一个功能是一个模块&#xff0c;那么生成器设计模式&#xff0c;是将一个类再度进行了一个拆分&#xff0c;让一个类的内部进行了单一职责化&#xff0c;其实我们在平时开发的时候就会不经…

【QT+QGIS跨平台编译】之七:【libjpeg+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

文章目录 一、libjpeg介绍二、文件下载三、文件分析四、pro文件五、编译实践一、libjpeg介绍 libjpeg是一个广泛使用的jpeg图像压缩和解压的函数库,采用 C 语言开发。 2013年1月,Independent JPEG Group发布了版本9,对新引入的无损编码模式进行了改进。2022年1月,发布了版…

Python可执行文件的转换

当开发者向普通用户分享程序时&#xff0c;为了方便用户在未安装Python环境的情况 下能够正常运行&#xff0c;需要将开发好的程序进行打包&#xff0c;转换成用户可运行的文件类 型。本节将介绍在Windows和Linux两种系统下&#xff0c;将Python类型的文件转换成可执 行文件的方…

搞定JACOCO企业实战!实现测试左移!

如何将JACOCO应用到企业实战中&#xff1f; 前言 1、下载 jacoco 官网&#xff1a;https://www.jacoco.org/jacoco/index.html 2、拷贝 jar 包 3、启动 jacocoagent&#xff0c;监控被测项目 java -javaagent:jacocoagent.jarincludes*,outputtcpserver,port6300,addressloca…

Open CASCADE学习|长方体的Brep数据

pload ALL box thebox 1 2 3 dump thebox *********** Dump of thebox ************* Shape : 34, FORWARD Dump of 34 TShapes 一共34个Tshapes&#xff0c;存储如下图所述的拓扑数据 ----------------- Flags : Free, Modified, Checked, Orientable, Closed, Infinit…

PyTorch初探:基本函数与案例实践

正文&#xff1a; 在熟悉了PyTorch的安装和环境配置后&#xff0c;接下来让我们深入了解PyTorch的基本函数&#xff0c;并通过一个简单的案例来实践这些知识。 1. 基本函数 PyTorch的核心是张量&#xff08;Tensor&#xff09;&#xff0c;它类似于多维数组&#xff0c;但可以…

野火霸道V2学习笔记

野火霸道V2学习笔记 STM32F103学习笔记说明基础配置配置KeilMDK配置串口下载程序美化Keil界面配置VScode 理论知识STM32命名方式例子 置位与清零GPIOGPIO简介GPIO和引脚的区别引脚的分类 GPIO 框图讲解保护二极管推挽输出开漏输出补充: 高阻态与悬空复用功能输出输入模式GPIO框…

SkiaSharp:.NET强大而灵活的跨平台图形库

在.Net 6之前&#xff0c;我们一般是使用System.Drawing.Common来生成图像。 但在.Net 6平台需要配置&#xff0c;才能在非Windows平台使用System.Drawing.Common。而从.Net 7开始&#xff0c;非Windows不再允许使用&#xff0c;官方也给我们推荐了几个替代库。 今天我们一起来…

兄弟HL-1208黑白激光打印机清零方法

兄弟HL-1208黑白激光打印机基本参数&#xff1a; 产品类型&#xff1a;黑白激光打印机&#xff08;定位类型家用&#xff09; 最大打印幅面&#xff1a;A4 最高分辨率&#xff1a;600600dpi 黑白打印速度&#xff1a;20ppm 内存标配&#xff1a;1MB&#xff0c;最大&#…

代码随想录算法训练营29期|day31 任务以及具体安排

理论基础 关于贪心算法&#xff0c;你该了解这些&#xff01; 题目分类大纲如下&#xff1a; #算法公开课 《代码随想录》算法视频公开课 (opens new window)&#xff1a;贪心算法理论基础&#xff01; (opens new window),相信结合视频再看本篇题解&#xff0c;更有助于大家…

廖雪峰Python教程实战Day 2 - 编写Web App骨架,运行后不显示网页如何解决

教程代码如下&#xff1a; import logging; logging.basicConfig(levellogging.INFO)import asyncio, os, json, time from datetime import datetimefrom aiohttp import webdef index(request):return web.Response(bodyb<h1>Awesome</h1>)asyncio.coroutine de…