io.netty学习(八)零拷贝原理

news2024/12/24 8:34:34

目录

零拷贝

传统I/O操作存在的性能问题

零拷贝技术原理

虚拟内存

mmap/write 方式

sendfile 方式

带有 scatter/gather 的 sendfile方式

splice 方式

总结


io.netty学习使用汇总

零拷贝

零拷贝(Zero-Copy)是一种 I/O 操作优化技术,可以快速高效地将数据从文件系统移动到网络接口,而不需要将其从内核空间复制到用户空间。其在 FTP 或者 HTTP 等协议中可以显著地提升性能。但是需要注意的是,并不是所有的操作系统都支持这一特性,目前只有在使用 NIO 和 Epoll 传输时才可使用该特性。

需要注意,它不能用于实现了数据加密或者压缩的文件系统上,只有传输文件的原始内容。这类原始内容也包括加密了的文件内容。

 

传统I/O操作存在的性能问题

如果服务端要提供文件传输的功能,我们能想到的最简单的方式是:将磁盘上的文件读取出来,然后通过网络协议发送给客户端。

传统 I/O 的工作方式是,数据读取和写入是从用户空间到内核空间来回复制,而内核空间的数据是通过操作系统层面的 I/O 接口从磁盘读取或写入。

代码通常如下,一般会需要两个系统调用:

read(file, tmp_buf, len);
write(socket, tmp_buf, len);

代码很简单,虽然就两行代码,但是这里面发生了不少的事情。

 首先,期间共发生了 4 次用户态与内核态的上下文切换,因为发生了两次系统调用,一次是 read() ,一次是 write(),每次系统调用都得先从用户态切换到内核态,等内核完成任务后,再从内核态切换回用户态。

上下文切换到成本并不小,一次切换需要耗时几十纳秒到几微秒,虽然时间看上去很短,但是在高并发的场景下,这类时间容易被累积和放大,从而影响系统的性能。

其次,还发生了 4 次数据拷贝,其中两次是 DMA 的拷贝,另外两次则是通过 CPU 拷贝的,下面说一下这个过程:

  • 第一次拷贝,把磁盘上的数据拷贝到操作系统内核的缓冲区里,这个拷贝的过程是通过 DMA 搬运的。

  • 第二次拷贝,把内核缓冲区的数据拷贝到用户的缓冲区里,于是我们应用程序就可以使用这部分数据了,这个拷贝到过程是由 CPU 完成的。

  • 第三次拷贝,把刚才拷贝到用户的缓冲区里的数据,再拷贝到内核的 socket 的缓冲区里,这个过程依然还是由 CPU 搬运的。

  • 第四次拷贝,把内核的 socket 缓冲区里的数据,拷贝到网卡的缓冲区里,这个过程又是由 DMA 搬运的。

这种简单又传统的文件传输方式,存在冗余的上文切换和数据拷贝,在高并发系统里是非常糟糕的,多了很多不必要的开销,会严重影响系统性能。

所以,要想提高文件传输的性能,就需要减少「用户态与内核态的上下文切换」和「内存拷贝」的次数。

零拷贝技术原理

零拷贝主要是用来解决操作系统在处理 I/O 操作时,频繁复制数据的问题。关于零拷贝主要技术有 mmap+writesendfilesplice等几种方式。

虚拟内存

在了解零拷贝技术之前,先了解虚拟内存的概念。

所有现代操作系统都使用虚拟内存,使用虚拟地址取代物理地址,主要有以下几点好处:

  • 多个虚拟内存可以指向同一个物理地址。

  • 虚拟内存空间可以远远大于物理内存空间。

利用上述的第一条特性可以优化,可以把内核空间和用户空间的虚拟地址映射到同一个物理地址,这样在 I/O 操作时就不需要来回复制了。

如下图展示了虚拟内存的原理。

mmap/write 方式

使用mmap/write方式替换原来的传统I/O方式,就是利用了虚拟内存的特性。下图展示了mmap/write原理:

 整个流程的核心区别就是,把数据读取到内核缓冲区后,应用程序进行写入操作时,直接把内核的Read Buffer的数据复制到Socket Buffer以便写入,这次内核之间的复制也是需要CPU的参与的。

上述流程就是少了一个 CPU COPY,提升了 I/O 的速度。不过发现上下文的切换还是4次并没有减少,这是因为还是要应用程序发起write操作。

那能不能减少上下文切换呢?这就需要sendfile方式来进一步优化了。

sendfile 方式

从 Linux 2.1 版本开始,Linux 引入了 sendfile来简化操作。sendfile方式可以替换上面的mmap/write方式来进一步优化。

sendfile将以下操作:

  mmap();
  write();

