极客时间已完结课程限时免费阅读

13 | 答疑(一):无法模拟出 RES 中断的问题,怎么办?

13 | 答疑(一):无法模拟出 RES 中断的问题,怎么办?-极客时间

13 | 答疑(一):无法模拟出 RES 中断的问题,怎么办?

讲述:冯永吉

时长11:04大小10.11M

你好,我是倪朋飞。
专栏更新至今,四大基础模块之一的 CPU 性能篇,我们就已经学完了。很开心过半数同学还没有掉队,仍然在学习、积极实践操作,并且热情地留下了大量的留言。
这些留言中,我非常高兴地看到,很多同学已经做到了活学活用,用学过的案例思路,分析出了线上应用的性能瓶颈,解决了实际工作中的性能问题。 还有同学能够反复推敲思考,指出文章中某些不当或不严谨的叙述,我也十分感谢你,同时很乐意和你探讨。
此外,很多留言提出的问题也很有价值,大部分我都已经在 app 里回复,一些手机上不方便回复的或者很有价值的典型问题,我专门摘了出来,作为今天的答疑内容,集中回复。另一方面,也是为了保证所有人都能不漏掉任何一个重点。
今天是性能优化答疑的第一期。为了便于你学习理解,它们并不是严格按照文章顺序排列的。每个问题,我都附上了留言区提问的截屏。如果你需要回顾内容原文,可以扫描每个问题右下方的二维码查看。

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

这是使用 CentOS 的同学普遍碰到的问题。在文章中,我的 pidstat 输出里有一个 %wait 指标,代表进程等待 CPU 的时间百分比,这是 systat 11.5.5 版本才引入的新指标,旧版本没有这一项。而 CentOS 软件库里的 sysstat 版本刚好比这个低,所以没有这项指标。
不过,你也不用担心。前面我就强调过,工具只是查找分析的手段,指标才是我们重点分析的对象。如果你的 pidstat 里没有显示,自然还有其他手段能找到这个指标。
比如说,在讲解系统原理和性能工具时,我一般会介绍一些 proc 文件系统的知识,教你看懂 proc 文件系统提供的各项指标。之所以这么做,一方面,当然是为了让你更直观地理解系统的工作原理;另一方面,其实是想给你展示,性能工具上能看到的各项性能指标的原始数据来源。
这样,在实际生产环境中,即使你很可能需要运行老版本的操作系统,还没有权限安装新的软件包,你也可以查看 proc 文件系统,获取自己想要的指标。
但是,性能分析的学习,我还是建议你要用最新的性能工具来学。新工具有更全面的指标,让你更容易上手分析。这个绝对的优势,可以让你更直观地得到想要的数据,也不容易让你打退堂鼓。
当然,初学时,你最好试着去理解性能工具的原理,或者熟悉了使用方法后,再回过头重新学习原理。这样,即使是在无法安装新工具的环境中,你仍然可以从 proc 文件系统或者其他地方,获得同样的指标,进行有效的分析。

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

使用 stress 无法模拟 iowait 升高,但是却看到了 sys 升高。这是因为案例中 的 stress -i 参数,它表示通过系统调用 sync() 来模拟 I/O 的问题,但这种方法实际上并不可靠。
因为 sync() 的本意是刷新内存缓冲区的数据到磁盘中,以确保同步。如果缓冲区内本来就没多少数据,那读写到磁盘中的数据也就不多,也就没法产生 I/O 压力。
这一点,在使用 SSD 磁盘的环境中尤为明显,很可能你的 iowait 总是 0,却单纯因为大量的系统调用,导致了系统 CPU 使用率 sys 升高。
这种情况,我在留言中也回复过,推荐使用 stress-ng 来代替 stress。担心你没有看到留言,所以这里我再强调一遍。
你可以运行下面的命令,来模拟 iowait 的问题。
# -i的含义还是调用sync,而—hdd则表示读写临时文件
$ stress-ng -i 1 --hdd 1 --timeout 600

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

