Netty中的零拷贝机制

news2024/11/26 19:46:16

零拷贝机制(Zero-Copy)是在操作数据时不需要将数据从一块内存区域复制到另一块内存区域的技术,这样就避免了内存的拷贝,使得可以提高CPU的。零拷贝机制是一种操作数据的优化方案,通过避免数据在内存中拷贝达到的提高CPU性能的方案。

1.操作系统的零拷贝机制

操作系统的存储空间包含硬盘和内存,而内存又分成用户空间和内核空间。以从文件服务器下载文件为例,服务器需要将硬盘中的数据通过网络通信发送给客户端,大致流程如下:

第一步:操作系统通过DMA传输将硬盘中的数据复制到内核缓冲区

第二步:操作系统执行read方法将内核缓冲区的数据复制到用户空间

第三步:操作系统执行write方法将用户空间的数据复制到内核socket缓冲区

第四步:操作系统通过DMA传输将内核socket缓冲区数据复制给网卡发送数据

流程如下图示:

 

整个流程中:DMA拷贝2次、CPU拷贝2次、用户空间和内核空间切换4次

整个流程从内核空间和硬件之间数据拷贝是DMA复制传输,内核空间和用户空间之间数据拷贝是通过CPU复制.另外CPU除了需要参与拷贝任务,还需要多次从内核空间和用户空间之间来回切换,无疑都额外增加了很多的CPU工作负担。

所以操作系统为了减少CPU拷贝数据带来的性能消耗,提供了几种解决方案来减少CPU拷贝次数

1.1.使用mmap函数

mmap函数的作用相当于是内存共享,将内核空间的内存区域和用户空间共享,这样就避免了将内核空间的数据拷贝到用户空间的步骤,通过mmap函数发送数据时上述的步骤如下:

第一步:操作系统通过DMA传输将硬盘中的数据复制到内核缓冲区,执行了mmap函数之后,拷贝到内核缓冲区的数据会和用户空间进行共享,所以不需要进行拷贝

第二步:CPU将内核缓冲区的数据拷贝到内核空间socket缓冲区

第三步:操作系统通过DMA传输将内核socket缓冲区数据拷贝给网卡发送数据

流程如下图示:

整个流程中:DMA拷贝2次、CPU拷贝1次、用户空间和内核空间切换4次

可以发现此种方案避免了内核空间和用户空间之间数据的拷贝工作,但是在内核空间内部还是会有一次数据拷贝过程,而且CPU还是会有从内核空间和用户空间的切换过程

1.2.使用sendfile函数

senfile函数的作用是将一个文件描述符的内容发送给另一个文件描述符。而用户空间是不需要关心文件描述符的,所以整个的拷贝过程只会在内核空间操作,相当于减少了内核空间和用户空间之间数据的拷贝过程,而且还避免了CPU在内核空间和用户空间之间的来回切换过程。整体流程如下:

第一步:通过DMA传输将硬盘中的数据复制到内核页缓冲区

第二步:通过sendfile函数将页缓冲区的数据通过CPU拷贝给socket缓冲区

第三步:网卡通过DMA传输将socket缓冲区的数据拷贝走并发送数据

流程如下图示:

整个过程中:DMA拷贝2次、CPU拷贝1次、内核空间和用户空间切换0次

可以看出通过sendfile函数时只会有一次CPU拷贝过程,而且全程都是在内核空间实现的,所以整个过程都不会使得CPU在内核空间和用户空间进行来回切换的操作,性能相比于mmap而言要更好

另外如果硬件支持的话,sendfile函数还可以直接将文件描述符和数据长度发送给socket缓冲区,然后直接通过DMA传输将页缓冲区的数据拷贝给网卡进行发送即可,这样就避免了CPU在内核空间内的拷贝过程,流程如下:

第一步:通过DMA传输将硬盘中的数据复制到内核页缓冲区

第二步:通过sendfile函数将页缓冲区数据的文件描述符和数据长度发送给socket缓冲区

第三步:网卡通过DMA传输根据文件描述符和文件长度直接从页缓冲区拷贝数据

如下图示:

整个过程中:DMA拷贝2次、CPU拷贝0次、内核空间和用户空间切换0次

所以整个过程都是没有CPU拷贝的过程的,实现了真正的CPU零拷贝机制

1.3.使用slice函数

splice函数的作用是将两个文件描述符之间建立一个管道,然后将文件描述符的引用传递过去,这样在使用到数据的时候就可以直接通过引用指针访问到具体数据。过程如下:

第一步:通过DMA传输将文件复制到内核页缓冲区

第二步:通过splice函数在页缓冲区和socket缓冲区之间建立管道,并将文件描述符的引用指针发送给socket缓冲区

第三步:网卡通过DMA传输根据文件描述符的指针直接访问数据

如下图示:

整个过程中:DMA拷贝2次、CPU拷贝0次、内核空间和用户空间切换0次

可以看出通过slice函数传输数据时同样可以实现CPU的零拷贝,且不需要CPU在内核空间和用户空间之间来回切换

