一文讲解系统性能分析之|iowait是什么?

news2024/9/23 9:36:59

我们对系统性能进行优化时,一般会使用 top 命令来查看系统负载和系统中各个进程的运行情况,从而找出影响系统性能的因素。如下图所示:

top

top 命令会输出很多系统相关的信息,如:系统负载、系统中的进程数、CPU使用率和内存使用率等,这些信息对排查系统性能问题起着至关重要的作用。

本文主要介绍 top 命令中的 iowait 指标(如上图中红色方框所示)的含义和作用。

 

什么是iowait

什么是 iowait?我们来看看 Linux 的解释:

Show the percentage of time that the CPU or CPUs were idle during which the system had an outstanding disk I/O request.

中文翻译的意思就是:CPU 在等待磁盘 I/O 请求完成时,处于空闲状态的时间百分比(此时正在运行着 idle 进程)。

可以看出,如果系统处于 iowait 状态,那么必须满足以下两个条件:

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

iowait统计原理

既然我们知道了 iowait 的含义,那么接下来看看 Linux 是怎么统计 iowait 的比率的。

Linux 会把 iowait 占用的时间输出到 /proc/stat 文件中,我们可以通过一下命令来获取到 iowait 占用的时间:

cat /proc/stat

命令输出如下图所示:

stat

红色方框中的数据就是 iowait 占用的时间。

我们可以每隔一段时间读取一次 /proc/stat 文件,然后把两次获取到的 iowait 时间进行相减,得到的结果是这段时间内,CPU处于 iowait 状态的时间。接着再将其除以总时间,得到 iowait 占用总时间的比率。

现在我们来看看 /proc/stat 文件是怎样获取 iowait 的时间的。

在内核中,每个 CPU 都有一个 cpu_usage_stat 结构,主要用于统计 CPU 一些信息,其定义如下:

struct cpu_usage_stat {
    cputime64_t user;
    cputime64_t nice;
    cputime64_t system;
    cputime64_t softirq;
    cputime64_t irq;
    cputime64_t idle;
    cputime64_t iowait;
    cputime64_t steal;
    cputime64_t guest;
    cputime64_t guest_nice;
};

cpu_usage_stat 结构的 iowait 字段记录了 CPU 处于 iowait 状态的时间。

所以要获取系统处于 iowait 状态的总时间,只需要将所有 CPU 的 iowait 时间相加即可,代码如下(位于源文件 fs/proc/stat.c):

static int show_stat(struct seq_file *p, void *v)
{
    u64 iowait;
    ...
    // 1. 遍历系统中的所有CPU
    for_each_possible_cpu(i) {
        ...
        // 2. 获取CPU对应的iowait时间,并相加
        iowait = cputime64_add(iowait, kstat_cpu(i).cpustat.iowait);
        ...
    }
    ...
    return 0;
}

show_stat() 函数首先会遍历所有 CPU,然后读取其 iowait 时间,并且将它们相加。

 

 资料直通车:Linux内核源码技术学习路线+视频教程内核源码

学习直通车:Linux内核源码内存调优文件系统进程管理设备驱动/网络协议栈

增加iowait时间

从上面的分析可知,每个 CPU 都有一个用于统计 iowait 时间的计数器,那么什么时候会增加这个计数器呢?

答案是:系统时钟中断

在 系统时钟中断 中,会调用 account_process_tick() 函数来更新 CPU 的时间,代码如下:

void account_process_tick(struct task_struct *p, int user_tick)
{
    cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy);
    struct rq *rq = this_rq();

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

我们主要关注当前进程是 idle 进程的情况,这是内核会调用 account_idle_time() 函数进行处理,其代码如下:

void account_idle_time(cputime_t cputime)
{
    struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
    cputime64_t cputime64 = cputime_to_cputime64(cputime);
    struct rq *rq = this_rq();

    // 1. 如果当前有进程在等待IO请求的话,那么增加iowait的时间
    if (atomic_read(&rq->nr_iowait) > 0) {
        cpustat->iowait = cputime64_add(cpustat->iowait, cputime64);
    }
    // 2. 否则增加idle的时间
    else {
        cpustat->idle = cputime64_add(cpustat->idle, cputime64);
    }
}

