朱辉(茶水): Linux Kernel iowait 时间的代码原理

原创 2018年01月01日 00:00:00

作者简介

朱辉,个人主页 http://teawater.github.io/,微信公众号茶水侃山(cschatcs)。

做过几年模拟器,做过几年GDB,在小米电视做过几年Linux内核优化,主要围绕MM。

现在在HyperHQ当软件工程师。

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1

Linuxer祝所有用户新年快乐,感谢您对Linuxer在2017长情的陪伴。继续欢迎您给Linuxer投稿,赢取人民邮电任意在售技术图书:

Linuxer-"Linux开发者自己的媒体"第五月稿件和赠书名单

2018,关注Linuxer,关注Linux技术和技术背后的人

0?wx_fmt=png

更新记录

2017.12.15:

对扩展文章的问题描述进行了精确化。

2017.12.10:

根据张骁和宋宝华老师的建议,将结尾的错误进行了修正。

增加一篇扩展阅读。

增加了对CPU负载均衡问题的讲解。

之前在我热爱的公众号Linuxer看到The precise meaning of I/O wait time in Linux 这篇文章,感觉写的不错,就是没有落实到源码上感觉稍微有点晦涩,于是自己读了一下代码。


当task发生iowait的时候,内核对他们的处理方法是将task切换出去,让可运行的task先运行,而在切换出去前,会将其in_iowait设置为1,再次被唤醒的时候in_iowait被设置为原值。相关函数io_schedule,io_schedule_timeout,mutex_lock_io,mutex_lock_io_nested。


例如:

0?wx_fmt=png

由此可见in_iowait表明了这个task是否在iowait。


另外要注意的是,这几个切换函数除了mutex_lock_io,mutex_lock_io_nested会设置task运行状态为TASK_UNINTERRUPTIBLE外,内核在调用io_schedule,io_schedule_timeout前都会设置task运行状态TASK_UNINTERRUPTIBLE。


在进程切换函数__schedule在切换task的时候,如果被切换出的task的in_iowait为真,则会对这个CPU的运行队列rq结构中的nr_iowait加1。


因为前面对task已经被设置为TASK_UNINTERRUPTIBLE,则task需要被唤醒,对nr_iowait的减少操作也是在task唤醒函数来做的。


由此可见nr_iowait可以表明某CPU上是否有task在iowait,以及数量。


因为处于iowait的task是TASK_UNINTERRUPTIBLE状态,其并不在就绪队列中,所以其也没有被CPU负载均衡到其他CPU的可能,所以nr_iowait也不需要处理负载均衡问题。


当累加系统idle时间的时候,如果CPU的nr_iowait为真,也就是当前这个cpu有task在等待iowait,则记录为iowait时间。


在打开NO_HZ的内核中,相关代码在update_ts_time_stats。

0?wx_fmt=png


而没打开的则在 account_idle_time。

0?wx_fmt=png

当相关/proc/stat接口被访问时,get_iowait_time就会访问这个时间并返回。

综上所述,iowait时间就是CPU idle时间,但是这时候CPU上不是完全没TASK需要运行,而是休眠的task中有一个或者若干个是iowait的task。


当然idle和iowait的时候CPU上还有idle task。


