【银河麒麟高级服务器操作系统】有关dd及cp测试差异的现象分析详解

了解更多银河麒麟操作系统全新产品,请点击访问

麒麟软件产品专区:https://product.kylinos.cn

开发者专区:https://developer.kylinos.cn

文档中心:https://documentkylinos.cn


dd现象

使用银河麒麟高级服务器操作系统执行两次dd用例后,表现不一致:

命令用例:/usr/bin/time dd if=/dev/zero of=/home/d.bin bs=2M count=4096

结果如图:

可以发现,在第二次执行dd时,速率只有412MB/S

现象猜测分析

基于上述的现象,猜测第一次dd没有等待数据完全落盘就结束了;而第二次dd是等待数据落盘之后才结束。

可以做如下复现和测试:

系统版本:

  1. Kernel:
  2. 4.19.90-89.11.v2401.ky10.x86_64
  3. Build:
  4. Kylin Linux Advanced Server
  5. release V10 SP3 2403/(Halberd)-x86_64-Build20/20240426

测试步骤:

执行:

  1. /usr/bin/time dd if=/dev/zero of=/home/d.bin bs=2M count=4096

再次执行:

  1. /usr/bin/time dd if=/dev/zero of=/home/d.bin bs=2M count=4096

可复现这个结果:

图1

分析和实验

删除d.bin后rm -rf d.bin,执行:

  1. strace -ttt -T -o strace_output_0.txt dd if=/dev/zero of=/home/d.bin bs=2M count=4096
  2. strace -ttt -T -o strace_output_1.txt dd if=/dev/zero of=/home/d.bin bs=2M count=4096

将生成两次对dd命令的系统调用报告,分析这两个output报告文件,对比close操作时,可以发现,第一次的dd,close耗时短,第二次的dd,close耗时更长

图2 strace系统调用对比

左边是第一次,close操作用不到1秒;

右边是第二次,close操作用了6秒,对比图1结果,第二次与第一次时间差接近6秒。

测试说明这个close()系统调用操作是导致第二次dd慢的原因。问题要从close调用的方向去分析。

根因分析

dd if=/dev/zero of=4G bs=1M count=4096在执行时,会以O_WRONLY|O_CREAT|O_TRUNC的方式打开文件,首次执行时,文件不存在则创建;

第二次执行时O_TRUNC就会发挥作用了,它会先把文件长度给TRUNC到0,然后再写数据;(这是dd程序本身执行的逻辑决定的)

而xfs文件系统,为了数据完整性,对这个这种情况做了加强——即:再检测到这种情况下,会在文件close时触发数据下刷,而且是同步的,就是导致dd性能降低的原因。

  1. 第一次运行时,由于目标文件/home/d.bin不存在,属于纯粹的内存操作,没有实际的磁盘IO开销。
  2. 第二次运行时,由于目标文件已存在且被写入了数据,而需要/dev/zero真实读取数据,并将数据写入磁盘文件。这就引入了额外的磁盘IO操作,成为了新的性能瓶颈。
  3. cpu占用率的差异就是由于落盘操作造成的,第一次dd时,都是操作的内存所以cpu占用率高;
  4. 第二次dd由于数据落盘会有IO等待,cpu占用率就会降下来。

验证猜测

使用watch监测页内存回写到硬盘

使用两个终端,并进行测试与观测,第一次dd

  1. rm -rf d.bin
  2. echo 3 > /proc/sys/vm/drop_caches
  3. time dd if=/dev/zero of=/home/d.bin bs=2M count=4096
  1. watch -n 1 cat /proc/meminfo

图三 第一次dd 的数据回写观测

第二次dd

  1. echo 3 > /proc/sys/vm/drop_caches
  2. time dd if=/dev/zero of=/home/d.bin bs=2M count=4096
  1. watch -n 1 cat /proc/meminfo

图4 第二次dd的数据回写观测

可以发现,第一次dd并没有writeback回写,即:没有从页内存往硬盘落数据,通过ls看到的d.bin的文件数据,是在内存中,只是因为有这个“机制”存在,让用户感觉这个数据落盘了;

第二次dd,由于出现了脏页(因为d.bin存在导致缓存数据不同),内核进行了数据落盘的操作,通过watch命令,观测到了在dd过程中,writeback就有数据流量。