这个问题是说,即使运行了大量的线程,也无法模拟出重调度中断 RES 升高的问题。
其实我在 CPU 上下文切换的案例中已经提到,重调度中断是调度器用来分散任务到不同 CPU 的机制,也就是可以唤醒空闲状态的 CPU ,来调度新任务运行,而这通常借助处理器间中断(Inter-Processor Interrupts,IPI)来实现。
所以,这个中断在单核(只有一个逻辑 CPU)的机器上当然就没有意义了,因为压根儿就不会发生重调度的情况。
不过,正如留言所说,上下文切换的问题依然存在,所以你会看到, cs(context switch)从几百增加到十几万,同时 sysbench 线程的自愿上下文切换和非自愿上下文切换也都会大幅上升,特别是非自愿上下文切换,会上升到十几万。根据非自愿上下文的含义,我们都知道,这是过多的线程在争抢 CPU。
其实这个结论也可以从另一个角度获得。比如,你可以在 pidstat 的选项中,加入 -u 和 -t 参数,输出线程的 CPU 使用情况,你会看到下面的界面:
$ 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。
在这里顺便提一下,留言中很常见的一个错误。有些同学会拿 pidstat 中的 %wait 跟 top 中的 iowait% (缩写为 wa)对比,其实这是没有意义的,因为它们是完全不相关的两个指标。
pidstat 中, %wait 表示进程等待 CPU 的时间百分比。
top 中 ,iowait% 则表示等待 I/O 的 CPU 时间百分比。
回忆一下我们学过的进程状态,你应该记得,等待 CPU 的进程已经在 CPU 的就绪队列中,处于运行状态;而等待 I/O 的进程则处于不可中断状态。
另外,不同版本的 sysbench 运行参数也不是完全一样的。比如,在案例 Ubuntu 18.04 中,运行 sysbench 的格式为:
$ sysbench --threads=10 --max-time=300 threads run
而在 Ubuntu 16.04 中,运行格式则为(感谢 Haku 留言分享的执行命令):
$ sysbench --num-threads=10 --max-time=300 --test=threads run

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

这个问题可以看成是上一个问题的延伸,只是把 stress 命令换成了一个在容器中运行的 app 应用。
事实上,在 I/O 瓶颈案例中,除了上面这个模拟不成功的留言,还有更多留言的内容刚好相反,说的是案例 I/O 压力过大,导致自己的机器出各种问题,甚至连系统都没响应了。
之所以这样,其实还是因为每个人的机器配置不同,既包括了 CPU 和内存配置的不同,更是因为磁盘的巨大差异。比如,机械磁盘(HDD)、低端固态磁盘(SSD)与高端固态磁盘相比,性能差异可能达到数倍到数十倍。
其实,我自己所用的案例机器也只是低端的 SSD,比机械磁盘稍微好一些,但跟高端固态磁盘还是比不了的。所以,相同操作下,我的机器上刚好出现 I/O 瓶颈,但换成一台使用机械磁盘的机器,可能磁盘 I/O 就被压死了(表现为使用率长时间 100%),而换上好一些的 SSD 磁盘,可能又无法产生足够的 I/O 压力。
另外,由于我在案例中只查找了 /dev/xvd 和 /dev/sd 前缀的磁盘,而没有考虑到使用其他前缀磁盘(比如 /dev/nvme)的同学。如果你正好用的是其他前缀,你可能会碰到跟 Vicky 类似的问题,也就是 app 启动后又很快退出,变成 exited 状态。
在这里,berryfl 同学提供了一个不错的建议:可以在案例中增加一个参数指定块设备,这样有需要的同学就不用自己编译和打包案例应用了。
所以,在最新的案例中,我为 app 应用增加了三个选项。
-d 设置要读取的磁盘,默认前缀为 /dev/sd 或者 /dev/xvd 的磁盘。
-s 设置每次读取的数据量大小,单位为字节,默认为 67108864(也就是 64MB)。
-c 设置每个子进程读取的次数,默认为 20 次,也就是说,读取 20*64MB 数据后,子进程退出。
你可以点击 Github 查看它的源码,使用方法我写在了这里:
$ docker run --privileged --name=app -itd feisky/app:iowait /app -d /dev/sdb -s 67108864 -c 20
案例运行后,你可以执行 docker logs 查看它的日志。正常情况下,你可以看到下面的输出:
$ docker logs app
Reading data from disk /dev/sdb with buffer size 67108864 and count 20

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

