IO零拷贝

在介绍零拷贝之前我们先看看传统的 Java 网络 IO 编程是怎样的。

下面代码展示了一个典型的 Java 网络程序。

    File file = new File("index.jsp");RandomAccessFile rdf = new RandomAccessFile(file, "rw");byte[] arr = new byte[(int) file.length()];rdf.read(arr);Socket socket = new ServerSocket(8080).accept();socket.getOutputStream().write(arr);

程序中调用 RandomAccessFile 的 read 方法将 index.jsp 的内容读取到字节数组中。然后调用 write 方法将字节数组中的数据写入到 Socket 对应的输出流中发送给客户端。那么 Java 应用程序中的 read、write 方法对应到 OS 底层是怎样的呢。下图展示了这个过程。
在这里插入图片描述
图中上半部分记录了用户态和内核态的上下文切换。下半部分展示了数据的复制过程。上述 Java 代码对应的操作系统底层步骤:

  1. read 方法触发操作系统从用户态到切换到内核态。同时通过 DMA 的方式从磁盘读取文件到内核缓冲区。DMA(Direct Memory Access)是 l/O 设备与主存之间由硬件组成的直接数据通路。即不需要 CPU 拷贝数据到内存,而是直接由 DMA 引擎传输数据到内存。

  2. 紧接着发生第二次数据拷贝,即从内核缓冲区拷贝到用户缓冲区,同时发生一次内核态到用户态的上下文切换。

  3. 调用 write 方法时,触发第三次数据拷贝,即从用户缓冲区拷贝到 Socket 缓冲区。同时发生一次用户态到内核态的上下文切换。

  4. 最后数据从 Socket 缓冲区异步拷贝到网络协议引擎,这一步采用的是 DMA 方式。同时没有发生上下文切换。

  5. write 方法返回时,触发了最后一次内核态到用户态的切换。

由此可见,复制的操作太频繁,共有 2 次 DMA 拷贝、2 次 CPU 拷贝、4 次上下文切换。能否优化呢?

这就要介绍称之为"零拷贝"的技术。首先声明,零拷贝技术依赖底层 OS 内核提供的支持。Linux 中提供的这类支持有 mmap(),sendfile() 以及 splice() 系统调用。说白了就是减少数据在操作系统内核的缓冲区和用户应用程序地址空间的缓冲区之间进行拷贝。

mmap

mmap 通过内存映射,将文件通过 DMA 的方式映射到内核缓冲区。操作系统会把这段内核缓冲区与应用程序(用户空间)共享。这样,在进行网络传输时,就能减少内核空间到用户空间的拷贝次数。此时输出数据时只要从内核缓冲区拷贝到 Socket 缓冲区即可。可见减少了一次 CPU 拷贝,但是上下文切换次数并没有减少。整个过程共 2 次 DMA 拷贝,1 次 CPU 拷贝,4 次上下文切换。示意图如下。
在这里插入图片描述

sendFile

Linux 2.1 开始提供了 sendFile 函数,其基本原理是:数据根本不经过用户态,直接从 Kernel Buffer 进入到 Socket Buffer,并且由于和用户态完全无关,这就避免了一次上下文切换。下图展示了整个过程。磁盘中的数据通过 DMA 引擎从复制到内核缓冲区。调用 write 方法时从内核缓冲区拷贝到 Socket 缓冲区。由于在同一个空间,因此没有发生上下文切换。最后由 Socket 缓冲区拷贝到协议引擎。整个过程共发生了 2 次 DMA 拷贝,1 次 CPU 拷贝,3 次上下文切换。
在这里插入图片描述

在 Linux 2.4 版本中,进一步做了优化。从 Kernel Buffer 拷贝到 Socket Buffer 的操作也省了,直接拷贝到协议栈,再次减少了 CPU 数据拷贝。下图展示了整个流程。本地文件 index.jsp 要传输到网络中,只需 2 次拷贝。第一次是 DMA 引擎从文件拷贝到内核缓冲区;第二次是从内核缓冲区将数据拷贝到网络协议栈;内核缓存区只会拷贝一些元信息,比如 offset 和 length 信息到 SocketBuffer,基本无消耗。
在这里插入图片描述

