%IOwait 一个迷之参数,top/iostat/mpstat/sar 都会统计的关键数据,字面理解是系统等待IO的时间,经常用于反映系统IO压力。 IOwait时候CPU在干什么?什么时间才算IOwait,到底在wait什么?

数据含义及来源

man mpstat 查看下官方定义

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

统计工具对IOwait的定义是CPU idle时系统有IO请求的时间百分比,也就是说要满足两个条件才会被记录为IOwait

1.CPU idle

2.有IO请求在处理

%iowait 数据来自/proc/stat 第5个参数,这里的数据又是怎么来的?

内核IOwait时间统计(kernel 5.3)

1. /proc/stat 数据来源

fs/proc/stat.c show_stat() 中找到/proc/stat 获取 iowait的路径 get_iowait_time()->get_cpu_iowait_time_us()。

根据CPU当前状态 online/offline,选择从cpustat.iowait 或者get_cpu_iowait_time_us() 获取iowait

static u64 get_iowait_time(struct kernel_cpustat *kcs, int cpu)
{u64 iowait, iowait_usecs = -1ULL;if (cpu_online(cpu))iowait_usecs = get_cpu_iowait_time_us(cpu, NULL);if (iowait_usecs == -1ULL)/* !NO_HZ or cpu offline so we can rely on cpustat.iowait */iowait = kcs->cpustat[CPUTIME_IOWAIT];elseiowait = iowait_usecs * NSEC_PER_USEC;return iowait;
}

get_cpu_iowait_time_us()数据来源于每个CPU 的 ts->iowait_sleeptime

u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time)
{struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);ktime_t now, iowait;if (!tick_nohz_active)return -1;now = ktime_get();if (last_update_time) {update_ts_time_stats(cpu, ts, now, last_update_time);iowait = ts->iowait_sleeptime;} else {if (ts->idle_active && nr_iowait_cpu(cpu) > 0) {ktime_t delta = ktime_sub(now, ts->idle_entrytime);iowait = ktime_add(ts->iowait_sleeptime, delta);} else {iowait = ts->iowait_sleeptime;}}return ktime_to_us(iowait);
}

即iowait 来源为 cpustat.iowait  或者 CPU 相关的 ts->iowait_sleeptime 。

2. cpustat.iowait/iowait_sleeptime 统计

这两个参数的累加函数为

void account_idle_time(u64 cputime)
{u64 *cpustat = kcpustat_this_cpu->cpustat;struct rq *rq = this_rq();if (atomic_read(&rq->nr_iowait) > 0)cpustat[CPUTIME_IOWAIT] += cputime;elsecpustat[CPUTIME_IDLE] += cputime;
}
static void
update_ts_time_stats(int cpu, struct tick_sched *ts, ktime_t now, u64 *last_update_time)
{ktime_t delta;if (ts->idle_active) {delta = ktime_sub(now, ts->idle_entrytime);if (nr_iowait_cpu(cpu) > 0)ts->iowait_sleeptime = ktime_add(ts->iowait_sleeptime, delta);elsets->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta);ts->idle_entrytime = now;}if (last_update_time)*last_update_time = ktime_to_us(now);
}

调用栈为:

do_idle()->tick_nohz_idle_exit()->__tick_nohz_idle_restart_tick()->tick_nohz_account_idle_ticks()->account_idle_ticks()->account_idle_time()

do_idle()->tick_nohz_idle_exit()->tick_nohz_stop_idle()->update_ts_time_stats()

即CPU idle时会触发计数,具体计数哪个根据cpu状态判断。

两个数据的计数逻辑一样,都是根据当前cpu runqueue的nr_iowait 判断时间要累加在idle 或者 iowait 。

3.nr_iowait 哪里统计

