系统性能优化-4 磁盘

磁盘作为计算机中速度最慢的硬件之一,常常是系统的性能瓶颈,优化磁盘一般能得到明显的提升~

文章以如何高效的传输文件来讨论针对磁盘的优化技术,如零拷贝、直接 IO、异步 IO等。

最简单的网络传输

最简单的方式的当然是找到文件存储的路径,创建一个固定的大小的缓冲区,每次读取缓冲区大小的文件内容,再通过网络 API 发送给客户端,重复上述流程直到把文件发送完成。

顺便一提,缓冲区的设置还是有必要的,java 有单字节的读取写入方式(FileInputStream.read()),这样会很慢,缓冲区可以有效的提升读取文件的性能。

但是这样的性能依旧不是很高,原因是这需要进行多次的内容拷贝,会导致大量的上下文切换

image-20250624112007687

  • 每次读取发送都经历了 4 次用户态与内核态的上下文切换
  • 每次发送的缓存区内容被拷贝了 4 次

接下来就从减少上下文切换次数减少内存拷贝次数来进行优化

零拷贝

读取磁盘或者操作网卡都由操作系统内核完成。内核负责管理系统上的所有进程,它的权限最高,工作环境与用户进程完全不同。只要我们的代码执行 read 或者 write 这样的系统调用,一定会发生 2 次上下文切换:首先从用户态切换到内核态,当内核执行完任务后,再切换回用户态交由进程代码执行。

因此如果要减少上下文切换次数,就要减少系统调用次数。解决方案就是把 read 和 write 系统调用合二为一,直接在内核中完成文件的读取和发送,可以把原本的 4 次上下文切换减少为 2 次。

那如何减少内存拷贝次数呢?对于常见的文件下载场景,我们并不需要进程对文件进行处理,如添加公司信息等,那么用户缓冲区就没有存在的必要,直接由 PageCache 拷贝到 Socket 缓冲区就可以,这可以把原本的 4 次内容拷贝缩短为 3 次,

image-20250624112749023

如果 网卡支持 DMA SG-DMA(The Scatter-Gather Direct Memory Access),那么 PageCache 可以直接拷贝到网卡,可以再减少一次内存拷贝。

image-20250624113104692

其实这就是零拷贝技术,它是操作系统提供的新函数,同时接收文件描述符和 TCP socket 作为输入参数,这样执行时就可以完全在内核态完成内存拷贝,既减少了内存拷贝次数,也降低了上下文切换次数。

零拷贝使用户无需关心 socket 缓冲区的大小(因为 socket 缓冲区是动态变化的,它既用于 TCP 滑动窗口,也用于应用缓冲区,还受到整个系统内存的影响)。综合种种优点,零拷贝可以极大的提升文件传输性能。

PageCache 磁盘高速缓存

正常读取文件时,是先把磁盘文件拷贝到 PageCache 上,再拷贝到进程中。原因是磁盘的读取速度是最慢的,而在内存中的 PageCache 速度就会快很多,那选择哪些数据复制到内存呢?根据时间局部性原理(刚被访问的数据在短时间内再次被访问的概率很高),用 PageCache 缓存最近访问的数据,当空间不足时淘汰最久未被访问的缓存(即 LRU 算法)。读磁盘时优先到 PageCache 中找一找,如果数据存在便直接返回,这便大大提升了读磁盘的性能。

对于机械硬盘来说,需要旋转磁头到数据所在的扇区,再开始顺序读取数据。其中,旋转磁头耗时很长,为了降低它的影响,PageCache 使用了预读功能。也就是即使你可能目前只读 32KB 数据,但内核会把后续的部分数据也读取到 PageCache,因为这个读取成本很低,而如果后续一段时间访问到了这些数据,带来的收益是很值得的。

PageCache 在 90% 以上场景下都会提升磁盘性能,但在某些情况下,PageCache 会不起作用,甚至由于多做了一次内存拷贝,造成性能的降低。

先说结论:在读取大文件时,不应使用 PageCache,进而也不应使用零拷贝技术处理。

当用户访问大文件时,内核就会把它们载入到 PageCache 中,这些大文件很快会把有限的 PageCache 占满。一方面这些大文件被再次访问的概率其实很低,耗费 CPU 多拷贝到 PageCache 一次;另一方面大文件占用 PageCache 会导致热点小文件无法被加载到 PageCache 中,读取的速度变慢。

  • 比如视频文件通常按时间顺序播放,播放器只会按需加载一定长度的视频数据。虽然文件本身很大,但只有少部分数据会在某一时间点内被访问到,其余的数据部分在播放过程中可能根本不会被访问到。
  • 某些大数据库文件也是按顺序或按块读取的,而数据库的查询操作通常集中在特定区域或范围内。大文件的其他部分可能在较长时间内不会被访问,导致它们在 PageCache 中的缓存效果差。

那么高并发场景下该怎么处理大文件呢?

异步 IO + 直接 IO

高并发场景处理大文件时,应当使用异步 IO 和直接 IO 来替换零拷贝技术。