总结:实际上操作系统的零拷贝机制只是针对于CPU的零拷贝,而内核空间和硬件之间还是会存在数据拷贝的过程,只不过通过DMA传输,而不需要CPU来参与数据的拷贝过程可以看出通过mmap函数可以减少一次CPU拷贝,但是还会有一个CPU拷贝。而使用sendfile和splice函数都已经实现了CPU零拷贝而实现了数据传输过程。

2.Java中的零拷贝机制

Java的应用程序经常会遇到数据传输的场景,在Java NIO包中就提供了零拷贝机制的实现,主要是通过NIO包中的FileChannel实现FileChannel提供了transferTo和transferFrom方法,都是采用了调用底层操作系统的sendfile函数来实现的CPU零拷贝机制。

kafka服务器就是采用了FileChannel的transfer方法实现了高性能的IO传输操作。

Netty中的零拷贝机制Netty作为NIO的高性能网络通信框架,同样也实现了零拷贝机制,不过和操作系统的零拷贝机制则不是一个概念。

Netty中的零拷贝机制体现在多个场景:

  1. 使用直接内存,在进行IO数据传输时避免了ByteBuf从堆外内存拷贝到堆内内存的步骤,而如果使用堆内内存分配ByteBuf的话,那么发送数据时需要将IO数据从堆内内存拷贝到堆外内存才能通过Socket发送

  2. Netty的文件传输使用了FileChannel的transferTo方法,底层使用到sendfile函数来实现了CPU零拷贝

  3. Netty中提供CompositeByteBuf类,用于将多个ByteBuf合并成逻辑上的ByteBuf,避免了将多个ByteBuf拷贝成一个ByteBuf的过程

  4. ByteBuf支持slice方法可以将ByteBuf分解成多个共享内存区域的ByteBuf,避免了内存拷贝

零拷贝总结

等一下,不是说零拷贝吗?为什么还是要 2 次拷贝?

首先我们说零拷贝,是从操作系统的角度来说的。因为内核缓冲区之间,没有数据是重复的(只有 kernel buffer 有一份数据,sendFile 2.1 版本实际上有 2 份数据,算不上零拷贝)。例如我们刚开始的例子,内核缓存区和 Socket 缓冲区的数据就是重复的。

而零拷贝不仅仅带来更少的数据复制,还能带来其他的性能优势,例如更少的上下文切换,更少的 CPU 缓存伪共享以及无 CPU 校验和计算。

再稍微讲讲 mmap 和 sendFile 的区别。

mmap 适合小数据量读写,sendFile 适合大文件传输。

mmap 需要 4 次上下文切换,3 次数据拷贝;sendFile 需要 3 次上下文切换,最少 2 次数据拷贝。

sendFile 可以利用 DMA 方式,减少 CPU 拷贝,mmap 则不能(必须从内核拷贝到 Socket 缓冲区)。

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

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

相关文章

C++基础(5)——类和对象(3)

前言 本文主要介绍了C中类和对象的基本知识 4.3.1:成员变量和成员函数分开存储 只有非静态成员变量才属于类的对象上 C语言中结构体为空时使用sizeof()打印的结果是0 C中类和结构体为空,用sizeof关键字可以算出是空类占1字节、…

OpenCV项目开发实战--图像识别和目标检测之(手写数字分类)

文末附基于Python和C++两种方式实现的测试代码下载链接 在本教程中,我们将使用 OpenCV 构建一个简单的手写数字分类器。一如既往,我们将分享用 C++ 和 Python 编写的代码。 最后两个帖子旨在提供了解基础知识所需的教育。这篇文章旨在提供成功实施图像分类器所需的培训。那么…

SpringBoot集成阿里云OSS实现图片存储服务

SpringBoot集成阿里云OSS实现图片存储服务 1、OSS概述2、账号申请2.1 购买服务2.2 创建Bucket 3、抽取模板工具OssProperties配置类OssTemplate模板对象AutoConfiguration配置类yml配置内容 4、测试 阿里云OSS(Object Storage Service)是一种强大的云存储…

ASO优化之关于应用商店的展示量

应用的展示数据代表应用在整个应用市场内的曝光次数,被展示的位置包括:首页精品推荐,搜索结果列表,应用详情页等。 应用的展示数据是衡量ASO搜索优化的关键指标。当关键词的覆盖数增加了,展示的次数没有增加&#xff…

【Nacos源码系列】服务注册的原理

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 文章目录 Nacos介绍服务注册客户端注册服务端 总结 Nacos介绍 Nacos是一个基于云原生的动态服务发现、配置管理和服务治理平台&#xff…

cppzmq编译和使用(ubuntu22.04)

libzmq libzmq,也称为 ZeroMQ,是一个高性能、异步消息传递库,用于构建分布式和并发系统。它提供了简单而强大的原语,使得开发者可以方便地在应用程序之间进行异步通信。 以下是对 libzmq 的详细介绍: 简介&#xff1…