account_idle_time() 函数的逻辑比较简单,主要分以下两种情况进行处理:

  1. 如果当前有进程在等待 I/O 请求的话,那么增加 iowait 的时间。
  2. 如果当前没有进程在等待 I/O 请求的话,那么增加 idle 的时间。

所以,从上面的分析可知,要增加 iowait 的时间需要满足以下两个条件:

  1. 当前进程是 idle 进程,也就是说 CPU 处于空闲状态。
  2. 有进程在等待 I/O 请求完成。

进一步说,当 CPU 处于 iowait 状态时,说明 CPU 处于空闲状态,并且系统中有进程因为等待 I/O 请求而阻塞,也说明了 CPU 的利用率不够充分。

这时,我们可以使用异步 I/O(如 iouring)来优化程序,使得进程不会被 I/O 请求阻塞。

 

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

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

相关文章

联诚发携多款创新产品及解决方案惊艳亮相ISLE 2023展!

这里写自定义目录标题4月7日-9日,ISLE 2023国际智慧显示及系统集成展览会在深圳国际会展中心(宝安新馆)隆重举行。来自全球各地1000余家企业参与展出,展出面积达8万㎡,吸引了众多业内专家、企业家以及广大观众前来观看…

《攻防演练》在没有基础安全能力的情况下如何做好蓝队防守

目的: 1、净化企业或机构的网络环境、强化网络安全意识; 2、防攻击、防破坏、防泄密、防重大网络安全故障; 3、检验企业关键基础设施的安全防护能力; 4、提升关键基础设施的网络安全防范能力和水平。 现状: 那么问…

什么是 prompts, completions, and tokens

从字面上看,任何文本都可以用作提示(prompts)——输入一些文本然后得到一些文本。 我们虽然知道 GPT-3 对随机字符串的处理很有趣,但是编写一个有效的提示才能更好的真正的让GPT理解我们要它做什么。 提示(prompts) Prompt是怎么…

DHTMLX Gantt入门使用教程【引入】:如何开始使用 dhtmlxGantt

DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的大部分开发需求,具备完善的甘特图图表库,功能强大,价格便宜,提供丰富而灵活的JavaScript API接口,与各种服务器端技术&am…

vue3插槽的使用

插槽就是子组件中的提供给父组件使用的一个占位符&#xff0c;用 表示&#xff0c;父组件可以在这个占位符中填充任何模板代码&#xff0c;如 HTML、组件等&#xff0c;填充的内容会替换子组件的标签。 1.插槽基本使用 子组件SlotComponent.vue <template><div cla…

Salesforce Admin管理员中文学习教程_如何高效筛选出具有Admin权限的用户!

组织中最常见的错误之一就是拥有太多具有系统管理员简档的用户。不幸的是&#xff0c;这在某些行业中非常普遍。 实际上这存在着很大的潜在风险。拥有这些权限的用户可能会暴露、窃取或删除组织中的数据&#xff0c;甚至影响到其他用户。防止过多的管理员访问权限是保护Salesf…

CSDN博客写作编辑器如何使用?

文章目录0.引言1.快捷键2.文字3.链接和代码4.注脚和注释5.公式6.表7.图0.引言 笔者阅读CSDN博客已有五年&#xff0c;从最初的学习跟随者&#xff0c;到现在的CSDN博客创造者&#xff0c;这其中的转变来源于自身发展的思考&#xff0c;有学的输入&#xff0c;又有创作的输出&am…

GPT关键词挖掘,自动关键词文章生成

随着互联网的发展&#xff0c;内容营销已成为企业营销策略中不可或缺的一环。有效的关键词文章生成可以帮助企业吸引更多的潜在客户&#xff0c;提高品牌曝光度和转化率&#xff0c;从而实现营销目标。 关键词文章生成是指根据特定的关键词和主题&#xff0c;使用软件工具自动生…

计算机的工作原理

文章目录前言一、计算机组成二、工作原理1.首先指令输入——由鼠标/键盘完成&#xff1a;2.计算机对指令/输出的处理——由CPU完成&#xff1a;3.计算机对信息的储存——由内存、磁盘完成&#xff1a;4.计算机输出信息——由显卡、显示器完成&#xff1b;总结前言 电脑最直白、…

剪枝与重参第五课:前置知识

