什么等等? I/O Wait ≠ I/O 瓶颈?

本文地址:什么等等? I/O Wait ≠ I/O 瓶颈? | 深入浅出 eBPF

  • 1. I/O Wait 定义
  • 2. 测试验证
  • 3. 进一步明确磁盘吞吐和读写频繁进程
  • 4. 内核 CPU 统计实现分析
  • 5. 总结
  • 参考资料

1. I/O Wait 定义

I/O Wait 是针对单个 CPU 的性能指标,表示当 CPU 分发队列(在睡眠态)里有线程被阻塞在磁盘 I/O 上时消耗的空闲时间。CPU 的空闲时间划分成无所事事的真正空闲时间和阻塞在磁盘 I/O 上的时间。较高的 CPU I/O Wait 时间表示磁盘可能存在瓶颈,导致 CPU 等待而空闲。如果你看到这个定义,有点雾中看花的感觉,那么请移步往后,相信你看完本文的测试验证过程,再回来读上述定义的时候一定会有不同的认识。

2. 测试验证

本地测试验证环境为:Ubuntu 22.04, CPU 12 核,内核 6.2.0-34-generic

$ cat /proc/cpuinfo |grep processor|wc -l
12

我们通过 sysbench 工具进行对应压测验证,同时观察对应的 I/O Wait 的表现。注意为了更好体现效果,我们测试 I/O 的过程中,将 threads 设置为 CPU 的全部核数的 50%(本文为 --threads=6

$ sudo apt-get update 
$ sudo apt install sysbench

# 提前准备测试的数据
$ sysbench  --threads=6 --time=0 --max-requests=0  fileio --file-num=1 \
	--file-total-size=10G --file-io-mode=sync --file-extra-flags=direct \
	--file-test-mode=rndrd run prepare

# 运行压测
$ sysbench  --threads=6 --time=0 --max-requests=0  fileio --file-num=1 \
	--file-total-size=10G --file-io-mode=sync --file-extra-flags=direct \
	--file-test-mode=rndrd run
...
Periodic FSYNC enabled, calling fsync() each 100 requests.
Calling fsync() at the end of test, Enabled.
Using synchronous I/O mode
Doing random read test
Initializing worker threads...

Threads started!

在运行 I/O 压测过程中,我们使用 top 命令查看 CPU 占用情况,可以看到 wa (I/O wait)值展示,图中为 38.3 %:

b53e1bc14c2e2acc911b355c1cff92dc

看到这里,给我们的感觉是 CPU I/O Wait 使用应该正确展示出了 I/O wait 的 CPU 使用情况。在我们一直保持 sysbench I/O 测试的同时,同时启动一个 CPU 密集类型的测试,然后我们观测 top 中的 wa 的值。这里测试我们设置使用所有的 CPU 核数。

1
$ sysbench --threads=`grep processor /proc/cpuinfo|wc -l` --time=0 cpu run

208a97d04ca69e6f6426d6641386cd2f

发生了什么,有没有觉得神奇,wa 变为了 0.0?给我们的感觉是 I/O 的瓶颈完全消失了?难道运行系统中的 I/O 压力突然消失了?我们可以注意到在运行的进程中两个 sysbench 进程在运行,分别对应于 I/O 和 CPU 测试的进程,所以实际运行情况看,I/O 的瓶颈仍然存在。

因此,I/O Wait 高能够表明系统中有许多进程在等待磁盘 I/O,但即使 I/O Wait 低甚至为 0,磁盘 I/O 也可能成为系统上某些进程的瓶颈。

结合我们上述的测试, I/O Wait 好像并不可靠,那么我们使用什么来提供更好 I/O 的可见性? 我们可以使用 vmstat 工具来进行查看。

在运行 I/O 和 CPU 负载的同时,我们使用 vmstat 工具观测,同时在一定时间测试后我们停掉 CPU 负载测试的 sysbench 进程,下图我们可以明显看到停止前后的效果对比趋势。

1b6bdde712f44cbbad2e97cc49c1eb8a

首先,我们可以发现 wa 列在运行 CPU 负载测试前后的变化比较明显,首列中的 r 的数据也得到了对应的体现(r 表示运行的任务数,运行 CPU 负载测试时的值为 12)。

15b628ce5fef0c35cc91208a3af1cef9

vmstat 展示数据中的 “b” 列代表的是对应于磁盘 I/O 上阻塞的进程,我们可以看到在运行 CPU 负载 sysbench 前后该值基本保持在 6 左右, 6 正是我们在运行 I/O 测试时候指定的 sysbench 中对应的 --threads=6 。该列值表明,即使在 wa 为 0.0 时,系统运行中仍然存在 6 个进程在等待 I/O。

fa1f24a7768d04a8dcb0dac2a419e01c

3. 进一步明确磁盘吞吐和读写频繁进程

在通过 vmstat b 列确定存在进程 I/O 等待情况后,我们也可以使用 iostat 和 iotop 进行进一步定义。

iostat 1 nvme0n1

nvme0n1 为本地磁盘

a921d64010d80eb7977092be6a3a3e8c

其中

  • tps:每秒事务数(IOPS)
  • kB_read/s、kB_wrtn/s : 每秒读取的 KB 数和每秒写入的 KB 数量

iotop 工具可快速定位到当前系统中读写频繁的进程信息。

3cacbc9f87bdce0a9fe755f60a3efbf2

4. 内核 CPU 统计实现分析

在通过上述分析以后,我们尝试从内核代码实现维度进行简单分析(内核代码代码版本 6.2.0 ):

cputime.c#L483

void account_process_tick(struct task_struct *p, int user_tick)
{
	u64 cputime, steal;

	if (vtime_accounting_enabled_this_cpu())
		return;

	if (sched_clock_irqtime) {
		irqtime_account_process_tick(p, user_tick, 1);
		return;
	}

	cputime = TICK_NSEC;
	steal = steal_account_process_time(ULONG_MAX);

	if (steal >= cputime)
		return;

	cputime -= steal;

  // 1. 如果当前进程处于用户态,那么增加用户态的 CPU 时间
	if (user_tick) 
		account_user_time(p, cputime);
  // 2. 如果前进程处于内核态,并且不是 idle 进程,那么增加内核态 CPU 时间
	else if ((p != this_rq()->idle) || (irq_count() != HARDIRQ_OFFSET))
		account_system_time(p, HARDIRQ_OFFSET, cputime);
  // 3. 如果当前进程是 idle 进程,那么调用 account_idle_time() 函数进行处理
	else
		account_idle_time(cputime);
}

account_idle_time 函数是统计当前 CPU 空闲的实现,可以看到如果 CPU 上有 nr_iowait 的值不为 0, 空余时间则会统计到 iowait 中,否则则会统计到 idle 列中。

cputime.c#L218

void account_idle_time(u64 cputime)
{
	u64 *cpustat = kcpustat_this_cpu->cpustat;
	struct rq *rq = this_rq();

  // 1. 如果当前有进程在等待 I/O 请求的话,那么增加 iowait的时间
	if (atomic_read(&rq->nr_iowait) > 0)
		cpustat[CPUTIME_IOWAIT] += cputime;
  // 2. 否则增加idle的时间
	else
		cpustat[CPUTIME_IDLE] += cputime;
}

通过代码我们可以明确看到,如果系统处于 I/O wait 状态,那么必须满足以下两个条件:

  1. 当前 CPU 中存在等待 I/O 请求完成的进程。
  2. 当期 CPU 处于空闲状态,也就是说没有可运行的进程。

5. 总结

经过上述测试,我们可以看到 I/O Wait 可能是一个令人非常困惑的指标。如果 CPU 密集型的进程运行,I/O Wait 的值可能会降低,但是尽管 I/O Wait 指标下降了,但磁盘 I/O 仍然和原来一样阻塞进程执行。所以在判断是否存在 I/O 瓶颈时,我们不能简单依靠 I/O Wait 值的高低来断定系统是否存在 I/O 瓶颈。

相信读完这篇文档的童鞋们,后续再也不会跳进 I/O Wait 指标的坑里了,那么这也就是本文的价值所在了。

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

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

相关文章

Bresenham 算法

1965 年,Bresenham 为数字绘图仪开发了一种绘制直线的算法,该算法同样使用于光栅扫描显示器,被称为 Bresenham 算法。 原理 算法的目标是选择表示直线的最佳光栅位置。Bresenhan 算法在主位移方向上每次递增一个单位。另一个方向的增量为 0…

【java爬虫】基于springboot+jdbcTemplate+sqlite+OkHttp获取个股的详细数据

注:本文所用技术栈为:springbootjdbcTemplatesqliteOkHttp 前面的文章我们获取过沪深300指数的成分股所属行业以及权重数据,本文我们来获取个股的详细数据。 我们的数据源是某狐财经,接口的详细信息在下面的文章中,本…

抖店对接厂家时,厂家不愿提供ERP打单如何解决?相关解答如下

我是王路飞。 现在的抖店已经不能拍单了,只能让厂家使用抖音电子面单发货。 关于这件事,我之前也说过,无货源商家太聪明了,所以平台一定会解决拍单问题的,无非是个时间问题罢了。 而且我认为这对我们商家来说也是个…

关于巴西网络犯罪分子使用LOLBaS和CMD脚本窃取银行账户的动态情报

一、基本内容 最近,一名未知身份的网络犯罪威胁行为者以使用西班牙语和葡萄牙语的用户为目标,破坏墨西哥、秘鲁和葡萄牙等地的网上银行账户。该攻击链主要利用社会工程学技术,利用葡萄牙和西班牙用户的电子邮件,发送带有欺骗性的…

如何使用固定二级子域名公网访问多个本地Windows Web网站

文章目录 1. 下载windows版Nginx2. 配置Nginx3. 测试局域网访问4. cpolar内网穿透5. 测试公网访问6. 配置固定二级子域名7. 测试访问公网固定二级子域名 1. 下载windows版Nginx 进入官方网站(http://nginx.org/en/download.html)下载windows版的nginx 下载好后解压进入nginx目…

图像识别SLIC、Haralick texture features(自备)

SLIC 简单线性迭代聚类(SLIC ),它采用k-means聚类方法来有效地生成超像素。 SLIC超像素分割详解(一)(二)(三)_超像素分割 样本-CSDN博客 超像素分割 & SLIC算法 & 使用示例_slic分割算法matlab-C…

快速剪辑视频软件,视频图像翻转软件

在这个信息爆炸的时代,视频已经成为了人们获取信息、娱乐、学习的主要方式之一。一个好的视频,不仅可以吸引观众的眼球,更可以传达出深层次的意义。那该什么快速的编辑视频,有没有好用的工具推荐呢?今天小编就给大家介…

MySQL数据库——约束

1. 约束 1.1. 概述 概述 约束是MySQL中用于限制表中数据规则的术语。这些规则可以确保数据类型、长度、精度等符合要求,并保持数据的正确性、有效性和完整性。约束可以应用于表中的字段,并帮助保护数据库中的数据免受无效或错误数据的干扰。 分类 约束…

行为型模式

目录 行为型模式1 模板方法模式1.1 概述1.2 结构1.3 案例实现1.3 优缺点1.4 适用场景1.5 JDK源码解析 2 策略模式2.1 概述2.2 结构2.3 案例实现2.4 优缺点2.5 使用场景2.6 JDK源码解析 3 命令模式3.1 概述3.2 结构3.3 案例实现3.4 优缺点3.5 使用场景3.6 JDK源码解析 4 责任链模…

多线程的基本使用与多线程中条件变量的使用——消费者生产者问题实例

多线程的基本使用与多线程中条件变量的使用——消费者生产者问题实例 本文主要涉及多线程的使用方法,通过两个实例来对多线程的使用进行理解, 案例包括: 1.一个线程负责计数,另一个线程负责打印计数值 2.消费者生产者问题 文章目录…

Git常用命令及解释说明

目录 前言1 git config2 git init3 git status4 git add5 git commit6 git reflog7 git log8 git reset结语 前言 Git是一种分布式版本控制系统,广泛用于协作开发和管理项目代码。了解并熟练使用Git的常用命令对于有效地管理项目版本和历史记录至关重要。下面是一些…

[THUPC 2024 初赛] 二进制 (树状数组单点删除+单点查询)(双堆模拟set)

题解 题目本身不难想 首先注意到所有查询的序列长度都是小于logn级别的 我们可以枚举序列长度len,然后用类似滑动窗口的方法,一次性预处理出每种字串的所有出现位置,也就是开N个set去维护所有的位置。预处理会进行O(logn)轮,每…

基于谷歌模型gemini-pro 的开发的QT 对话项目

支持的功能,新建对话框,目前发现相关梯子不支持访问谷歌的api 的可能代理设置的不对, QNetworkAccessManager manager;// Set up your requestQNetworkRequest request;request.setUrl(QUrl("https://generativelanguage.googleapis.com…

这一平台只要把握住风口期,自己就能当老板!

我是电商珠珠 短视频渐渐走进大家的视野,改变了大家的日常娱乐方式。从19年开始,抖音开始发展电商平台-抖音小店。 在改变大家娱乐方式的同时,还将直播电商的热度掀了起来,由此改变了大家的购物方式,给大家带来了方便…

ansible-playbook实操之一键搭建lnmp+wordpress

目录 1、架构和准备: 2、配置nginx角色: 3、配置mariadb角色: 4、配置php角色: 5、配置完之后,写脚本调用roles 6、配置完之后浏览器搭建wordpress: 1、架构和准备: 操控节点:…

Echarts社区推荐

Apache Echarts官方示例中,有的demo并不能完全符合我们的需求,下面推荐几个Echarts社区,以便快速搭建项目。 1. isqqw 官方地址 :https://www.isqqw.com/ 2. makepie 官方地址 :https://www.makeapie.cn/echarts 3. P…

20231224解决outcommit_id.xml1 parser error Document is empty的问题

20231224解决outcommit_id.xml1 parser error Document is empty的问题 2023/12/24 18:13 在开发RK3399的Android10的时候,出现:rootrootrootroot-X99-Turbo:~/3TB/Rockchip_Android10.0_SDK_Release$ make installclean PLATFORM_VERSION_CODENAMEREL…

形态学处理

形态学处理的相关内容 (1)基于图像形态进行处理的一般方法 (2)这些处理方法基本是对二进制图像进行处理 (3)卷积核决定着图像处理后的结果 形态学图像处理 (1)腐蚀(…

测试C#使用AForge从摄像头获取图片

百度“C# 摄像头”关键词,从搜索结果来看,使用OpenCV、AForge、window动态链接库获取摄像头数据的居多,本文学习基于Aforge.net连接摄像头并从摄像头获取图片的基本方法。   AForge相关包(尤其是相关的控件)主要针对…

【AIPRM】-高效管理Prompt模板,让你与众多AI互动更加流畅

关于AIPRM 链接: AIPERM AIPRM:Google 推出的AI提示管理工具。它提供多样化的Prompt模板,能帮助你与各种AI进行更加高效的互动。 登录 在主页点击“免费安装”–>Add to Chrome。 安装完成后,你在新的ChatGPT界面里面,能…