调度时若当前task是in_iowait,则当前CPU runqueue 的nr_iowait 加1,表示当前有task在等待IO,参考__schedule() 。

 if (!preempt && prev->state) {if (signal_pending_state(prev->state, prev)) {prev->state = TASK_RUNNING;} else {deactivate_task(rq, prev, DEQUEUE_SLEEP | DEQUEUE_NOCLOCK);if (prev->in_iowait) {atomic_inc(&rq->nr_iowait);delayacct_blkio_start();}}switch_count = &prev->nvcsw;}

task的in_iowait 在 io_schedule_prepare()中设置,调用io_schedule_prepare()的相关函数有io_schedule(), io_schedule_time() , mutex_lock_io() , mutex_lock_io_nested() 等。 即当因这些调用产生调度则标记当前CPU有iowait的task,task重新wakeup时in_iowait恢复,cpu runqueu 的nr_iowait减1。

int io_schedule_prepare(void)
{int old_iowait = current->in_iowait;current->in_iowait = 1;blk_schedule_flush_plug(current);return old_iowait;
}

总的来说当有task因为IO而被调度出CPU时,标识该CPU有在等待IO的task,当CPU进入idle时如果仍有等待IO的task,就标记这段时间为IOwait,否则标记为idle, 与man mpstat中的定义一致。

IO在哪里阻塞

系统中执行IO的流程非常的多,其阻塞点也很多,这里列出两个通常IO操作中最常见的阻塞点。

1. io提交至驱动后,等待数据返回。

2. 有并发IO请求时争抢IO软/硬队列等资源。

用 kprobe 观察两种测试场景,单线程IO/多线程IO,的io_schedule调用栈

单线程read,仅有一种调用栈

             fio-7834  [001] d... 875382.127151: io_schedule: (io_schedule+0x0/0x40)fio-7834  [001] d... 875382.127163: <stack trace>=> io_schedule=> ext4_file_read_iter=> new_sync_read=> __vfs_read=> vfs_read=> ksys_pread64=> sys_pread64=> ret_fast_syscall

多线程read,多了因争抢IO资源产生的io调度

            fio-9800  [001] d... 875471.769845: io_schedule: (io_schedule+0x0/0x40)fio-9800  [001] d... 875471.769858: <stack trace>=> io_schedule=> ext4_file_read_iter=> new_sync_read=> __vfs_read=> vfs_read=> ksys_pread64=> sys_pread64=> ret_fast_syscall=> 0xbe9445a8fio-9801  [003] d... 875471.770153: io_schedule: (io_schedule+0x0/0x40)fio-9801  [003] d... 875471.770164: <stack trace>=> io_schedule=> blk_mq_get_request=> blk_mq_make_request=> generic_make_request=> submit_bio=> ext4_mpage_readpages=> ext4_readpages=> read_pages=> __do_page_cache_readahead=> force_page_cache_readahead=> page_cache_sync_readahead=> generic_file_read_iter=> ext4_file_read_iter=> new_sync_read=> __vfs_read=> vfs_read=> ksys_pread64=> sys_pread64=> ret_fast_syscall=> 0xbe9445a8

结论

IOwait 是指CPU空闲时,且当前有task在等待IO的时间。

因IO阻塞而调度主要出现在 1.等待数据返回; 2.并发IO时竞争资源

影响该时间的因素很多,不只有IO负载,CPU负载也会严重影响该参数,不可一味根据IOwait判断系统的IO压力,还需要结合iostat 等数据综合判断。

