首页 > 其他分享 >44 | 理解IO_WAIT:I/O性能到底是怎么回事儿?

44 | 理解IO_WAIT:I/O性能到底是怎么回事儿?

时间:2023-05-22 15:35:12浏览次数:37  
标签:44 性能 CPU IO SSD 我们 0.00 硬盘 WAIT


在专栏一开始的时候,我和你说过,在计算机组成原理这门课里面,很多设计的核心思路,都来源于性能。在前面讲解 CPU 的时候,相信你已经有了切身的感受了。


第 36 讲 讲解局部性原理的时候,我们一起看了通过把内存当作是缓存,来提升系统的整体性能。在 第 37 讲


然而,我们知道,并不是所有问题都能靠利用内存或者 CPU Cache 做一层缓存来解决。特别是在这个“大数据”的时代。我们在硬盘上存储了越来越多的数据,一个 MySQL 数据库的单表有个几千万条记录,早已经不算是什么罕见现象了。这也就意味着,用内存当缓存,存储空间是不够用的。大部分时间,我们的请求还是要打到硬盘上。那么,这一讲我们就来看看硬盘 I/O 性能的事儿。


IO 性能、顺序访问和随机访问


响应时间 (Response Time),另一个叫作 数据传输率


我们先来看一看后面这个指标,数据传输率。


我们现在常用的硬盘有两种。一种是 HDD 硬盘,也就是我们常说的机械硬盘。另一种是 SSD 硬盘,一般也被叫作固态硬盘。现在的 HDD 硬盘,用的是 SATA 3.0 的接口。而 SSD 硬盘呢,通常会用两种接口,一部分用的也是 SATA 3.0 的接口;另一部分呢,用的是 PCI Express 的接口。


这个带宽相当于每秒可以传输 768MB 的数据。而我们日常用的 HDD 硬盘的数据传输率,差不多在 200MB/s 左右。



44 | 理解IO_WAIT:I/O性能到底是怎么回事儿?_ios


这是在我自己的电脑上,运行 AS SSD 测算 SATA 接口 SSD 硬盘性能的结果,第一行的 Seq 就是顺序读写硬盘得到的数据传输率的实际结果


当我们换成 SSD 的硬盘,性能自然会好上不少。比如,我最近刚把自己电脑的 HDD 硬盘,换成了一块 Crucial MX500 的 SSD 硬盘。它的数据传输速率能到差不多 500MB/s,比 HDD 的硬盘快了一倍不止。不过 SATA 接口的硬盘,差不多到这个速度,性能也就到顶了。因为 SATA 接口的速度也就这么快。



44 | 理解IO_WAIT:I/O性能到底是怎么回事儿?_ios_02


不过,实际 SSD 硬盘能够更快,所以我们可以换用 PCI Express 的接口。我自己电脑的系统盘就是一块使用了 PCI Express 的三星 SSD 硬盘。它的数据传输率,在读取的时候就能做到 2GB/s 左右,差不多是 HDD 硬盘的 10 倍,而在写入的时候也能有 1.2GB/s。


除了数据传输率这个吞吐率指标,另一个我们关心的指标响应时间,其实也可以在 AS SSD 的测试结果里面看到,就是这里面的 Acc.Time 指标。


这个指标,其实就是程序发起一个硬盘的写入请求,直到这个请求返回的时间。可以看到,在上面的两块 SSD 硬盘上,大概时间都是在几十微秒这个级别。如果你去测试一块 HDD 的硬盘,通常会在几毫秒到十几毫秒这个级别。这个性能的差异,就不是 10 倍了,而是在几十倍,乃至几百倍。


光看响应时间和吞吐率这两个指标,似乎我们的硬盘性能很不错。即使是廉价的 HDD 硬盘,接收一个来自 CPU 的请求,也能够在几毫秒时间返回。一秒钟能够传输的数据,也有 200MB 左右。你想一想,我们平时往数据库里写入一条记录,也就是 1KB 左右的大小。我们拿 200MB 去除以 1KB,那差不多每秒钟可以插入 20 万条数据呢。但是这个计算出来的数字,似乎和我们日常的经验不符合啊?这又是为什么呢?


在 顺序读写 和 随机读写 的情况下,硬盘的性能是完全不同的。


我们回头看一下上面的 AS SSD 的性能指标。你会看到,里面有一个“4K”的指标。这个指标是什么意思呢?它其实就是我们的程序,去随机读取磁盘上某一个 4KB 大小的数据,一秒之内可以读取到多少数据。


更重要的是,你会发现,即使我们用 PCI Express 的接口,在随机读写的时候,数据传输率也只能到 40MB/s 左右,是顺序读写情况下的几十分之一。