综上所述,最后一种方式发生了 2 次 DMA 拷贝、0 次 CPU 拷贝、3 次上下文切换。这就是所谓的“零拷贝”实现。

总结:

因此零拷贝通常是站在操作系统的角度看,即整个过程中,内核缓冲区之间是没有重复数据的。同时伴随着更少的上下文切换。这就带来了 IO 性能质的提升!

实际开发中,mmap 和 sendFile 都有应用,可以认为是“零拷贝”的两种实现方式。它们都有各自的适用场景。mmap 更适合少量数据读写,sendFile 适合大文件传输。sendFile 可以利用 DMA 方式将内核缓冲区将数据拷贝到网络协议栈,减少 CPU 拷贝,而 mmap 则不能(必须从内核拷贝到 Socket 缓冲区)。

案例:

RocketMQ 在 CommitLog 和 CosumerQueue 的实现中都采用了 mmap。而 Kafka 的零拷贝实现则使用了 sendFile。

RocketMQ 和 Kafka 高性能的原因之一便是顺序写入和近似顺序读取 + 零拷贝。


引用:https://zhuanlan.zhihu.com/p/543661648

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

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

相关文章

Tcl语言语法精炼总结

一、置换符号 1.变量置换 $ TCl解释器会将认为$后面为变量名,将变量名置换成它的值 2.命令置换 [] []内是一个独立的TCL语句 3.反斜杠置换 \ 换行符、空格、[、$等被TCL解释器当作特殊符号处理。加上反斜杠后变成普通字符 \t TAB \n 换行符 4.双引号 “” “…

鸿蒙开发之页面与组件生命周期

一、页面间的跳转 创建文件的时候记得选择创建page文件,这样就可以在main->resources->profile->main_pages.json中自动形成页面对应的路由了。如果创建的时候你选择了ArkTS文件,那么需要手动修改main_pages.json文件中,添加相应的…

关于大模型ChatGLM3-6B在CPU下运行

最近在调研市场上语言大模型,为公司的产品上虚拟人的推出做准备。各厂提供语言模型都很丰富,使用上也很方便,有API接口可以调用。但唯一的不足,对于提供给百万用户使用的产品,相比价格都比较贵。所以对ChatGLM3-6B的使…

基于pandoraNext使用chatgpt4

1.登陆GitHub 获取pandoraNext项目GitHub - pandora-next/deploy: Pandora Cloud Pandora Server Shared Chat BackendAPI Proxy Chat2API Signup Free PandoraNext. New GPTs(Gizmo) UI, All in one! 在release中选择相应版本操作系统的安装包进行下载 2.获取license_…

分享一个很方便查看所有目录的文件浏览器

分享一个很方便查看所有目录的文件浏览器RootExplorer.apk 链接:文件分享 密码:zxhi33 前提是要设备root过,这样可以方便查看整个设备所有目录的各种文件。 最近客户想要定制Launcher3桌面各种小部件Widget 时间、天气、日历、新闻。 按照客…

最新鸿蒙HarmonyOS4.0开发登陆的界面1

下载deveco-studio 说明一下,本人只是学习中,现在只是拿着vue及uniapp的经验在一点一点的折腾,不过现在看来,鸿蒙入门并不是很难。也许是自己没有深入下去。 https://developer.harmonyos.com/cn/develop/deveco-studio#download…

docker使用详解

介绍 Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化。 Docker基于轻量级虚拟化技术,整个项目基于Go语言开…

Mybatis源码解析6:Mapper执行流程2-三个Handler

Mybatis源码解析6:Mapper执行流程2-三个Handler 1.项目结构2. 源码分析2.1 StatementHandler分析 BaseStatementHandler#prepare2.2 ParameterHandler分析 DefaultParameterHandler#setParameters2.3 ResultSetHandler分析 1.项目结构 2. 源码分析 之前已经对 Sim…

Scrapy爬虫学习

Scrapy爬虫学习一 1 scrapy框架1.1 scrapy 是什么1.2 安装scrapy 2 scrapy的使用2.1创建scrapy项目2.2 创建爬虫文件2.3爬虫文件的介绍2.4 运行爬虫文件 3 爬取当当网前十页数据3.1 dang.py:爬虫的主文件3.2 items.py 定义数据结构3.3 pipelines.py 管道3.4 执行命令…

总结了人工智能领域,能源领域,电气领域比较好中的一些sci期刊!!仅供参考

文章目录 前言一、总结了人工智能领域,能源领域,电气领域比较好中的一些sci期刊 总结 前言 期刊查询网站: https://www.letpub.com.cn/index.php?pagejournalapp&viewsearch 链接: 点我跳转期刊查询网站 一、总结了人工智能领域&#…

React 列表页实现

一、介绍 列表页是常用的功能,从后端获取列表数据,刷新到页面上。开发列表页需要考虑以下技术要点:1.如何翻页;2.如何进行内容搜索;3.何时进行页面刷新。 二、使用教程 1.user-service 根据用户id获取用户列表,返回…

【Spring】02 Bean 的命名

文章目录 1. 定义2. 使用优势3. 如何命名4. 注解驱动5. 最佳实践1)使用明确的业务名词2)避免缩写和首字母缩略词2)不要过度使用别名 结语 在 Spring 框架中,Bean 是应用程序中的主要组件,负责承载和管理应用的核心功能…

