Linux性能优化实战学习笔记:第十三讲

问题1:性能工具版本太低,导致指标不全

解决方案1:

这是使用 CentOS 的同学普遍碰到的问题。在文章中,我的pidstat 输出里有一个 %wait 指标,代表进程等待 CPU 的时间百分比,

这是 systat 11.5.5 版本才引入的新指标,旧版本没有这一项。而 CentOS 软件库里的 sysstat 版本刚好比这个低,所以没有这项指标。

解决方案2

查看proc文件系统,获取自己想要的指标

问题 2:使用 stress 命令,无法模拟 iowait高的场景

1、分析过程:

使用 stress 无法模拟 iowait 升高,但是却看到sys 升高。这是因为案例中 的 stress -i 参数它表示通过系统调用 sync() 来模拟 I/O 的问题,但这种方法实际上并不可靠。

因为 sync() 的本意是刷新内存缓冲区的数据到磁盘中,以确保同步。如果缓冲区内本来就没多少数据,那读写到磁盘中的,的数据也就不多,也就没法产生 I/O 压力。

这一点,在使用 SSD 磁盘的环境中尤为明显,很可能你的iowait总是 0,却单纯因为大量的系统调用,导致了系CPU 使用率 sys 升高。

2、解决方案:

使用 stress-ng 来代替 stress。

1
$ stress-ng -i 1 --hdd 1 --timeout 600

 -i 的含义还是调用 sync,而—hdd 则表示读写临时文件

问题3:无法模拟出 RES 中断的问题

 

 中断在单核(只有一个逻辑 CPU)的机器上当然就没有意义了,因为压根儿就不会发生重调度的情况。

1、过多的线程争抢CPU

根据非自愿上下文的含义,我们都知道,这是过多的线程在争抢 CPU导致的,其实这个结论也可以从另一个角度获得

1
2
3
4
5
6
7
8
9
pidstat -u -t 1
 
14:24:03 UID TGID TID %usr %system %guest %wait %CPU CPU Command
14:24:04 0 - 2472 0.99 8.91 0.00 77.23 9.90 0 |__sysbench
14:24:04 0 - 2473 0.99 8.91 0.00 68.32 9.90 0 |__sysbench
14:24:04 0 - 2474 0.99 7.92 0.00 75.25 8.91 0 |__sysbench
14:24:04 0 - 2475 2.97 6.93 0.00 70.30 9.90 0 |__sysbench
14:24:04 0 - 2476 2.97 6.93 0.00 68.32 9.90 0 |__sysbench
...

从这个 pidstat 的输出界面,你可以发现,每个 stress 线程的 %wait 高达 70%而 CPU使用率只有不到 10%。换句话说, stress 线程大部分分时间都消耗在了等待 CPU 上,

这也表明,确实是过多的线程在争抢 CPU。

2、pidstat 中的 %wait 跟 top 中的 iowait% 没有可比性

有些同学会拿 pidstat 中的 %wait 跟 top 中的 iowait% (缩写为 wa)对比,其实这是没有意义的,因为它们是完全不相关的两个指标。

pidstat 中, %wait 表示进程等待 CPU的时间百分比
top 中 ,iowait% 则表示等待 I/O 的 CPU的时间百分比

3、不同版本的 sysbench 运行参数也不是完全一样的

1
2
3
4
5
Ubuntu 18.04
sysbench --threads=10 --max-time=300 threads run
 
Ubuntu 16.04
sysbench --num-threads=10 --max-time=300 --test=threads run

问题 4:无法模拟出 I/O 性能瓶颈,以及 I/O 压力过的问题

 

 

1、磁盘性能差异

更是因为磁盘的巨大差异。比如,机械磁盘(HDD)、低端固态磁盘(SSD)与高端固态磁盘相比,性能差异可能达到数倍到数十倍

2、磁盘前缀差异

由于我在案例中只查找了 /dev/xvd 和 /dev/sd前缀的磁盘,而没有考虑到使用其他前缀,磁盘(比如 /dev/nvme)的同学。如果你正好用的是其他
前缀,你可能会碰到跟 Vicky 类似的问题,也就是 app启动后又很快退出,变成 exited 状态。

所以,在最新的案例中,我为 app 应用增加了三个选项。

-d 设置要读取的磁盘,默认前缀为 /dev/sd 或者 /dev/xvd 的磁盘。
-s 设置每次读取的数据量大小,单位为字节,默认为67108864(也就是 64MB)。
-c 设置每个子进程读取的次数,默认为 20 次,也就是说,读取 20*64MB 数据后,子进程退出。

1
docker run --privileged --name=app -itd feisky/app:iowait /app -d /dev/sdb -s 67108864 -c 20

案例运行后,你可以执行 docker logs 查看它的日志正常情况下,你可以看到下面的输出:

1
2
docker logs app
Reading data from disk /dev/sdb with buffer size 67108864 and count 20

问题 5:性能工具(如 vmstat)输出中,第一行数据跟其他行差别巨大

1
2
3
4
5
6
7
[root@luoahong ~]# vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 7541212      0 151572    0    0   296   720   90  121  0  3 97  0  0
 0  0      0 7541212      0 151576    0    0     0     0   54  108  0  0 100  0  0
 0  0      0 7541212      0 151576    0    0     0     0   45   79  0  0 100  0  0
 0  0      0 7541212      0 151576    0    0     0     0   54   94  0  1 100  0  0

1、man vmstat

1
2
3
4
5
DESCRIPTION
vmstat reports information about processes, memory, paging, block IO, traps, disks and cpu activity.
 
The first report produced gives averages since the last reboot. Additional reports give information on a sampling period of length delay. The
process and memory reports are instantaneous in either case.

一行数据是系统启动以来的平均值其他行才是你在运行 vmstat 命令时设置的间隔时间的平均值。另外,进程和内存的报告内容都是即时数数据

 

学习是一个“从薄到厚再变薄”的过程,我们从细节知识入手开始学习,积累到一定程度,需要整理成一个体系来记忆,这其中还要不断地对这个体系进行细节修补,

有疑问、有反思才可以达到最佳的学习效果。

posted @   活的潇洒80  阅读(1360)  评论(0编辑  收藏  举报
编辑推荐:
· 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语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示