替换为:

 sendfile();

这样就减少了上下文切换,因为少了一个应用程序发起write操作,直接发起sendfile操作。

下图展示了sendfile原理:

sendfile方式只有三次数据复制(其中只有一次 CPU COPY)以及2次上下文切换。

那能不能把 CPU COPY 减少到没有呢?这样需要带有 scatter/gathersendfile方式了。

带有 scatter/gather 的 sendfile方式

Linux 2.4 内核进行了优化,提供了带有 scatter/gather 的 sendfile 操作,这个操作可以把最后一次 CPU COPY 去除。其原理就是在内核空间 Read BUffer 和 Socket Buffer 不做数据复制,而是将 Read Buffer 的内存地址、偏移量记录到相应的 Socket Buffer 中,这样就不需要复制。其本质和虚拟内存的解决方法思路一致,就是内存地址的记录。

下图展示了scatter/gather 的 sendfile 的原理:

 scatter/gather 的 sendfile 只有两次数据复制(都是 DMA COPY)及 2 次上下文切换。CUP COPY 已经完全没有。不过这一种收集复制功能是需要硬件及驱动程序支持的。

splice 方式

splice 调用和sendfile 非常相似,用户应用程序必须拥有两个已经打开的文件描述符,一个表示输入设备,一个表示输出设备。与sendfile不同的是,splice允许任意两个文件互相连接,而并不只是文件与socket进行数据传输。对于从一个文件描述符发送数据到socket这种特例来说,一直都是使用sendfile系统调用,而splice一直以来就只是一种机制,它并不仅限于sendfile的功能。也就是说 sendfile 是 splice 的一个子集。

在 Linux 2.6.17 版本引入了 splice,而在 Linux 2.6.23 版本中, sendfile 机制的实现已经没有了,但是其 API 及相应的功能还在,只不过 API 及相应的功能是利用了 splice 机制来实现的。

和 sendfile 不同的是,splice 不需要硬件支持。

总结

无论是传统的 I/O 方式,还是引入了零拷贝之后,2 次 DMA copy是都少不了的。因为两次 DMA 都是依赖硬件完成的。所以,所谓的零拷贝,都是为了减少 CPU copy 及减少了上下文的切换。

下图展示了各种零拷贝技术的对比图:

CPU拷贝DMA拷贝系统调用上下文切换
传统方法22read/write4
内存映射12mmap/write4
sendfile12sendfile2
scatter/gather copy02sendfile2
splice02splice0

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

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

相关文章

总结906

学习目标: 月目标:6月(线性代数强化9讲,背诵15篇短文,考研核心词过三遍) 周目标:线性代数强化3讲,英语背3篇文章并回诵,检测 每日规划 今日已做: 1.回环背诵…

chatgpt赋能python:Python捕捉按键:探索基础和应用

Python捕捉按键:探索基础和应用 Python作为高级编程语言,可以用于各种任务,例如数据分析、机器学习、图形用户界面等等。其中,捕捉用户键盘输入是一个常见的任务,它可以用于实现简单的游戏、命令行应用和用户交互&…

Redis持久化说明及其单台Linux服务器搭建Redis集群架构

一.Redis持久化方式 1.1 RDB快照 说明:RDB快照主要以二进制文件的形式进行存储数据,主要以文件名dump.rdb进行存储,主要设置redis.conf里面设置’save 60 1000’命令可以开启, 表示在60秒内操作1000次进行一次备份数据。在客户端…

《网络安全0-100》网络安全工具

网络安全工具 抓包工具 抓包工具是网络安全领域中常用的一种工具,用于捕获和分析网络数据包,帮助用户了解网络流量、发现网络攻击和漏洞等问题。以下是几个常用的抓包工具: Wireshark:Wireshark是一种开放源代码的网络协议分析工…

软考A计划-系统集成项目管理工程师-信息化知识(五)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列 👉关于作者 专注于Android/Unity和各种游戏开发技巧&#xff…

Unity核心6——Animation

一、动画窗口 ​ 通过 Window --> Animation --> Animation 打开 Animation 窗口 ​ Animation窗口主要用于在 Unity 内部创建和修改动画,所有在场景中的对象都可以通过 Animation 窗口为其制作动画 ​ 原理: ​ 制作动画时:记录在…

chatgpt赋能python:Python提供的68个内置函数:一个全面的指南

Python提供的68个内置函数:一个全面的指南 Python是一种强大的编程语言,具有出色的生态系统和强大的功能。它提供了许多内置函数,这些函数可以使你的编程任务变得更加容易和高效。本篇文章将介绍Python提供的68个内置函数,帮助你…