【python-wrf】绘制wrf中的土地利用报错内容及其解决方法

从该代码处绘制wrf中的土地利用报错内容及其解决方法 1.报错内容: 微信公众平台 (qq.com)https://mp.weixin.qq.com/s/Cn0vhvfroVADPnT237LXNw --------------------------------------------------------------------------- AttributeError …

14--常用类和基础API--04

1、Arrays类 1.1 Arrays类概述 java.util.Arrays 此类包含用来操作数组的各种方法,比如排序和搜索等。其所有方法均为静态方法,调用起来非常简单。简单来说:Arrays这个是专门用来操作数组相关的工具类 1.2 Arrays类常用方法 public static…

OkHttp: 使用入门

文章目录 1. 领域对象1. Request2. Response2.1 请求重写2.2 重写返回2.3 跟踪请求2.4 自动重试 3. Calls 2. 创建连接1、URLs2、Addresses3、Routes4、Connections 3. 使用案例1、同步GET请求2、异步GET请求3、发送和读取HTTP头4、POST 字符传5、POST 流6、POST 文件内容7、PO…

mysql 字符串合并方法以及合并为null问题

concat()不推荐 mysql一般提供了两种一种是concat()函数一种是concat_ws()函数,前者合并字符串有个弊端,合并字段不能有null值, 否则如下图合并后会是null concat_ws()推荐 concat_ws()函数可以解决合并字符串为null问题,conca…

Go并发编程:保障安全与解锁奥秘

一、并发安全与锁 1、并发安全 有时候在 Go 代码中可能会存在多个 goroutine 同时操作一个资源(临界区),这种情况会发生竞态问题(数据竞态)类比现实生活中的例子有十字路口被各个方向的汽车竞争;还有火车…

使用Microsoft Dynamics AX 2012 - 8. 财务管理

财务管理的主要职责是控制和分析与货币金额有关的所有交易。这些事务发生在整个组织的业务流程中。 因此,财务管理是企业管理解决方案的核心领域。在Dynamics AX中,支持所有部门业务流程的应用程序的深度集成可立即提供准确的财务数据。 分类账交易的原…

K8S(三)—组件

目录 k8s组件控制平面组件(Control Plane Componentskube-apiserveretcdkube-schedulerkube-controller-managercloud-controller-managerNode 组件kubelet(单独的进程)kube-proxy(单独的进程)容器运行时(C…

Redis常问面试题

Redis常问面试题 Redis常问面试题1、Redis 支持哪几种数据类型?2、Redis 做登录是怎么实现的?和传统session有何区别?3、什么是缓存穿透?4、什么是缓存雪崩?5、什么是缓存击穿?6、Redis高可用的几种实现方式…