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

文章目录

  • 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.mzph.cn/news/654135.shtml

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

相关文章

后台管理系统模板搭建/项目配置

1 项目初始化 一个项目要有统一的规范&#xff0c;需要使用eslintstylelintprettier来对我们的代码质量做检测和修复&#xff0c;需要使用husky来做commit拦截&#xff0c;需要使用commitlint来统一提交规范&#xff0c;需要使用preinstall来统一包管理工具。 1.1 环境准备 1…

idea 创建 spring boot

1.创建步骤 2. 编码添加 2.1 这是自动生成的启动函数 package com.example.comxjctest4;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;SpringBootApplication public class Application {publi…

MySql的使用方法

一.什么是MySql MySql是一种数据库管理系统&#xff0c;是用来存储数据的&#xff0c;可以有效的管理数据&#xff0c;数据库的存储介质为硬盘和内存。 和文件相比&#xff0c;它具有以下优点&#xff1a; 文件存储数据是不安全的&#xff0c;且不方便数据的查找和管理&#xf…

【3分钟开服】幻兽帕鲁服务器一键部署保姆教程,PalWorld开服联机教程

在帕鲁的世界&#xff0c;你可以选择与神奇的生物「帕鲁」一同享受悠闲的生活&#xff0c;也可以投身于与偷猎者进行生死搏斗的冒险。帕鲁可以进行战斗、繁殖、协助你做农活&#xff0c;也可以为你在工厂工作。你也可以将它们进行售卖&#xff0c;或肢解后食用。 想要部署属于自…

从零开发短视频电商 Tesseract OCR识别增强

文章目录 概要图像预处理阶段默认反转图像重新缩放二值化噪音消除膨胀/腐蚀旋转/偏移校正边框缺少边框边框太大扫描边框去除 透明度/Alpha通道 引擎处理阶段语言模型配置提高识别速度词典、单词列表和模式表格识别 使用 Tesseract OCR 的 GUI 和其他项目 原文如下&#xff1a; …

TypeScript实战系列之合理运用类型

目录 介绍any 和 unknownerve 的用途断言type 和 interfacedeclare 关键字的作用联合类型 和 类型守卫交叉类型 介绍 这篇主要介绍下ts 常用的基本类型和一些常用的技巧性技能 any 和 unknow any 和 unknown 是两个类型关键字&#xff0c;它们用于处理类型不确定或未知的情况…

【Sql Server】新手一分钟看懂在已有表基础上修改字段默认值和数据类型

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是《Sql Server》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对…

力扣日记1.28-【回溯算法篇】93. 复原 IP 地址

力扣日记&#xff1a;【回溯算法篇】93. 复原 IP 地址 日期&#xff1a;2023.1.28 参考&#xff1a;代码随想录、力扣 93. 复原 IP 地址 题目描述 难度&#xff1a;中等 有效 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&…

IP地址定位技术的巧妙运用:企业网络安全的坚实防线

在当今数字时代&#xff0c;企业网络安全成为了至关重要的议题。面对不断增长的网络威胁&#xff0c;企业不得不采用创新性技术来保护其机密信息和关键系统。IP地址定位技术作为一种强大的工具&#xff0c;为企业提供了一种新颖而高效的网络安全保护手段。 IP地址定位技术简介 …

前端Vue v-for 的使用

目录 ​编辑 简介 使用方式 基本使用 v-for"(item, index)中item和index作用 示例 迭代对象 示例 结果 前言-与正文无关 生活远不止眼前的苦劳与奔波&#xff0c;它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界中&#xff0c;我们往往容易陷入…

证券公司怎么选择?福州开股票账户佣金最低是多少?怎么开低佣金账户?

股票交易佣金是指投资者在进行股票交易时&#xff0c;需要向券商支付的手续费。具体的佣金费用根据券商的政策而有所不同&#xff0c;一般分为固定佣金和按比例佣金两种方式。 固定佣金是指交易每一笔固定收取一定金额的佣金&#xff0c;通常适用于较小交易量的投资者&#xf…

github ssh ssh-keygen

生成和使用 SSH 密钥对是一种安全的身份验证方式&#xff0c;用于在你的本地系统和 GitHub 之间进行身份验证。以下是在 GitHub 上生成和使用 SSH 密钥对的基本步骤&#xff1a; 1. 生成 SSH 密钥对 在命令行中执行以下命令来生成 SSH 密钥对&#xff1a; ssh-keygen -C &q…

ATT汇编

指令后缀 AT&T格式的汇编指令有不同的后缀 其中 b表示byte&#xff0c;字节 w表示word&#xff0c;字/两字节 l表示long&#xff0c;32位系统下的long是4字节 q表示quad&#xff0c;意味四重&#xff0c;表示4个字/8字节 寄存器用途 参见 AT&T的汇编世界 - Gemfield…

把数组中的key都取出来然后去重

今日接到一个小需求&#xff0c;一张表有类似这样的数据&#xff1a;&#xff08;下面是一行&#xff09; 但是每行的数据&#xff0c;主要是key不一样&#xff0c;我们想把所有的key取出来&#xff0c;并且做个去重。 首先我先在mysql中&#xff0c; SELECT GROUP_CONCAT(RE…

蓝桥杯---九数组分数

1,2,3 ... 9 这九个数字组成一个分数,其值恰好为1/3,如何组法? 下面的程序实现了该功能,请填写划线部分缺失的代码。 注意,只能填写缺少的部分,不要重复抄写已有代码。不要填写任何多余的文字。 代码 public class _05九数组分数 {public static void test(int[] x){int a …

Linux, Certbot快速申请免费https证书

linux环境. 更新apt,为了能正确的下载certbot apt update 安装certbot apt install certbot 如果之前nginx已经开启着了,先关掉,防止端口占用 nginx -s stop 运行certbot开始获取证书文件 certbot certonly 输入1直接回车,意思就是让certbot模拟一个web服务器执行下面的…

探秘Photoshop | 一站式了解所有相关信息

Photoshop是迄今为止世界上最强大的图像编辑软件&#xff0c;它已成为许多涉及图像处理的行业标准。软件技术一天行千里&#xff0c; Photoshop也在不断更新&#xff0c;从1990年开始发布&#xff0c; photoshop1.0到最新的 2018Photoshop... 几乎每隔一年&#xff0c;Photosho…

Apache 辅助系统工具

一丶Apache Sqoop 1.Sqoop的介绍&#xff1a; Sqoop的工作机制是将导入或者导出的命令翻译成MapReduce实现&#xff0c;Sqoop可以理解为&#xff1a;SQL到Hadoop或者Hadoop到SQL 2.Sqoop的安装 配置文件修改&#xff1a; cd $SQOOP_HOME/conf mv sqoop-env-template.sh sqo…

Dubbo Consumer 对Provider的protocol选择逻辑

一、简介 dubbo consumer 如果没有指定protocol参数&#xff0c;默认会将provider注册的protocol provider url都获取并转换为Invoker放到Directory中。如果consumer指定了protocol则会在Directory中选择相应的protocol provider url转换为Invoker放在Directory中。 二、代码分…

力扣hot100 柱状图中最大的矩形 单调栈

Problem: 84. 柱状图中最大的矩形 文章目录 思路复杂度Code 思路 &#x1f468;‍&#x1f3eb; 参考地址 复杂度 时间复杂度: O ( n ) O(n) O(n) 空间复杂度: O ( n ) O(n) O(n) Code class Solution {public static int largestRectangleArea(int[] height){Stack&l…