chatgpt赋能python:Python排版快捷键:提高效率的必备技能

Python排版快捷键:提高效率的必备技能 随着Python编程语言的广泛应用,作为开发者,我们不仅需要注重代码质量,还需要注重代码的可读性。在编写Python代码时,排版也是一项重要的任务。好的排版不仅使代码更易于理解&…

k8s日志收集组件 Grafana loki --- 理论篇

当我们在k8s上运行程序时,习惯的会使用ELK来收集和查询程序运行日志。今天我们介绍一款新的专为日志收集而生的神器:Grafana loki。Grafana Loki 是一组组件,可以组合成一个功能齐全的日志堆栈。 与其他日志记录系统不同,Loki 仅…

VUE 2X 数据代理 ④

目录 文章有误请指正,如果觉得对你有用,请点三连一波,蟹蟹支持✨ V u e j s Vuejs Vuejs数据代理 什么是数据代理❓ 代理底层~ D e f i n e P r o p e r y DefinePropery DefinePropery V u e Vue Vue数据代理原理理解总结 文章有误…

Xubuntu22.04之便签工具(一百八十)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…

三、Kafka的消费全流程

Kafka的消费全流程 我们接着继续去理解最后这条消息是如何被消费者消费掉的。其中最核心的有以下内容。 1、多线程安全问题 2、群组协调 3、分区再均衡 多线程安全问题 当多个线程访问某个类时,这个类始终都能表现出正确的行为,那么就称这个类是线…

深度学习实战39-U-Net模型在医学影像识别分割上的应用技巧,以细胞核分割任务为例

大家好,我是微学AI,今天给大家介绍一下深度学习实战39-U-Net模型在医学影像识别分割上的应用技巧,以细胞核分割任务为例。本文将介绍在医学影像分割领域中应用U-Net模型的方法。我们将从U-Net模型原理出发,并使用PyTorch搭建模型,详细展示模型代码。接着,我们将展示一些医…

I.MX RT1170之FlexSPI(2):LUT表格的组成和FlexSPI结构体配置

从上一节FlexSPI的框图中可知,SEQ_CTL实现了对外部存储器的时序控制。不同的存储器有着不同的时序,这个时序就是由LUT(Look Up Table)指定的。LUT有它自己的寄存器,当我们设置好之后,外部存储器的读、写和擦除等操作就会根据LUT寄…

《网络安全0-100》安全事件案例

网络安全事件案例分析 2017年Equifax数据泄露事件 Equifax是美国一家信用评级机构,2017年9月,该公司披露发生了一起重大的数据泄露事件,涉及1.43亿美国人的个人信息,包括姓名、出生日期、社会安全号码等敏感信息。经过调查&#…

《OpenCV 计算机视觉编程攻略》学习笔记(一:图像编程入门)

1、参考引用 OpenCV 计算机视觉编程攻略(第3版)本书结合 C 和 OpenCV 3.2 全面讲解计算机视觉编程所有代码均在 Ubuntu 系统中用 g 编译执行 0. 安装 OpenCV 库 在Ubuntu上安装OpenCV及使用OpenCV 库分为多个模块,常见模块如下 opencv_core …

Python数据可视化 - 使用Python dash搭建交互式地图可视化看板

1.前言 前几年刚接触Dash库的时候,Dash生态还不太成熟,做些简单的web还行,复杂的、系统性还是得用flask或django来实现。随着这两年dash的不断迭代更新,以及dash大佬feffery相继开发了feffery_antd_components、feffery_leaflet_…

编译原理笔记7:语法分析(1)语法分析器的任务、语法错误的处理

目录 语法分析器是编译器前端的核心语法错误的处理语法错误的处理目标语法错误的基本恢复策略 语法分析器是编译器前端的核心 语法分析器的两项主要任务,分别: 是根据词法分析器提供的记号流,为语法正确的输入构造分析树(或语法树…

uboot下UCLASS框架详解---结合项目工作中spi master和flash驱动开发

文章目录 一、综述二、UCLASS架构解析2.1 uclass2.2 udevice2.3 uclass driver2.4 driver2.4.1 spi master driver 三、uboot代码解析3.1 DM的初始化3.2 spi norflash设备识别3.3 设备树内容3.4 .config配置3.5 spi读写测试 四、其他相关链接1、SPI协议详细总结附实例图文讲解通…

IDEA合并分支和.gitignore可能遇到的问题

将本地的 v1 分支合并到 master 分支上 1.确认你在 master 分支上,在命令行执行以下命令,这将切换到 master 分支。 git checkout master 2.拉取最新代码 在合并分支之前,请确保您的代码库是最新的。在命令行执行以下命令,这将从…