查看系统cpu个数:
(1)grep 'model name' /proc/cpuinfo|wc -l
(2)grep 'core id' /proc/cpuinfo|wc -l
性能工具的安装:
(1)centos:yum install -y stress sysstat
(2)ubuntu:apt install stress sysstat
实战
情景一:CPU密集型进程
(1)压测cpu:stress --cpu 1 --timeout 600
(2)查看系统平均负载的变化:watch -d uptime
(-d 表示高亮显示变化的区域)
(3)查看系统cpu使用率的变化情况:mpstat -P ALL 5
(-P ALL 表示监控所有的cpu,后面的数字5表示间隔5秒输出一组数据)动态的输出
(4)查看系统进程使用cpu情况:pidstat -u 5 2
(-u表示每隔5秒输出一组数据,总共输出两次,并打印出平均数值)
情景二:I/O密集型进程
-
压测IO:
stress --io 1 --timeout 600
- 过程如情景一
情景三:大量进程的场景
-
模拟8个进程:
stress --cpu 8 --timeout 600
- 过程如情景一
情景四:查看系统上下文切换情况
- 查看上下文切换:
vmstat 5
(每隔5秒输出1组数据)
(1)cs(context switch)
就是每秒上下文切换的次数
(2)in(interrupt)
每秒中断的次数
(3)r(running or runnable)
表示就绪队列的长度,也就是正在运行和等待CPU的进程数
(4)b(blocked)
表示处于不可中断睡眠状态的进程数
- 查看详细上下文切换的情况:
pidstat -w 5
(每隔5秒输出1组数据,动态的)
(1)cswch
表示每秒自愿上下文切换(voluntary context switches)的次数
(2)nvcswch
表示每秒非自愿上下文切换(non voluntary context switches)的次数
- 上下文切换概念:
(1)自愿上下文切换:指进程无法获取所需资源,导致的上下文切换。比如,I/O,内存等系统资源不足时;
(2)非自愿上下文切换:指进程由于时间片已到等原因,被系统强制调度,进而发生的上下文切换。比如,大量进程都在争抢CPU时;
- 模拟多线程调度:
(1)centos:yum install -y sysbench
(2)ubuntu:apt install sysbench
- 测试:
(1)以10个线程运行5分钟的基准测试,模拟系统多线程切换的问题:sysbench --threads=10 --max-time=300 threads run
(2)观察上下文切换情况:vmstat 1
(3)查看cpu和上下文切换的进程和线程情况:pidstat -w -u 1
系统的就绪队列过长,也就是正在运行和等待cpu的进程数过多,导致大量的上下文切换,而上下文切换又导致了系统cpu的占用率升高。
(4)上图中pidstat 默认显示进程的指标数据,加上-t
参数后,才会输出线程的指标。
(5)查找源头,注意中断次数,是什么类型的中断上升呢:watch -d cat /proc/interrupts
会发现是RES(重调度中断),这个中断类型表示,唤醒空闲状态的CPU来调度新的任务运行。
情景五:查看CPU使用率
- 使用工具top和ps:
(1)top:显示系统总体的CPU和内存使用情况,以及各个进程的资源使用情况,默认每隔3秒刷新一次
空白行之后是进程的实时信息,每个进程都有一个%CPU列,表示进程的CPU使用率。
它是用户态和内核态CPU使用率总和,包括进程用户空间使用的CPU、通过系统调用执行的内核空间CPU、以及在就绪队列等待运行的CPU。在虚拟化环境中,它还包括了运行虚拟机占用的CPU。
Top并没有细分进程的用户态CPU和内核态CPU,那么怎么查看每个进程的详细情况呢:pidstat 1 5
(每隔1秒输出一组数据,共输出5组 )
(2)ps:只显示每个进程的资源使用情况
- CPU过高排查工具:想知道占用CPU的到底是代码里的哪个函数,找到它,才能更高效、更针对性地进行优化。
(1)GDB(the GNU Project Debugger)
功能强大的程序调试利器,但不适合在性能分析的早期应用,因为GDB调试程序过程会中断程序运行,这在线上环境往往是不允许的。
(2)perf(Linux2.6.31以后内置的性能分析工具)
,它以性能事件采样为基础,不仅可以分析系统的各种事件和内核性能,还可以用来分析指定应用程序的性能问题。如系统没有,请安装:yum install -y perf
- perf两种常见用法:
(1)perf top类似于top,它能够实时显示占用CPU时钟最多的函数或指令,因此可以用来查找热点函数,如下:
第一行包含三个数据,分别是:采样数(Samples)、事件类型(event)和事件总数量(Event count)
另外注意:如果采样数过少(比如直有十几个),那下面的排序和百分比就没有什么实际参考价值了。
再往下看是一个表格式样的数据,每一行包含四列,分别是:
第一列Overhead
,是该符号的性能事件在所有采样中的比例,用百分比来表示。
第二列Shared
,是该函数或指令所在的动态共享对象(Dynamic Shared Object),如内核、进程名、动态链接库名、内核模块名等。
第三列Object
,是动态共享对象的类型。比如[.]表示用户空间的可执行程序、或者动态链接库,而[k]则表示内核空间。
第四列Symbol
是符号名,也就是函数名。当函数名未知时,用十六进制的地址来表示。
(2)perf record和perf report
perf top
虽然实时展示了系统的性能信息,但它缺点是不能保存数据,也就是无法用于离线或者后续的分析。
perf record
则提供了保存数据的功能,保存后的数据,需要用perf report解析展示。
实际工作中,我们还经常为perf top和perf record加上-g
参数,开启调用关系的采样,方便我们根据调用链来分析性能问题。
比如:perf top -g -p 21515
(-g开启调用关系分析,-p指定服务的进程号是21515)
- HTTP服务性能测试工具:
ab(apache bench)
比如:ab -c 10 -n 1000 http://192.168.246.191:80/
(并发10个请求,总共测试1000个请求)
情景六:系统的CPU使用率很高,但是找不到高CPU的应用
pidstat -p 24344
(指定PID是24344的进程)
Pstree
用树状形式显示所有进程之间的关系
grep stress -r app/
(-r
目录递归)
execsnoop
:一个专门为段时进程设计的工具。它通过ftrace实时监控进程的exec()行为,并输出短时进程的基本信息,包括进程的PID、父进程PID、命令行参数以及执行的结果。
- 常规无法解释的CPU使用率情况,有可能是下面这两种情况:
(1)应用里直接调用了其他二进制程序,这些程序通常运行时间比较短,通过top等工具不容易发现;
(2)应用本身在不停地奔溃重启,而启动过程的资源初始化,很可能会占用相当多的CPU;
对于这类进程,我们可以用pstree或者execsnoop找到它们的父进程,再从父进程所在的应用入手,排查问题的根源。
注意⚠️:当碰到无法解释的CPU使用率问题时,先要检查下是不是短时应用在捣鬼!
情景七:系统中出现大量不可中断进程和僵尸进程怎么办(上)
- 进程常见的五种状态:
(1)R
是 Running 或 Runnable 的缩写,表示进程在 CPU 的就绪队列中,正在运行或者正在等待运行。
(2)D
是 Disk Sleep 的缩写,也就是不可中断状态睡眠(Uninterruptible Sleep),一般表示进程正在跟硬件交互,并且交互过程不允许被其他进程或中断打断。
注意⚠️:进程长时间处于不可中断状态,通常表示系统有 I/O 性能问题。
(3)Z
是 Zombie 的缩写,如果你玩过“植物大战僵尸”这款游戏,应该知道它的意思。它表示僵尸进程,也就是进程实际上已经结束了,但是父进程还没有回收它的资源(比如进程的描述符、PID 等)。
(4)S
是 Interruptible Sleep 的缩写,也就是可中断状态睡眠,表示进程因为等待某个事件而被系统挂起。当进程等待的事件发生时,它会被唤醒并进入 R 状态。
(5)I
是 Idle 的缩写,也就是空闲状态,用在不可中断睡眠的内核线程上。前面说了,硬件交互导致的不可中断进程用 D 表示,但对某些内核线程来说,它们有可能实际上并没有任何负载,用 Idle 正是为了区分这种情况。要注意,D 状态的进程会导致平均负载升高,I 状态的进程却不会。
- 进程不常见的两种状态:
(1)T 或者 t
,也就是 Stopped 或 Traced 的缩写,表示进程处于暂停或者跟踪状态。
向一个进程发送 SIGSTOP 信号,它就会因响应这个信号变成暂停状态(Stopped);再向它发送 SIGCONT 信号,进程又会恢复运行(如果进程是终端里直接启动的,则需要你用 fg 命令,恢复到前台运行)。
而当你用调试器(如 gdb)调试一个进程时,在使用断点中断进程后,进程就会变成跟踪状态,这其实也是一种特殊的暂停状态,只不过你可以用调试器来跟踪并按需要控制进程的运行。
(2)X
,也就是 Dead 的缩写,表示进程已经消亡,所以你不会在top 或者 ps 命令中看到它。
注意⚠️:Ss+
:S表示可中断睡眠状态,s表示这个进程是一个会话的领导进程,而+表示前台进程组。
- 进程组与会话:
它们是管理一组相互关联的进程,意思如下:
(1)进程组表示一组相互关联的进程,比如每个子进程都是父进程所在组的成员;
(2)会话是指共享同一个控制端的一个或多个进程组;
比如,我们通过 SSH 登录服务器,就会打开一个控制终端(TTY),这个控制终端就对应一个会话。而我们在终端中运行的命令以及它们的子进程,就构成了一个个的进程组,,其中,在后台运行的命令,构成后台进程组;在前台运行的命令,构成前台进程组。
- 安装dstat
(1)CentOS:yum install -y dstat
(2)Ubuntu:apt install dstat
这里dstat是一个新的性能工具,它吸收了vmstat、iostat、ifstat等几种工具的优点,可以同时观察系统的CPU、磁盘I/O、网络以及内存使用情况。
情景八:系统中出现大量不可中断进程和僵尸进程怎么办(下)
- 工具使用:
(1)dstat 1 10
(间隔1秒输出10组数据)
(2)pidstat -d -p 4344 1 3
(-d 展示 I/O 统计数据,-p 指定进程号,间隔 1 秒输出 3 组数据)
(3)strace -p 6082
(-p指定进程号)
Strace最常用的跟踪进程系统调用的工具。
(4)perf record -g
(终端运行十五分钟左右,再ctrl+c)
(5)perf report
- 僵尸进程的处理
要解决僵尸进程,就要找到它的根儿,也就是找出父进程,然后在父进程里解决。
(1)pstree -aps 3084
(-a表示输出命令行选项,p表示PID,s表示指定进程的父进程)
运行完,你会发现 3084 号进程的父进程是 4009,也就是 app 应用。
(2)接着查看 app 应用程序的代码,看看子进程结束的处理是否正确,比如有没有调用wait() 或 waitpid() ,抑或是,有没有注册 SIGCHLD 信号的处理函数。