当调用 read 方法读取文件时,实际上 read 方法会在磁盘寻址过程中阻塞等待,导致进程无法并发地处理其他任务,如下图所示:

image-20250624132341046

异步 IO(异步 IO 既可以处理网络 IO,也可以处理磁盘 IO,这里我们只关注磁盘 IO)把读操作分为两部分,前半部分向内核发起读请求,但不等待数据就位就立刻返回,此时进程可以并发地处理其他任务。当内核将磁盘中的数据拷贝到进程缓冲区后,进程将接收到内核的通知,再去处理数据,这是异步 IO 的后半部分。如下图所示:

image-20250624132423219

异步 IO 并没有把数据拷贝到 PageCache 中,这其实是异步 IO 实现上的缺陷。经过 PageCache 的 IO 我们称为缓存 IO,它与虚拟内存系统耦合太紧,导致异步 IO 从诞生起到现在都不支持缓存 IO。绕过 PageCache 的 IO 是个新物种,我们把它称为直接 IO。对于磁盘,异步 IO 只支持直接 IO。

直接 IO 的应用场景为:

  • 应用程序已经实现了磁盘文件的缓存,不需要 PageCache 再次缓存,引发额外的性能消耗。比如 MySQL 等数据库就使用直接 IO
  • 高并发下传输大文件

缺点为无法享受 PageCache 造成的性能提升(内核会缓存尽量多的连续IO在 PageCache 中,合并为一个更大的 IO 发给磁盘,减少磁盘的寻址操作;内核也会预读后续的 IO 放在 PageCache 中,减少磁盘操作)

总结

零拷贝技术基于 PageCache(缓存最近读的数据),合并读取和发送的系统调用,能够有效减少传输文件过程中的上下文切换次数和内存拷贝次数,同时最大程度利用 socket 缓冲区。但缺点是用户进程无法对文件做任何修改,比如压缩后再发送。当文件大小超过某个阈值后,PageCache 还可能引发副作用,因此,实践中通常会设定一个文件大小阈值,针对大文件使用异步 IO 和直接 IO,而对小文件使用零拷贝( 例如 Nginx 的 directio 指令)。

文件传输场景中的优化可以大概分为三个方向:

  • 减少磁盘工作量(PageCache)
  • 减少 CPU 工作量 (直接 IO)
  • 提高内存利用率(零拷贝)

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

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

相关文章

Windows注册HTTP服务实现Jenkins Allure报告、测试日志永久访问

使用 NSSM (Non-Sucking Service Manager) 将 Allure 报告的 HTTP 服务注册为 Windows 后台服务的详细操作攻略,确保 Jenkins 测试结果可以长期通过 URL 访问。 ✅ 目标 将 allure generate 生成的报告目录托管为静态网页服务,并作为后台服务运行&#…

从ADI与AMD的专利诉讼,看高端FPGA的巅峰对决

RFSoC,作为FPGA家族中的“贵族”,高端芯片中的尖端代表,技术积累要求高、利润厚,售价贵,主要面向不差钱的军用雷达处理、通信和测试/测量仪器用户。 2019年,模拟芯片龙头ADI公司,发起专利侵权诉讼,而尝到甜头的赛灵思,一边反诉,一边揶揄ADI公司:爱哭的娃未必有奶吃…

性能测试-jmeter实战3

课程:B站大学 记录软件测试-性能测试学习历程、掌握前端性能测试、后端性能测试、服务端性能测试的你才是一个专业的软件测试工程师 性能测试-jmeter实战3 负载测试稳定性测试负载测试曲线图其他测试策略并发测试压力测试容量测试 性能指标的介绍响应时间并发用户数…

Maven镜像

在 Maven 中配置多个镜像源,主要是为了解决依赖包在不同地区下载速度不同的问题,或者为了使用特定的私有仓库作为依赖源。Maven 支持在 pom.xml 文件中配置多个镜像源(repositories),也可以在 Maven 的全局配置文件 se…

ArduPilot 教程(2):运行第一个 SITL 无人机仿真

目录 1. MAVLink 通信协议 2. MAVProxy 地面控制站 3. 运行 SITL 无人机仿真 3.1. 使用 MAVProxy 控制无人机 3.2. 使用 SITL 地图界面控制无人机 4. MAVProxy 常用命令 5. 其它地面控制站 5.1. QGroundControl 5.2. MissionPlanner 5.3. 不启用 MAVProxy 6. 本讲小…

开源AI大模型驱动下视频媒介对图文生态的重构与S2B2C商业场景创新——基于AI智能名片与商城小程序源码的实践分析

摘要:数字媒介演进的进程中,视频对图片及文字的媒介侵蚀效应正呈现加速态势,尤其在Z世代及新网民群体中,视频已成为其触网的首要信息载体。本文基于媒介技术迭代与商业场景融合的双重视角,探究开源AI大模型如何通过智能…

Kafka线上集群部署方案:从环境选型到资源规划思考

在分布式消息系统的落地应用中,Kafka集群的线上部署方案直接关系到业务系统的稳定性与性能表现。不同于测试环境的简易搭建,生产级集群需要从操作系统适配、存储介质选型、容量规划到网络资源调度等多维度进行系统性设计。本文将从工程实践角度&#xff…