我们拿这个 40MB/s 和一次读取 4KB 的数据算一下。


40MB / 4KB = 10,000


也就是说,一秒之内,这块 SSD 硬盘可以随机读取 1 万次的 4KB 的数据。如果是写入的话呢,会更多一些,90MB /4KB 差不多是 2 万多次。


这个每秒读写的次数,我们称之为 IOPS ,也就是每秒输入输出操作的次数。事实上,比起响应时间,我们更关注 IOPS 这个性能指标。IOPS 和 DTR(Data Transfer Rate,数据传输率)才是输入输出性能的核心指标。


这是因为,我们在实际的应用开发当中,对于数据的访问,更多的是随机读写,而不是顺序读写。我们平时所说的服务器承受的“并发”,其实是在说,会有很多个不同的进程和请求来访问服务器。自然,它们在硬盘上访问的数据,是很难顺序放在一起的。这种情况下,随机读写的 IOPS 才是服务器性能的核心指标。


好了,回到我们引出 IOPS 这个问题的 HDD 硬盘。我现在要问你了,那一块 HDD 硬盘能够承受的 IOPS 是多少呢?其实我们应该已经在第 36 讲说过答案了。


HDD 硬盘的 IOPS 通常也就在 100 左右,而不是在 20 万次。在后面讲解机械硬盘的原理和性能优化的时候,我们还会再来一起看一看,这个 100 是怎么来的,以及我们可以有哪些优化的手段。


如何定位 IO_WAIT?


我们看到,即使是用上了 PCI Express 接口的 SSD 硬盘,IOPS 也就是在 2 万左右。而我们的 CPU 的主频通常在 2GHz 以上,也就是每秒可以做 20 亿次操作。


即使 CPU 向硬盘发起一条读写指令,需要很多个时钟周期,一秒钟 CPU 能够执行的指令数,和我们硬盘能够进行的操作数,也有好几个数量级的差异。这也是为什么,我们在应用开发的时候往往会说“性能瓶颈在 I/O 上”。因为很多时候,CPU 指令发出去之后,不得不去“等”我们的 I/O 操作完成,才能进行下一步的操作。


那么,在实际遇到服务端程序的性能问题的时候,我们怎么知道这个问题是不是来自于 CPU 等 I/O 来完成操作呢?别着急,我们接下来,就通过 top 和 iostat 这些命令,一起来看看 CPU 到底有没有在等待 io 操作。





# top





你一定在 Linux 下用过 top 命令。对于很多刚刚入门 Linux 的同学,会用 top 去看服务的负载,也就是 load average。不过,在 top 命令里面,我们一样可以看到 CPU 是否在等待 IO 操作完成。





-                       06
           :
           26
           :
           30
            up 
           4
            days, 
           53
            min, 
           1
            
           user
           , load average: 
           0.79
           , 
           0.69
           , 
           0.65
          
204            total,            1
            
           running
           , 
           203
            sleeping, 
           0
            stopped, 
           0
          
%           Cpu(s):            20.0
            us, 
           1.7
            sy, 
           0.0
            ni, 
           77.7
            id, 
           0.0
            wa, 
           0.0
            hi, 
           0.7
            si, 
           0.0
          
7679792            total,            6646248
            used, 
           1033544
            
           free
           , 
           251688
          
0            total,            0
            used, 
           0
            free. 
           4115536




top 命令的输出结果


这个指标就代表着 iowait,也就是 CPU 等待 IO 完成操作花费的时间占 CPU 的百分比。下一次,当你自己的服务器遇到性能瓶颈,load 很大的时候,你就可以通过 top 看一看这个指标。


知道了 iowait 很大,那么我们就要去看一看,实际的 I/O 操作情况是什么样的。这个时候,你就可以去用 iostat 这个命令了。我们输入“iostat”,就能够看到实际的硬盘读写情况。





$            iostat
          
nice
          

            17.02 0.01 2.18 0.04 0.00 80.76
          
          

           Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
          
          

           sda 1.81 2.02 30.87 706768 10777408





你会看到,这个命令里,不仅有 iowait 这个 CPU 等待时间的百分比,还有一些更加具体的指标了,并且它还是按照你机器上安装的多块不同的硬盘划分的。


这里的 tps 指标,其实就对应着我们上面所说的硬盘的 IOPS 性能。而 kB_read/s 和 kB_wrtn/s 指标,就对应着我们的数据传输率的指标。


知道实际硬盘读写的 tps、kB_read/s 和 kb_wrtn/s 的指标,我们基本上可以判断出,机器的性能是不是卡在 I/O 上了。那么,接下来,我们就是要找出到底是哪一个进程是这些 I/O 读写的来源了。这个时候,你需要“iotop”这个命令。