这个问题主要是说,在执行 vmstat 时,第一行数据跟其他行相比较,数值相差特别大。我相信不少同学都注意到了这个现象,这里我简单解释一下。
首先还是要记住,我总强调的那句话,在碰到直观上解释不了的现象时,要第一时间去查命令手册
比如,运行 man vmstat 命令,你可以在手册中发现下面这句话:
The first report produced gives averages since the last reboot. Additional reports give information on a sam‐
pling period of length delay. The process and memory reports are instantaneous in either case.
也就是说,第一行数据是系统启动以来的平均值,其他行才是你在运行 vmstat 命令时,设置的间隔时间的平均值。另外,进程和内存的报告内容都是即时数值。
你看,这并不是什么不得了的事故,但如果我们不清楚这一点,很可能卡住我们的思维,阻止我们进一步的分析。这里我也不得不提一下,文档的重要作用。
授之以鱼,不如授之以渔。我们专栏的学习核心,一定是教会你性能分析的原理和思路,性能工具只是我们的路径和手段。所以,在提到各种性能工具时,我并没有详细解释每个工具的各种命令行选项的作用,一方面是因为你很容易通过文档查到这些,另一方面就是不同版本、不同系统中,个别选项的含义可能并不相同。
所以,不管因为哪个因素,自己 man 一下,一定是最快速并且最准确的方式。特别是,当你发现某些工具的输出不符合常识时,一定记住,第一时间查文档弄明白。实在读不懂文档的话,再上网去搜,或者在专栏里向我提问。
学习是一个“从薄到厚再变薄”的过程,我们从细节知识入手开始学习,积累到一定程度,需要整理成一个体系来记忆,这其中还要不断地对这个体系进行细节修补。有疑问、有反思才可以达到最佳的学习效果。
最后,欢迎继续在留言区写下你的疑问,我会持续不断地解答。我的目的仍然不变,希望可以和你一起,把文章的知识变成你的能力,我们不仅仅在实战中演练,也要在交流中进步。
分享给需要的人,Ta购买本课程,你将得20
生成海报并分享

赞 43

提建议

上一篇
12 | 套路篇:CPU 性能优化的几个思路
下一篇
14 | 答疑(二):如何用perf工具分析Java程序?
unpreview
 写留言