算法第40天|买卖股票的最佳时机 1 2 3

121. 买卖股票的最佳时机 题目 思路与解法 记录每一天买或不买时的价值 class Solution { public:int maxProfit(vector<int>& prices) {// dp数组含义&#xff1a;// dp[i][0]:第i天&#xff0c;持有股票时的最大价值&#xff0c;dp[i][1]:第i天&#xff0c;不持…

【赵渝强老师】使用select...into outfile语句备份MySQL

MySQL可以使用select…into outfile语句将表的内容导出为一个文本文件。其基本的语法格式如下&#xff1a; select [列名] from 表名 [WHERE 语句] into outfile 目标文件 [其他选项];该语句分为两个部分。前半部分是一个普通的select语句&#xff0c;通过这个select语句来查询…

PHY XGE 自协商AN数据交互过程

在裸机环境下&#xff0c;两个 **支持 10GBASE-T** 的 PHY 芯片通过 Clause 73 协议完成自协商&#xff08;Auto-Negotiation&#xff0c;AN&#xff09;&#xff0c;它们在 **无操作系统控制** 的条件下&#xff0c;完成以下 **完整的点对点数据交互流程**&#xff1a; --- ##…

【算法 day09】LeetCode 232.用栈实现队列 | 225. 用队列实现栈 | 20. 有效的括号 |1047. 删除字符串中的所有相邻重复项

232.用栈实现队列 题目链接 | 文档讲解 |视频讲解 : 链接 1.思路&#xff1a; 使用2个栈去实现队列 先将元素放入栈1中&#xff0c;然后在将栈1中的元素出栈到栈2中&#xff0c;栈2的元素出栈顺序就和队列的出队一样 2.代码&#xff1a; class MyQueue {Stack<Integer…

大模型项目实战:业务场景和解决方案

你的这张图已经涵盖了很多主流的大模型实战项目&#xff0c;非常全面&#xff01;下面我会补充更多市面上常见的AI大模型实战项目&#xff0c;并且简要说明每个项目的核心内容、实现思路和主流技术栈&#xff0c;方便你参考和扩展。 1. 智能问答/知识库系统 核心内容&#xff…

vscode + Jlink 一键调试stm32 单片机程序(windows系统版)

vscode Jlink 一键调试stm32 单片机程序 安装交叉编译工具链安装 x-pack 构建工具安装 JLink 工具gnu-debuger 插件编译一键启动调试 安装交叉编译工具链 stm32采用 交叉编译工具链 arm-none-eabi-xxx, 下载之后解压&#xff0c;压缩包内部结构如下图&#xff1a; 目录下的bi…

Linux线程概念和控制

Linux线程概念 Linux中线程如何理解 线程<执行流<进程 Linux中的线程模拟进程实现&#xff08;线程就是轻量级进程&#xff09; 与独立的进程相比&#xff0c;线程创建和销毁的开销较小&#xff0c;因为它们共享相同的内存空间和资源。 线程是进程内的执行分支&…

服务器出现问题,连接服务器出现3680 并删除数据库出现1192,请查看详细问题(运维)

mysql连接服务器时&#xff0c;出现这个问题&#xff1a;3680 - Failed to create schema directory xxxx (errno: 28 - No space left on device) 第一步&#xff1a;诊断问题类型 检查磁盘空间 运行以下命令&#xff1a; bash df -h # 查看磁盘使用情况 如果输出中 Use% 接…

uniapp:微信小程序胶囊「复制链接」灰色处理

在原生开发的小程序中默认是支持复制的 &#x1f424; 但是在 uniapp 开发的小程序中无法复制&#xff08;体验版与开发版都可以进行复制&#xff0c;但发布后不可&#xff09; 解决方法&#xff1a; methods: {onShareAppMessage: function() {// return custom share data …

差分数组c++

温度波动记录 每天记录温度&#xff0c;支持区间温度调整和单日查询 输入&#xff1a; 第一行&#xff1a;一个整数n表示有n个温度 第二行&#xff1a;n个数表示具体温度 第三行&#xff1a;三个整数&#xff1a;S&#xff0c;e&#xff0c;c&#xff0c;表示从…

Vue.js 列表过滤实现详解(watch和computed实现)

Vue.js 列表过滤实现详解 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthd…

性能测试-jmeter实战4

课程&#xff1a;B站大学 记录软件测试-性能测试学习历程、掌握前端性能测试、后端性能测试、服务端性能测试的你才是一个专业的软件测试工程师 性能测试-jmeter实战4 jmeter环境搭建1. 安装Java环境&#xff08;必需&#xff09; JMeter环境搭建完整指南1. 安装Java&#xff0…

GPPT(Graph Pre-training and Prompt Tuning)项目复现

GPPT(Graph Pre-training and Prompt Tuning)项目复现 项目概述 GPPT是一种创新的图神经网络预训练与提示调整框架,由MingChen-Sun等人提出。该项目通过将自然语言处理中的提示学习概念引入图领域,解决了图预训练模型在下游任务中的适应性问题。 环境配置 # 创建Python…