$            iotop
       
     

           Total DISK READ : 0.00 B/s | Total DISK WRITE : 15.75 K/s
          
          

           Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 35.44 K/s
          
          

            TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND 
          
          

            104 be/3 root 0.00 B/s 7.88 K/s 0.00 % 0.18 % [jbd2/sda1-8]
          
          

            383 be/4 root 0.00 B/s 3.94 K/s 0.00 % 0.00 % rsyslogd -n [rs:main Q:Reg]
          
          

            1514 be/4 www-data 0.00 B/s 3.94 K/s 0.00 % 0.00 % nginx: worker process




通过 iotop 这个命令,你可以看到具体是哪一个进程实际占用了大量 I/O,那么你就可以有的放矢,去优化对应的程序了。


上面的这些示例里,不管是 wa 也好,tps 也好,它们都很小。那么,接下来,我就给你用 Linux 下,用 stress 命令,来模拟一个高 I/O 复杂的情况,来看看这个时候的 iowait 是怎么样的。


我在一台云平台上的单个 CPU 核心的机器上输入“stress -i 2”,让 stress 这个程序模拟两个进程不停地从内存里往硬盘上写数据。





$ stress -i 2

$ top





你会看到,在 top 的输出里面,CPU 就有大量的 sy 和 wa,也就是系统调用和 iowait。


-                       06
           :
           56
           :
           02
            up 
           3
            days, 
           19
           :
           34
           , 
           2
            users, load average: 
           5.99
           , 
           1.82
           , 
           0.63
          
88            total,            3
            
           running
           , 
           85
            sleeping, 
           0
            stopped, 
           0
          
%           Cpu(s):            3.0
            us, 
           29.9
            sy, 
           0.0
            ni, 
           0.0
            id, 
           67.2
            wa, 
           0.0
            hi, 
           0.0
            si, 
           0.0
          
1741304            total,            1004404
            
           free
           , 
           307152
            used, 
           429748
            buff
           /
          
0            total,            0
            
           free
           , 
           0
            used. 
           1245700



$ iostat 2 5





如果我们通过 iostat,查看硬盘的 I/O,你会看到,里面的 tps 很快就到了 4 万左右,占满了对应硬盘的 IOPS。


nice
          

            5.03 0.00 67.92 27.04 0.00 0.00
          
          

           Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
          
          

           sda 39762.26 0.00 0.00 0 0




如果这个时候我们去看一看 iotop,你就会发现,我们的 I/O 占用,都来自于 stress 产生的两个进程了。



$            iotop
     
         

           Total DISK READ : 0.00 B/s | Total DISK WRITE : 0.00 B/s
          
          

           Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 0.00 B/s
          
          

            TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND 
          
          

           29161 be/4 xuwenhao 0.00 B/s 0.00 B/s 0.00 % 56.71 % stress -i 2
          
          

           29162 be/4 xuwenhao 0.00 B/s 0.00 B/s 0.00 % 46.89 % stress -i 2
          
          

            1 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % init




相信到了这里,你也应该学会了怎么通过 top、iostat 以及 iotop,一步一步快速定位服务器端的 I/O 带来的性能瓶颈了。你也可以自己通过 Linux 的 man 命令,看一看这些命令还有哪些参数,以及通过 stress 来模拟其他更多不同的性能压力,看看我们的机器负载会发生什么变化。


总结延伸


这一讲里,我们从硬盘的两个核心指标,响应时间和数据传输率,来理解和研究 I/O 的性能问题。你也自己可以通过 as ssd 这样的性能评测软件,看一看自己的硬盘性能。


在顺序读取的情况下,无论是 HDD 硬盘还是 SSD 硬盘,性能看起来都是很不错的。不过,等到进行随机读取测试的时候,硬盘的性能才能见了真章。因为在大部分的应用开发场景下,我们关心的并不是在顺序读写下的数据量,而是每秒钟能够进行输入输出的操作次数,也就是 IOPS 这个核心性能指标。


你会发现,即使是使用 PCI Express 接口的 SSD 硬盘,IOPS 也就只是到了 2 万左右。这个性能,和我们 CPU 的每秒 20 亿次操作的能力比起来,可就差得远了。所以很多时候,我们的程序对外响应慢,其实都是 CPU 在等待 I/O 操作完成。


在 Linux 下,我们可以通过 top 这样的命令,来看整个服务器的整体负载。在应用响应慢的时候,我们可以先通过这个指令,来看 CPU 是否在等待 I/O 完成自己的操作。进一步地,我们可以通过 iostat 这个命令,来看到各个硬盘这个时候的读写情况。而 iotop 这个命令,能够帮助我们定位到到底是哪一个进程在进行大量的 I/O 操作。