精选留言(50)

  • ninuxer
    2018-12-19
    打卡day14 之前一直理解有误,感谢指出! pidstat 中, %wait 表示进程等待 CPU 的时间百分比。此时进程是运行状态。 top 中 ,iowait% 则表示等待 I/O 的 CPU 时间百分比。此时进程处于不可中断睡眠态。 等待 CPU 的进程已经在 CPU 的就绪队列中,处于运行状态;而等待 I/O 的进程则处于不可中断状态。
    展开

    作者回复: 👍

    共 4 条评论
    42
  • 念你如昔
    2018-12-19
    非常非常感谢,这钱花的值,之前没有对这些东西形成体系,老是感觉有力使不上的感觉,自从看了老师的文档,终于飘了,都想跳槽了?!。

    作者回复: 😢

    17
  • 郭江伟
    2018-12-19
    课程很系统,把自己以前的知识都串起来了,后续争取每个案例自己都做一次,并且融合自己的经验改进下案例

    作者回复: 欢迎分享你的改进经验😊

    8
  • 微思
    2018-12-19
    老师,等待IO的不可中断进程是否一直占用CPU?

    作者回复: 不会,有其他需要CPU的进程运行时会切换过去

    7
  • MoFanDon
    2018-12-19
    做了几年运维一直想要掌握,却了解的很零散。这段时间的课程让我学习很多,感谢老师。

    作者回复: 😊

    4
  • MJ
    2019-03-28
    虽然有很多地方不太懂(不熟Linux原理),但还是要跟下来,多过几遍。 同时,私下学Linux原理
    2
  • 我来也
    2018-12-19
    [D13打卡] 多谢老师提出来, pidstat 和 top 中的 %wait 含义并不一样. 之前只知道top是io的wait, 而新接触的pidstat的倒没有细想过. 确实是应该多man一下,看下命令文档. 刚开始要把工具用起来, 之后再查看命令的详细文档.

    作者回复: 嗯嗯,虽然专栏里也有不少使用案例,但并能包括所有细节的知识,这都需要查文档

    2
  • 饭粒
    2019-08-27
    测试跑的Q4 还是无法模拟出 I/O 性能瓶颈,依然是要加了 --device-write-iops --device-read-iops 限制后才可以。 [root@centos-7 ~]# docker run --privileged --name=app -itd feisky/app:iowait /app -d /dev/sda -s 67108864 -c 20 e7a7deddba3d2845030515fbbe25785382306d3c600c474a22de54d543a2cf53 [root@centos-7 ~]# docker logs app Reading data from disk /dev/sdb with buffer size 67108864 and count 20 # 内核cpu时间sy,软中断cpu时间si升高明显 top - 00:15:15 up 12 min, 2 users, load average: 23.50, 7.07, 2.49 Tasks: 148 total, 43 running, 104 sleeping, 1 stopped, 0 zombie %Cpu0 : 21.1 us, 54.9 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 24.0 si, 0.0 st %Cpu1 : 21.8 us, 76.8 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 1.4 si, 0.0 st KiB Mem : 3880792 total, 737592 free, 2880084 used, 263116 buff/cache KiB Swap: 0 total, 0 free, 0 used. 764308 avail Mem # docker run --privileged --name=app -itd --device-write-iops /dev/sda:3 --device-read-iops /dev/sda:3 feisky/app:iowait /app -d /dev/sda -s 67108864 -c
    展开
    1
  • 大哈
    2019-07-10
    老师,您好,我想知道像pidstat这样的工具是怎么获取到这些性能数据的,我自己去开发应该从那里获取呢?

    作者回复: man 查询工具手册,一般都有介绍。一般数据都是来自 /proc、/sys 等

    1
  • 胡莉婷
    2019-01-08
    补充一点。我们的进程都是后台服务,机器1和机器2启动后都没有业务进来

    作者回复: 嗯 我的第一反应是负载不均匀,后台处理的业务是均匀的吗?

    共 2 条评论
    1
  • Only now
    2018-12-27
    mark
    1
  • 灬 黑 礼服 ~
    2018-12-24
    老师 。。我们这边系统多数都是java 语言开发的。。。也有些系统经常出现cpu暴涨的时候。。。都是根据网上 jstack那种工具 去分析。。。对于java而言?? 有没有更好的 查找cpu暴涨的时候的信息? 具体什么原因引起的 ? 同时 ,根据jdk自带的检查工具 jstack之类的 都是瞬时的。。。有没有 连续监控排查的 工具??有效的查找 java语言 开发的系统引起的cpu暴涨????
    共 3 条评论
    1
  • nuan
    2022-11-18 来自北京
    期待老师出个新版教程!
  • Geek_f93234
    2022-08-03 来自北京
    day13 授之以鱼,不如授之以渔
  • DayDayUp
    2022-05-28
    老师,一个机器有很多D state的进程,然后导致机器很慢,有时间讲一下关于“D进程太多的相关诊断”章节吗?
  • ch_ort
    2021-09-12
    “pidstat 中, %wait 表示进程等待 CPU 的时间百分比。 top 中 ,iowait% 则表示等待 I/O 的 CPU 时间百分比。 ” 问题来了,现在通过top和mpstat发现是iowati高导致的,怎么通过pidstat找到iowait高的进程呢?
    共 2 条评论
  • 生活不如诗
    2020-07-01
    一直以来理解错误的几个误区: 1.pidstat 中, %wait 表示进程等待 CPU 的时间百分比。 2.top 中 ,iowait% 则表示等待 I/O 的 CPU 时间百分比。 3.vmstat命令中第一行数据是系统启动以来的平均值,其他行才是你在运行 vmstat 命令时,设置的间隔时间的平均值。另外,进程和内存的报告内容都是即时数值 4.还是得学会通过man命令查看手册帮助;
    展开
  • Yong
    2020-05-17
    虚拟机装的centos7系统,只有2个cpu,大部分命令cpu个数都正常,但cat /proc/softirqs 显示出来的cpu有120个,有同学知道我什么么. 搜到的一篇相关的文章proc-softirqs-the-number-of-columns-doesnt-match-the-number-of-cpu-cores 但页面已经不在了
    共 1 条评论
  • Damoncui
    2020-05-15
    有一个问题 现在系统核心太多。比如256逻辑线程这种级别 通过 /proc查看中断特别不方便。能不能指定核心啊?
    共 2 条评论
  • 斑马Z
    2020-03-27
    孜孜不倦,加油!