IOwait 到底在wait什么相关推荐

  1. c语言中aver是什么意思_Linux系统top命令中的io使用率,到底是什么意思?

    最近在做连续数据流的缓冲系统,C语言代码实现后,粗略测试了下,功能上应该没有问题.那么,接下来就该测试性能了.输入 top 命令,的确可以看到一系列 cpu 使用率,其中一个值得注意的子项就是 io ...

  2. linux存储技术学习资料

    参考 https://www.cnblogs.com/pengdonglin137/p/16525428.html Linux I/O栈 Linux内核的I/O栈大图 知乎Linux I/O专栏1 L ...

  3. 02丨基础篇:到底应该怎么理解“平均负载”?

    每次发现系统变慢时,我们通常做的第一件事,就是执行 top 或者 uptime 命令,来了解系统的负载情况.比如像下面这样,我在命令行里输入了 uptime 命令,系统也随即给出了结果. $ upti ...

  4. hd disk / disk raid / disk io / iops / iostat / iowait / iotop / iometer

    DISK IOPS / Input/Output Operations Per Second http://baike.baidu.com/view/2302083.htm IOPS (Input/O ...

  5. Iowait的成因、对系统影响及对策

    什么是iowait? 顾名思义,就是系统因为io导致的进程wait.再深一点讲就是:这时候系统在做io,导致没有进程在干活,cpu在执行idle进程空转,所以说iowait的产生要满足两个条件,一是进 ...

  6. 数据分析需要懂linux吗,学数据分析到底要不要掌握Linux-Python基础前传(2) ......

    Python数据分析师到底要不要掌握Linux? 对于上面的问题,大部分的答案是Python数据分析在windows的环境下跑跑就可以了,没有必要再花时间来学习Linux; 这里jacky有一个明确的 ...

  7. [转载]Tensorflow 的reduce_sum()函数的axis,keep_dim这些参数到底是什么意思?

    转载链接:https://www.zhihu.com/question/51325408/answer/125426642 来源:知乎 这个问题无外乎有三个难点: 什么是sum 什么是reduce 什 ...

  8. 硬核科普:到底啥是云原生?

    本文主要根据课程 什么是云原生?_哔哩哔哩_bilibili 总结而来,其他参考文章如下: <云原生人才计划之Kubernetes 技术图谱>发布! - 知乎 (zhihu.com) ku ...

  9. 深度学习到底有哪些卷积?

    深度学习到底有哪些卷积? 深度学习中不同种类的卷积(比如 2D / 3D / 1x1 /转置/扩张(Atrous)/空间可分/深度可分/平展/分组/混洗分组卷积),能帮理解实际的工作方式. 总结深度学 ...

最新文章

  1. 如何用Python快速抓取Google搜索?
  2. Keras—ModelCheckpoint
  3. sql 游标_SQL基础丨游标
  4. JAVA设计模式(09):结构型-代理模式(Proxy)
  5. 单例模式(Singleton-Pattern)百媚生
  6. 13 种 JavaScript 代码技巧
  7. 【大学课程】计算机组成原理知识点
  8. Error querying database. Cause: java.sql.SQLSyntaxErrorException: ORA-00911: 无效字符
  9. H3C 单区域OSPF配置示例二
  10. 计算机操作系统原理教程与实训(目录)
  11. anaconda下安装新包一直报错(‘parse() got an unexpected keyword argument 'transport_encoding'’)...
  12. figtree如何编辑进化树_进化树的注释:ggtree
  13. [转]程序员应打破牢笼,展望更高层次的世界
  14. SUS安装配置简明图解攻略
  15. Android studio 报错 Gradle sync failed 你的主机中的软件中止了一个已建立的连接
  16. Logisim实验一
  17. 【Linux CentOS系统】Matplotlib不显示Times New Roman
  18. excel保存快捷键_Excel新手必备的5大技巧,看看你会几个?(附26个超实用快捷键)
  19. 计算机信息心得体会作文50字,考试感想作文50字5篇
  20. 正则表达式前端使用手册

热门文章

  1. CCNP路由:EIGRP笔记
  2. CSS+JS实现图片集展示(二)
  3. Cocos Creator开发技术研究:微信小游戏中音效中断问题处理
  4. 分布式搜索引擎search.minty dowser类聚引擎和larbin蜘蛛
  5. 你不知道的服装ERP系统的功能模块与好处!
  6. Exception in thread main java.lang.SecurityException: Prohibited package name: java.com.
  7. 暑期科研见习总结:移动设备上的深度学习与模型剪枝初探
  8. 解读《网络产品安全漏洞管理规定》
  9. 主流手机CPU及机型介绍
  10. elementUI的日期选择组件只能选择当前年的日期,不能选择之前年和之后年的日期