这些命令的组合,可以快速帮你定位到是不是我们的程序遇到了 I/O 的瓶颈,以及这些瓶颈来自于哪些程序,你就可以根据定位的结果来优化你自己的程序了。


标签:44,性能,CPU,IO,SSD,我们,0.00,硬盘,WAIT
From: https://blog.51cto.com/u_15202985/6324692

相关文章

  • 多方安全计算Secure Multi-Party Computation(SMPC)学习笔记
    引言随着数字化时代的到来,数据的价值变得前所未有的重要。然而,随之而来的是对数据隐私和安全的日益关注。个人和组织都希望能够利用敏感数据进行有益的分析和合作,但又不希望将这些数据暴露给其他人。在这种情况下,安全多方计算(SMPC)崭露头角。SMPC是一种创新的加密技术,它允许多个参与......
  • 分析双网口以太网IO模块在智能制造中的角色
    双网口可级联远程IO模块用于工业自动化在当今时代,工业自动化控制有着广泛的应用,而远程I/O模块是其不可或缺的一部分。工业自动化需要远距离数据采集传输的场景越来越多,其中双网口可级联远程I/O模块已成为业界的常用设备之一。本文将从工业自动化的角度出发,讨论双网口可级联远程I/O......
  • expdp 报错ORA-7445 的一个问题展开
    某客户说一套数据库由于非正常关机重启之后,进行数据导出发现报错,expdp无法正常工作,报错之后直接退出:处理对象类型SCHEMA_EXPORT/JOB..导出了"STATS"."T_REPORT_MONTH_TEMPS"988.2MB1292221行ORA-39014:一个或多个......
  • 深入解析buffer busy waits
    在写一个培训ppt的时候,为了深入理解buffebusywaits这个等待事件,做了一个仔细的测试,对大家也有帮助,经过测试,发现我个人以前的认识都有一点问题。大家一起探讨!1.创建测试表www.killdb.com>connroger/rogerConnected.www.killdb.com>create......
  • APIO2023 线下又寄
    前情提要:因为\(\text{CSP-S}\)没挂分所以是线下\(\text{Day0}\)下午三点多到的,从高铁站到华山饭店路上跟一中、学军的一路,本来华二和我们差不多一起到的,但不知道为啥他们先走了,不过在车上都不敢跟\(\text{qiuly}\)他们讲话,实在太社恐了/ll然后就是报道,报完道,开幕式也没啥......
  • Audition 2022 for Mac软件安装包下载Au 2022软件安装教程
    [名称]:Audition2022[大小]:493MB[语言]:简体中文 [安装环境]:MacOS10.15及以上[是否支持M系列芯片]:支持[简介]:Audition是一种完善工具集,其中包括用于对音频内容进行创建、混音和编辑的多音轨、波形和光谱显示。这一强大的音频工作站旨在加快视频制作工作流程和音频修整的速度,并且......
  • Audition 2021 for Mac软件安装包下载Au 2021软件安装教程
    [名称]:Audition2021[大小]:473MB[语言]:简体中文 [安装环境]:MacOS10.14及以上[是否支持M系列芯片]:支持[简介]:Audition是一种完善工具集,其中包括用于对音频内容进行创建、混音和编辑的多音轨、波形和光谱显示。这一强大的音频工作站旨在加快视频制作工作流程和音频修整的速度,并且......
  • Failed to execute 'setSelectionRange' on 'HTMLInputElement'
    jcubic commented on7Jan2016WhenIusenumberinputI'vegoterrorinGoogleChromeUncaughtInvalidStateError:Failedtoexecute'setSelectionRange'on'HTMLInputElement':Theinputelement'stype('number')......
  • 【iOS开发】UIWebView调用JS点击事件(stringByEvaluatingJavaScriptFromString)
    一、场景描述产品需求是移动端app要调用h5页面,然后监听h5代码中的某个方法,最终执行h5中的具体代码。二、具体代码.m文件@interfaceViewController()<UIWebViewDelegate>@property(nonatomic,strong)UIWebView*webView;@end@implementationViewController-(void)viewDid......
  • 【Swift开发】混合开发-React Native集成到原生iOS项目
    一、场景描述针对目前项目需求,部分功能需要动态热部署,因此考虑使用ReactNative。下面有个Demo介绍原生iOS项目是如何与ReactNative集成的。先贴下ReactNative中文网是官方教程:ReactNative嵌入到现有原生应用。对老项目来说,官方推荐使用第三方包管理器CoCoaPods来自动集成,但是考......