深入浅出计算机组成原理学习笔记:第四十四讲
在专栏一开始的时候,我和你说过,在计算机组成原理这门课里面,很多设计的核心思路,都来源于性能。在前免讲解CPU的时候,相信你已经有了切身的感受了。
大部分程序员开发的都是应⽤系统。在开发应用系统的时候,我们遇到的性能瓶颈大部分都在I/O上。在第36讲讲解局部性原理的时候,我们一起看了通过把内存当作是缓存,
来提升系统的整体性能。在第37讲讲解CPU Cache的时候,我们一起看了CPU Cache和主内存之间性能的巨大差异
然而,我们知道,并不是所有问题都能靠利⽤内存或者CPU Cache做一层缓存来解决。特别是在这个“大数据”的时代。我们在硬盘上存储了越来越多的数据,
一个MySQL数据库的单表有个几千万条记录,早已经不算是什么罕见现象了。这也就意味着,用内存当缓存,存储空间是不够用的。大部分时间,
我们的请求还是要打到硬盘上。那么,这⼀讲我们就来看看硬盘I/O性能的事儿。
一、随机IO
1、硬盘厂商
2、数据传输率
HDD硬盘
SSD硬盘
3、响应时间
Acc.Time
指标和日常的经验不符啊
光看响应时间和吞吐率这两个指标,似乎我们的硬盘性能很不错、我们平时往数据库里写入一条记录,也就是1KB左右的大小。我们拿200MB去除以1KB,
也能够在几毫秒时间返回、一秒钟能够传输的数据,也有200MB左右
顺序读写和随机读写
随机读写
顺序读写
二、OPS和DTR才是输入输出性能的核心指标
实际开发中对数据的访问
服务器承受的“并发”
三、性能瓶颈在
硬盘性能
CPU性能
和我们硬盘能够进⾏的操作数,也有好一个数量级的差异,因为很多时候,CPU指令发出去之后,不得不去“等”我们的I/O操作完成,才能进入下一步的操作
四、如何定位IO_WAIT?
那么,在实际遇到服务端程序的性能问题的时候,我们怎么知道这个问题是不是来自于CPU等I/O来完成操作呢?别着急,我们接下来,
就通过top和iostat这些命令,一起来看看CPU到底有没有在等待io操作。
1、top
1 2 3 4 5 | top - 06:26:30 up 4 days, 53 min, 1 user, load average: 0.79, 0.69, 0.65 Tasks: 204 total, 1 running, 203 sleeping, 0 stopped, 0 zombie %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 st KiB Mem: 7679792 total, 6646248 used, 1033544 free , 251688 buffers KiB Swap: 0 total, 0 used, 0 free . 4115536 cached Mem |
2、iowat
1 2 3 4 | avg-cpu: %user % nice %system %iowait %steal %idle 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”这个命令。
3、iotop
1 2 3 4 5 6 7 | 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是怎么样的。
4、完整案例
我在一台云平台上的单个CPU核⼼的机器上输⼊“stress-i2”,让stress这个程序模拟两个进程不停地从内存里往硬盘上写数据。
1 | stress -i 2 |
top查看负载和wa
1 2 3 4 5 6 | top top - 06:56:02 up 3 days, 19:34, 2 users , load average: 5.99, 1.82, 0.63 Tasks: 88 total, 3 running, 85 sleeping, 0 stopped, 0 zombie %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 st KiB Mem : 1741304 total, 1004404 free , 307152 used, 429748 buff /cache KiB Swap: 0 total, 0 free , 0 used. 1245700 avail Mem |
iowat查看iops
1 2 3 4 5 | iostat 2 5 avg-cpu: %user % nice %system %iowait %steal %idle 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 |
如果我们通过iostat,查看硬盘的I/O,你会看到,里面的tps很快就到了4万左右,占满了对应硬盘的IOPS。
iotop查看io占用排行榜
1 2 3 4 5 6 7 | 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的瓶颈,以及这些瓶颈来自于哪些程序,你就可以根据定位的结果来优化你自己的程序了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
2017-08-16 第一章:数据结构和算法