dduo518 / hexo-blog

hexo静态blog点击 https://github.com/chong0808/hexo-blog/issues
3 stars 0 forks source link

iowait 过高 #58

Open dduo518 opened 3 years ago

dduo518 commented 3 years ago

Linux iowait 过高

问题

测试环境的TCP 推送报价,本地开发环境推送到了3000口每秒,但是代码push到测试环境1000口不到,相差近3倍。

本地开发环境 2021-09-22_08-53-16

测试环境 2021-09-22_08-53-15

跟运维反馈之后,运维反馈回复是 IO wait 过高导致。 iowait:

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

iowait 计算方式:

iowait = (cpu idle time)/(all cpu time)

显示系统有未完成的磁盘 I/O 请求期间一个或多个 CPU 空闲的时间百分比

「iowait」指的是 CPU 空闲并且存在未完成 I/O 操作的时间,所占总时间的比例。每个时刻,CPU 都有四种可能的状态:用户(user)、系统(sys)、空闲(idle)、iowait。性能工具诸如 vmstat、iostat、sar,都能显示出这四种状态所占的时间比例。sar(加上 -P 参数)可以显示出每个 CPU 各自的状况,但大部分工具显示的是所有 CPU 的平均值。

当某个 CPU 发生时钟中断时,内核会检查 CPU 是否空闲。如果不空闲,内核就会判断当前指令运行在用户态还是内核态。如果在用户态,则将「用户」计数器加一;如果在内核态,则将「系统」指针加一。

如果 CPU 处于空闲状态,内核就会判断是否至少有一个 IO 操作正在执行,不论对象是本地磁盘,还是该 CPU 负责挂载的远程存储(如 NFS)。如果有,则将「iowait」计数器加一;如果没有进行中的 IO 操作,则将「空闲」计数器加一。

iowait 可能造成的影响

  1. 假设某个程序在执行批处理任务,在每个任务中,程序都会执行 10 毫秒的计算,然后将结果同步写到磁盘上。因为写的文件是以同步模式打开的,直到写入磁盘的操作彻底完成之后,write 才会返回。 假设这个磁盘没有缓存,每次物理写入操作耗时 20 毫秒,于是程序每次执行任务需要 30 毫秒。在 1 秒(1000 毫秒)的周期内,每个程序可以处理 33 个任务(33 tps)。如果这个程序在单 CPU 系统上单任务运行,那么 CPU 就会在 1/3 的时间里忙碌,而在剩下的时间里等待 IO 完成——所以 CPU 会是 67% 的 iowait、33% 的忙碌。 如果改进 IO 子系统(例如加入磁盘缓存),一次 IO 写操作只耗时 1 毫秒,一个任务也就只需要 11 毫秒完成,程序就能每秒完成 90~91 个任务。这时 iowait 的时间比例就会是 8% 左右。注意,这里 iowait 的降低直接提升了程序的性能。

  2. 假设系统上运行着 dd 程序,每次从磁盘读取 4 KB 的数据。假设 dd 将逻辑实现在 main() 中,调用 read() 来读取数据,而这两者都是用户空间里的函数。read() 会接着启动 kread() 系统调用并进入内核态。kread() 会启动设备的物理 IO 操作,随后 dd 程序会进入睡眠状态,直至物理 IO 完成。 程序执行 main、read、kread 的时间非常短暂,可能最多 50 微秒。磁盘完成 IO 的时间可能会在 2~20 毫秒之间,取决于磁盘臂寻道的距离。这就意味着,当时钟中断发生时,dd 程序很可能正处于睡眠状态,等待 IO 操作完成,因而 iowait 计数器会加一。假定 IO 操作在 20 毫秒后完成完成,dd 程序恢复运行,再次执行 50 微秒的自身代码。但是 50 微秒比之 20 毫秒(20000 微秒)是如此短暂,很可能当时钟中断发生时,CPU 还是在等待 IO 完成的空闲状态,所以 iowait 计数器依然会增加。如果每次 IO 操作耗时缩短到 2 毫秒,iowait 就会是 97~98% 左右。尽管这两种情况下 iowait 的比例都非常之高,但第二种情况的吞吐量却是前一种的十倍。

  3. 假设一个 CPU 上运行着两个程序。其中一个是 dd 程序,在读取磁盘;另一个不执行 IO 操作,但使用 100% 的时间片进行计算。假设 IO 子系统出现了故障,每次物理 IO 需要超过一秒来完成。每当 dd 处于睡眠状态、等待 IO 操作完成时,另一个程序都能够在这个 CPU 上运行。当时钟中断发生时,永远都会有一个程序,要么在用户态要么在内核态运行,因此,空闲和 iowait 的比例值都会是 0。尽管现在 iowait 是 0,但并不代表不存在 IO 方面的问题。

通俗理解就是等待IO设备完成其工作时,CPU的空闲比例,但其实在某些场景下,iowait高并不等于说有异常,需要酌情分析。 iowait 的值不一定是有用的 IO 性能指标,但它的确可以告诉我们,这个系统能够处理更多的计算工作。处在 iowait 状态的 CPU 并非不能运行其他线程,iowait 只是空闲的一种形式而已。