VOC数据洞察在淘宝详情页的应用与实践

本专题共10篇内容,包含淘宝APP基础链路过去一年在用户体验数据科学领域(包括商详、物流、性能、消息、客服、旅程等)一些探索和实践经验,本文为该专题第二篇。 在商详页基于用户动线和VOC挖掘用户决策因子带来浏览体验提升&#x…

如何使用 PowerPoint 2021 制作演示文稿(PPT)?

软件安装:办公神器office2021安装教程,让你快速上手_正经人_____的博客-CSDN博客 引言 PowerPoint 是一款非常常用的演示文稿制作工具,它可以帮助您创建漂亮的幻灯片,展示您的想法和信息。如果您是 PowerPoint 的新手&#xff…

如何选择初始化向量【密码学】(5)

目录 一、分组算法如何计算 二、什么影响算法的安全性 三、密钥的使用次数限制 一、分组算法如何计算 分组算法包括3个部分:数据分组,分组运算和链接模式。 数据分组:将数据分割成加密函数能够处理的数据块,如果不能整分&#x…

【MYSQL篇】mysql不同存储引擎中索引是如何实现的?

前言 不同的存储引擎文件是不一样,我们可以查看数据文件目录: show VARIABLES LIKE datadir;每 张 InnoDB 的 表 有 两 个 文 件 ( .frm 和 .ibd ), MyISAM 的 表 有 三 个 文 件 (.frm、.MYD、.MYI&…

简单的PWN堆栈溢出的尝试

这是一道2018年西电CTF线下赛的一道ez_pwn的小题目,该题目为堆栈溢出漏洞的利用1 本次实验环境为 ubuntu 20.0.4 使用工具:GDB pwngdb 首先分析文件大致情况 checksec ez_pwn Arch: amd64-64-little 表示该二进制文件是 64 位的 。 RELRO: Partial R…

计算机网络课程设计——中小型网络工程设计

文件地址:https://github.com/Recursiondzl/Computer-Network github里面有课设文件,别白嫖,点个star哦 摘 要:本次计算机网络实践,完成了中小型网络工程设计与实现对计算机网络知识进行了系统的复习,实践能力获得了…

0基础学习VR全景平台篇第45篇:编辑器底部菜单- 关联场景功能操作

大家好,欢迎观看蛙色VR官方系列——后台使用课程! 本期为大家带来蛙色VR平台,底部菜单—关联场景功能操作。 一、本功能将用在哪里? 关联场景,是某个场景下的子场景,也可以理解为VR漫游作品的三级分组&…

1-简单回归问题

一.梯度下降(gradient descent) 1.预测函数 这里有一组样本点,横纵坐标分别代表一组有因果关系的变量 我们的任务是设计一个算法,让机器能够拟合这些数据,帮助我们算出参数w 我们可以先随机选一条过原点的直线&#xf…

【GESP】2023年03月图形化一级 -- 小猫捉老鼠

文章目录 小猫捉老鼠1. 准备工作2. 功能实现3. 设计思路与实现(1)角色、舞台背景设置a. 角色设置b. 舞台背景设置 (2)脚本编写a. 角色:Mouse1b. 角色:Cat 2 4. 评分标准 小猫捉老鼠 1. 准备工作 &#xff…

Vue3项目中使用vue-router

目录 1、Vue Router 的主要概念和功能2、什么是 vue-router?3、为什么需要 vue-router?4、基本概念和安装4.1 了解单页面应用(SPA)和路由的基本概念4.1.1单页面应用(Single Page Application,SPA)4.1.2路由…

【运维知识进阶篇】zabbix5.0稳定版详解3(监控Nginx+PHP服务状态信息)

这篇文章继续给大家介绍zabbix监控,监控Nginx、PHP等服务,其实非常简单,难点在于如何去取这个值,包括监控业务,难点在于思路是否清晰,思维是否活跃,如何去进行判断是否有这个业务,并…

小白到运维工程师自学之路 第三十四集 (redis的基本使用)

一、概念 Redis是一个开源的内存数据结构存储系统,它可以用作数据库、缓存和消息中间件。Redis支持多种数据结构,如字符串、哈希表、列表、集合、有序集合等。Redis的特点是数据存储在内存中,因此读写速度非常快,同时也支持数据持…

【Vue3+Ts project】认识 @vueuse/core 库

目标: 根据屏幕宽度改变 实现动态获取盒子的宽度 目录 目标: 一、javascript实现 二、vueuse/core 库实现 一、javascript实现 1.首先 window.innerWidth 获取当前屏幕宽度,然后将 盒子宽度 除 375 乘 当前屏幕宽度 150 / 375 * window.innerWidth 2.将获取的…

千万不要跟随这 4 种领导!

​ 见字如面,我是军哥! 最近有程序员读者问我,什么样的领导不能跟随?都有哪些坑!这个我擅长哈,毕竟职场混迹 15 年~ 第一种,技术能力不行还喜欢指手画脚的领导。 第二种,…