使用sar观测I/O

  1. time dd if=/dev/zero of=/home/d.bin bs=2M count=4096
  1. sar -d 1

第一次dd的情况

图5 第一次dd的I/O情况

第二次dd的情况

图6 第二次dd的I/O情况

可以看到,第二次的磁盘I/O操作比第一次dd多很多,说明有很多I/O落盘的操作,佐证页缓存机制在工作。

如何让dd观测结果稳定?

优化dd测试方法

既然dd的运行逻辑决定了最后观测的结果,那么可以通过指定一些参数,来更准确的进行测试:

通过添加ofag=direct参数,不走系统缓存

测试命令和观测结果如下:

  1. [root@localhost home]# rm -rf d.bin
  2. [root@localhost home]# time dd if=/dev/zero of=/home/d.bin bs=2M count=4096 oflag=direct
  3. 记录了4096+0 的读入
  4. 记录了4096+0 的写出
  5. 8589934592字节(8.6 GB,8.0 GiB)已复制,11.2041 s,767 MB/s
  6. real0m11.205s
  7. user0m0.003s
  8. sys0m0.694s
  9. [root@localhost home]# time dd if=/dev/zero of=/home/d.bin bs=2M count=4096 oflag=direct
  10. 记录了4096+0 的读入
  11. 记录了4096+0 的写出
  12. 8589934592字节(8.6 GB,8.0 GiB)已复制,11.4382 s,751 MB/s
  13. real0m11.443s
  14. user0m0.000s
  15. sys0m0.700s
  16. [root@localhost home]#

图7 dd添加参数后

可以看到,在添加oflag=direct参数后,dd命令不管是第几次都稳定了;

通过观察页内存,可以发现,直接写时,数据落盘,没有通过脏页内存回写。

通过添加conv=notrunc方式,不截断输出文件

默认情况下,如果输出文件已经存在,dd命令会首先将其截断为0字节大小。然后再将输入数据写入该输出文件。

当指定conv=notrunc参数时,dd命令将保留输出文件已有的数据,而只是从输出文件的当前文件结尾处开始覆盖写入数据。

删除生成的d.bin文件

如果每次测试前,都删除d.bin文件,那么每次dd都是通过内存出来,速率也可以稳定

为什么FreeBSD的表现和Linux不同?

freebsd上使用zfs文件系统,而linux上使用了xfs文件系统,他们在数据下刷机制上也存在一些差异:

对于 XFS,代码中的 filemap_flush(VFS_I(ip)->i_mapping) 实际上是调用 VFS(虚拟文件系统)层的通用页高速缓存写入磁盘的操作。

具体来说,它会遍历给定映射(mapping)关联的所有脏页,将这些脏页写入对应的后备存储设备(通常是磁盘)。这个过程是同步执行的,即该函数直到所有脏页都被写入磁盘才会返回。

以上是XFS文件系统特有实现,而zfs实现不同,所以不存在同样的问题。

cp现象

在d6.bin存在的情况下,使用cp d.bin d6.bin进行拷贝,如果使用了truncate -s 0 d6.bin,会使拷贝速度急速上升的。为什么?

现象分析

cp a b慢

truncate -s 0 b; cp a b快

直接cp a b时对b文件打开是带O_TRUNC标志(d6.bin已存在),就会在close的时候进行同步下刷,速度就不会快;

而truncate -s 0 b; cp a b,cp对b的打开同样是带O_TRUNC标志的,但是由于在cp之前,执行了truncate的操作,根据xfs文件系统落盘的机制,在cp的时候O_TRUNC就不起作用了,也就是在close的时候不会进行同步下刷;=》内核会对同样的两次操作进行优化,避免做重复的工作。

xfs文件系统源码

先看紫色字的注释:

如果之前对该文件进行了截断操作,删除了旧的文件数据。我们希望在最后关闭该文件时,提前(early)将数据写出到磁盘。这个问题特别容易在以下情况发生:先截断文件,然后通过缓冲区写入(重写)数据(延迟分配delalloc),接着系统崩溃。我们在这里所做的,实际上是大大缩小了可能遇到这个问题的时间窗口。