目录前置知识前言1.CIFAR10数据集1.1 简介1.2 数据集的获取1.3 数据集的加载2.VGG网络搭建2.1 VGGNet2.2 VGG网络实现3.Batch Normalize3.1 简介3.2 BN层实现4.L1&L2正则4.1 L1正则化(Lasso回归)4.2 L2正则化(岭回归)4.3 思考5.train5.1 parse_opt5.2 train5.3 test5.4 sav…

基于Amazon S3的通用封装oss-spring-boot-starter,支持前端分片直传

前段时间使用minio-java封装了一个 minio-spring-boot-starter&#xff0c;但是有局限性&#xff0c;不能很好的支持各个云服务厂商的OSS服务&#xff0c;为此&#xff0c;利用 aws-java-sdk-s3 做一个统一的封装&#xff0c;兼容S3 协议的通用文件存储工具类 &#xff0c;支持…

打造高效的跑腿配送系统,分享源码与经验

打造高效的跑腿配送系统&#xff0c;则是每一个快递公司和物流企业所追求的目标。在这篇文章中&#xff0c;我们将分享一些跑腿配送系统源码的技术解析、跑腿系统骑手端、商家端的优点以及跑腿配送相关的功能点介绍。 一、跑腿配送系统源码的技术解析 跑腿配送系统源码主要采…

1679_电子生产中的治具了解

全部学习汇总&#xff1a; GreyZhang/g_hardware_basic: You should learn some hardware design knowledge in case hardware engineer would ask you to prove your software is right when their hardware design is wrong! (github.com) 工作中切换了一下角色&#xff0c;做…

安装pyinstaller打包EXE

安装pyinstaller pycharm 左下角&#xff0c;打开包管理器 左上角输入要搜索的包 右上角点击安装 安装完后在 File - Settings - Projecxt:XXX 中设置 Python Interpreter 设置系统环境变量 打包时报错&#xff1a;找不到pyinstaller命令 pyinstaller : 无法将“pyinstal…

自动控制原理模拟卷4

自动控制原理模拟题四 Question1 仓库大门自动开闭控制系统原理图如下图所示,说明系统自动控制大门开闭的工作原理并画出系统方块图; 解: 当合上开门开关时,电位器桥式测量电路产生一个偏差电信号;此偏差电压经放大器放大后,驱动伺服电动机带动绞盘转动,使大门提起;与…

五、Locust之HTTP用户类

HttpUser是最常用的用户。它增加了一个客户端属性&#xff0c;用来进行HTTP请求。 from locust import HttpUser, task, betweenclass MyUser(HttpUser):wait_time between(5, 15)task(4)def index(self):self.client.get("/")task(1)def about(self):self.client.…

Python标准库 --- json库

目录 一、简介 二、属性 三、数据格式 一、简介 Json&#xff0c;全称JavaScript Object Notation&#xff0c;也就是JavaScript对象标记&#xff0c;通过对象和数组的组合表示数据&#xff0c;虽然构造简洁但是结构化程度非常高&#xff0c;是一种轻量级的数据交换格式。J…

ftp-vsftpd(Centos)

一.关闭selinux跟防火墙 setenforce 0 systemctl stop firewalld 二.安装vsftpd yum install vsftpd -y 三.创建虚拟用户与目录并申请证书 mkdir /webdata 根目录 chmod 777 /webdata/ useradd webadmin 上传的文件映射为webadmin vim user webuser虚拟用户 通过d…

Android---内存泄漏检测核心原理

目录 LeakCanary 核心原理 LeakCanary 检测对象的类型 ReferenceQueue 与 WeakReference LeakCanary 里的监控列表与保留列表 常见内存泄漏案例 1. 单例导致内存泄漏 2. 静态变量导致内存泄漏 3. 非静态内部类导致内存泄漏 4. 未取消注册或回调导致内存泄漏 5. Timer…

paddleocr 实操笔记 (前向后梳理)

要点&#xff1a; 参考&#xff1a; 基于PaddleOCR的数字显示器字符识别 工业仪表数值识别 前言 问题分析 要处理电表中的数据&#xff0c;可以分为步骤&#xff0c;拆解为以下问题&#xff1a; 感兴趣区域定位问题OCR读数问题 针对问题1,经过实验与探索&#xff0c;也找到…