最后推荐一篇阿里内核组的文章作为扩展阅读Kernel Documents/new iowait calculation (http://link.zhihu.com/?target=http%3A//kernel.taobao.org/index.php%3Ftitle%3DKernel_Documents/new_iowait_calculation)


比较有意思是这里:

 

+       wait_event_interruptible_hrtimeout(ctx->wait,

+                       aio_read_events(ctx, min_nr, nr, event, &ret), until);

无论超时值until是什么值,都会调用wait_event_interruptible_hrtimeout,虽然是hrtimer实时性已经很高,但是在用来实际处理wait的宏__wait_event_hrtimeout可以看到hrtimer初始化使用的是:

hrtimer_start_range_ns(&__t.timer, timeout,\

       current->timer_slack_ns,\

       HRTIMER_MODE_REL);\

其中第三个参数current->timer_slack_ns是传递给hrtimer的触发范围,因为hrtimer实时性高,但是频繁触发系统显然受不了,所以每次hrtimer触发都会将时间范围内的timer都处理掉(见__hrtimer_run_queues)。所以timeout+current->timer_slack_ns才是设置的hrtimer的最后触发时间,current->timer_slack_ns的默认值是50000,也就是代表50000纳秒。也就是这个时钟最久会在50000纳秒后触发,当然也可能被之前的hrtimer触发。


所以在wait_event_interruptible_hrtimeout中,一旦ctx->wait未能就绪,即使设置超时时间为0,也很可能要调用一次schedule,这导致iowait时间相差很大,也还很大幅度伤害了性能。


而这个问题也被5f785de588735306ec4d7c875caf9d28481c8b21进行了修复,这段代码改成了:


-       wait_event_interruptible_hrtimeout(ctx->wait,

-                       aio_read_events(ctx, min_nr, nr, event, &ret), until);

+       if (until.tv64 == 0)

+               aio_read_events(ctx, min_nr, nr, event, &ret);

+       else

+               wait_event_interruptible_hrtimeout(ctx->wait,

+                               aio_read_events(ctx, min_nr, nr, event, &ret),

+                               until);


从而在until为0的时候,直接调用aio_read_events。应该就不会再有那么明显的iowait问题了,另外也因此这个修复让io_getevents的调用得到了超过百倍的性能提升。


当然这个iowait不够精确的原因还是存在,一旦因为需要发生task切换,还是会有不够精确的问题。


最后要吐槽一下aio的设计,都aio了还需要wait吗?

0?wx_fmt=png

版权声明:本文为博主原创文章,未经博主允许不得转载。

查找最耗iowait的进程

转载于http://blogold.chinaunix.net/u1/43502/index.html 很多时候发现linux系统输入一些命令很慢,用top查看IOwait占用CPU很高,top...
  • rocky2com
  • rocky2com
  • 2011年08月05日 15:16
  • 7189

关于新闻类应用快速开发框架的思考

序言在上一篇博客 10分钟开发网易新闻首页的框架,我把我正在使用的框架拿出来分享了一下,但是部分同学告诉我源码看不懂,我觉得也有必要说说我对这个框架的思考过程。流程目前我主要开发的是新闻资讯类的应用,...
  • qq_22706515
  • qq_22706515
  • 2016年09月21日 17:11
  • 592

定位 iowait 占用的进程

refer to I/O问题一直是一个比较难定位的问题,今天线上环境遇到了I/O 引起的CPU负载问题,看到了如下这篇比较好的文章,完饭后的我还在和西红柿和黄瓜在减肥的路上抗争,正好将原文翻译...
  • G7N3F
  • G7N3F
  • 2016年09月26日 19:15
  • 904

定位IOWait高的一些方法和工具

[导读]定位IOWait高的一些方法和工具: 在Linux性能分析时经常使用的工具包括:top, iostat, vmstat等 IOWait高的一些处理方法 1、检查RAID的状态,比如是否正在重建...
  • dzhj11
  • dzhj11
  • 2012年06月16日 11:50
  • 817

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

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

top iowait

http://bbs.chinaunix.net/archiver/?tid-296344.html一直都是用的top,刚才看了一下iostat里面的wait项,应该和top里面的iowait项是一样...
  • adaptiver
  • adaptiver
  • 2011年06月18日 13:41
  • 5697

一个数据库服务器高iowait的优化案例

一个数据库服务器高iowait的优化案例1.开发反馈某一测试环境sql运行缓慢,而在其他测试环境该sql运行很快。两个环境其配置相同,均只部署了mysql服务器。 2.执行top命令发现sql运行缓...
  • zyz511919766
  • zyz511919766
  • 2015年11月25日 15:18
  • 2789

Android ANR 搜集

Android ANR排查 应用层一般如下情况下需要查看log 1) 程序异常退出 , uncaused exception 2) 程序强制关闭 ,Force Closed (简称FC) ...
  • lijinwei_123
  • lijinwei_123
  • 2013年05月29日 17:56
  • 2931

iostat和iowait

iostat和iowait[转] 十月 14th, 2011 发表在 linux系统 本文作者:深夜的蚊子 %iowait并不能反应磁盘瓶颈 iowait实际测量的是cpu时...
  • macky0668
  • macky0668
  • 2012年08月07日 16:31
  • 7119

Linux内核时间获取

内核一般通过jiffies值来获取当前时间。尽管该数值表示的是自上次系统启动到当前的时间间隔,但因为驱动程序的生命期只限于系统的运行期 (uptime),所以也是可行的。驱动程序利用jiffies的当...
  • stonesharp
  • stonesharp
  • 2015年05月25日 15:55
  • 2590
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:朱辉(茶水): Linux Kernel iowait 时间的代码原理
举报原因:
原因补充:

(最多只允许输入30个字)