所谓空文件问题,是指在截断、重写文件数据的过程中,如果系统崩溃,可能导致原有数据被删除,而新写入的数据还未持久化到磁盘,从而使文件内容变为空或不完整。

为了避免这种情况,XFS会在关闭经过截断和重写的文件时,主动提前将缓冲区数据刷新到磁盘。这样可以最大限度减小系统崩溃导致数据丢失的窗口期,从而提高数据完整性和一致性。

执行过程如下:

判断文件系统状态xfs_is_shutdown,执行以下操作:

a. 判断truncated状态:XFS_ITRUNCATED会把XFS_ITRUNCATED复位,返回true;如果flags里面没有XFS_ITRUNCATED置位,返回false

b. 如果上一步标志被清除(即之前发生了截断),调用 xfs_iflags_clear(XFS_IDIRTY_RELEASE) 清除 XFS_IDIRTY_RELEASE 标志。该标志表示需要在卸载时将延迟写入的元数据写入磁盘。

c. 如果上一步标志被清除,调用 filemap_flush(VFS_I(ip)->i_mapping) 将所有延迟的元数据写入磁盘。(数据下刷

所以手动执行truncate命令时,变量truncated=false,if(truncated)函数就不会执行,也就没有数据下刷的操作,观测结果“看上去”cp速度很快。

验证

这个情况同样可以用sar观测I/O被证实:

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

sqli-labs靶场第26-30关

第26关 这关将逻辑运算符,注释符以及空格给过滤了 我们先使用单引号进行闭合 这时我们查看源代码可以看到这一关过滤了很多字符 可以看到这里将or and / -- # 空格等字符都被注释了 空格被过滤了我们可以使用()来代替,and和or可以使用双写来绕过 因为…

ik分词器了解 和 通过zip安装包的方式 将ik分词器安装到elasticsearch中

目录 1. ik分词器的作用(效果) (1)标准分析器效果 (2)ik_smart分词 (3)ik_max_word分词 2. 首先根据自己的elasticsearch的版本下载对应的ik分词器版本 3. 将下载好的ik分词器…

实景视频与模型叠加融合?

[视频GIS系列]无人机视频与与实景模型进行实时融合_无人机视频融合-CSDN博客文章浏览阅读1.5k次,点赞28次,收藏14次。将无人机视频与实景模型进行实时融合是一个涉及多个技术领域的复杂过程,主要包括无人机视频采集、实景模型构建、视频与模型…

【解决】k8s使用kubeadm初始化集群失败问题整理

执行提示命令,查看报错信息 journalctl -xeu kubelet1、错误:running with swap on is no 报错 "command failed" err"failed to run Kubelet: running with swap on is no 解决: swap未禁用,需要禁用swap&…

aws(学习笔记第十七课) SQS Amazon Simple Queue Service服务

aws(学习笔记第十七课) SQS Amazon Simple Queue Service服务 学习内容: 使用SQS Amazon Simple Queue Service服务整体代码(nodejs的通常工程)代码动作 1. 使用SQS Amazon Simple Queue Service服务 利用应用程序来学习SQS 创建S3$ aws s…

qt-C++笔记之父类窗口、父类控件、对象树的关系

qt-C笔记之父类窗口、父类控件、对象树的关系 code review! 参考笔记 1.qt-C笔记之父类窗口、父类控件、对象树的关系 2.qt-C笔记之继承自 QWidget和继承自QObject 并通过 getWidget() 显示窗口或控件时的区别和原理 3.qt-C笔记之自定义类继承自 QObject 与 QWidget 及开发方式…

VMware ubuntu12.04怎么设置静态IP联网

记得刚开始学习嵌入式就是从ubuntu12.04的环境开始学习的C语言,当时没有弄清楚怎么设置静态IP联网,现在写一篇文章。 1.首先,关闭ubuntu的网络; 2.电脑使用的是wifi,将VMware桥接到该网卡上; 3.在虚拟机设置里面选择桥…

计算机视觉中的图像滤波与增强算法

摘要: 本文深入探讨了计算机视觉领域中的图像滤波与增强算法。首先介绍了图像滤波与增强的基本概念和重要性,随后详细阐述了线性滤波算法中的均值滤波和高斯滤波,以及非线性滤波算法中的中值滤波和双边滤波,包括它们的原理、数学模…

AI大模型学习笔记|神经网络与注意力机制(逐行解读)

来源分享链接:通过网盘分享的文件:详解神经网络是如何训练的 链接: https://pan.baidu.com/s/12EF7y0vJfH5x6X-0QEVezg 提取码: k924 内容摘要:本文深入探讨了神经网络与注意力机制的基础,以及神经网络参数训练的过程。以鸢尾花数…

腾讯云系统盘扩容

在腾讯云申请空间后,只要执行三行命令 云硬盘 在线扩展系统盘分区及文件系统-操作指南-文档中心-腾讯云 安装工具 yum install -y cloud-utils-growpart 给/eav/vda1扩分区 LC_ALLen_US.UTF-8 growpart /dev/vda 1 挂载扩容 ext4 文件系统 resize2fs /dev/vda1 …

【控制系统】深入理解反步控制(Backstepping) | 反步法控制器原理与应用实例解析(附Matlab/Simulink仿真实现)

💯 欢迎光临清流君的博客小天地,这里是我分享技术与心得的温馨角落 💯 🔥 个人主页:【清流君】🔥 📚 系列专栏: 运动控制 | 决策规划 | 机器人数值优化 📚 🌟始终保持好奇心&…

构建树莓派温湿度监测系统:从硬件到软件的完整指南

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…

人工智能系统

介绍人工智能 的基础书 点击这里 1.1 深度学习的历史,现状与发展 本章将介绍深度学习的由来,现状和趋势,让读者能够了解人工智能系统之上的深度学习负载的由来与趋势,为后面理解深度学习系统的设计和权衡形成初步的基础。我们在后…

NVR小程序接入平台EasyNVR设置预置位显示“参数错误”的解决方法

视频监控技术在现代社会中的应用已经变得越来越广泛,从城市安防到家庭安全,从交通管理到商业监控,其作用无处不在。随着科技的不断进步,视频监控不仅提高了安全性,还带来了许多新的机遇和挑战。 近期,我们收…

下载红米Note 9 Pro5G对应的LineageOS代码下载及编译

构建 LineageOS 进入网站:Info about gauguin | LineageOS Wiki,点击:Build for yourself,里面有详细的教程,我这里就按照Note 9 Pro 5G来。 机器环境 Ubuntu环境为:20.04.6LinagesOS版本:21-…

如何在 Ubuntu 22.04 上安装 Strapi CMS

简介 Strapi 是一个使用 JavaScript 构建的开源、无头内容管理系统 (CMS)。与其他无头 CMS 一样,Strapi 开箱即用不带前端。它使用 API 作为其前端,允许你使用流行的框架(如 React 和 Next.js)构建网站。Strapi 基于插件系统&…

Java:集合(List、Map、Set)

文章目录 1. Collection集合1-1. 迭代器遍历方式1-2. 通过for循环进行遍历1-3. forEach遍历 2. List集合2-1. ArrayList底层实现原理2-2. LinkedList底层实现原理 3. Set集合3-1. HashSet 底层实现3-2. LinkedHashSet 底层实现3-3. TreeSet 4. Collection集合->总结5. Map集…

私有云dbPaaS为何被Gartner技术成熟度曲线标记为“废弃”?

当云计算席卷而来,基于云基础设施的数据库部署也改变了数据库。在传统的私有化部署(On-premises)和公有云部署(Public Cloud)之间,不断融合的混合IT(Mixed IT)形式成为最常见的企业级…

ElementPlus Table 表格实现可编辑单元格

通过基础的Table表格来实现单元格内容的可编辑 1.首先定位到需要编辑的列&#xff0c;替换el-table-column <el-table-column label"Editable Column" width"300"><template #default"{ row, column, $index }"><el-inputsize&qu…

《数据结构》(408代码题)

2009 单链表&#xff08;双指针&#xff09; 分析&#xff1a;首先呢&#xff0c;给我们的数据结构是一个带有表头结点的单链表&#xff0c;也不允许我们改变链表的结构。链表的长度不是直接给出的啊&#xff0c;所以这个倒数也很棘手。那我们该如何解决这个“k”呢&#xff0c…