性能调优是找出系统瓶颈并消除这些瓶颈的过程。 很多系统管理员认为性能调优仅仅是调整一下内核的参数即可解决问题, 事实上情况并不是这样。 性能调优是实现操作系统的各个子系统之间的平衡性,这些子系统包括:
子系统之间相互依存,任何一个子系统的负载过度都能导致其他子系统出现问题,例如:
性能调优的前提是找出系统瓶颈之所在, 尽管问题看似由某个子系统所导致, 然而这很可能是另外一个子系统的过载所引起的。
为了明白从何处开始着手调整性能瓶颈, 弄清被分析系统的性能表现是首要任务。 任何系统的应用常可分为以下两类:
我们在进行压测时,可以用来判断系统好坏的一个标准,可以参考如下表格的一个标准:
影响性能因素 |
评判标准 |
||
好 |
坏 |
糟糕 |
|
CPU |
user% + sys%< 70% |
user% + sys%= 85% |
user% + sys% >=90% |
内存 |
Swap In(si)=0 |
Per CPU with 10 page/s |
More Swap In & Swap Out |
磁盘 |
iowait % < 20% |
iowait % =35% |
iowait % >= 50% |
其中:
%user:表示CPU处在用户模式下的时间百分比。
%sys:表示CPU处在系统模式下的时间百分比。
%iowait:表示CPU等待输入输出完成时间的百分比。
swap in:即si,表示虚拟内存的页导入,即从SWAP DISK交换到RAM。
swap out:即so,表示虚拟内存的页导出,即从RAM交换到SWAP DISK。
平均负载:是指单位时间内,系统处于可运行状态和不可中中断状态的平均进程数,也就是平均活跃进程数,它和 CPU 使用率没有直接关系。
这里需要注意的是:load average这个输出值,这三个值的大小一般不能大于系统CPU的个数。例如,本输出中系统有16个CPU,如果load
average的三个值长期大于16时,说明CPU很繁忙,负载很高,可能会影响系统性能,但是偶尔大于16时,倒不用担心,一般不会影响系统性能。相反,如果load
average的输出值小于CPU的个数,则表示CPU还有空闲的时间片,比如本例中的输出,CPU是非常空闲的。
也可以通过查询文件/proc/loadavg获取系统在前一分钟、前五分钟和前十五分钟的平均负载以及当前运行的进程、系统的进程数和上一次调度运行的进程。
(2)top
平均负载是指单位时间内,处于可运行状态和不可中断状态的进程数。它不仅包括了正在使用CPU的进程,还包括等待CPU和等待I/O的进程。
CPU使用率,是单位时间内CPU繁忙情况的统计,跟平均负载并不一定完全对应。
CPU 密集型进程,使用大量 CPU 会导致平均负载升高,此时这两者时一致的。
I/O 密集型进程,等待 I/O 也会导致平均负载升高,但CPU使用率不一定很高。
大量等待 CPU 的进程调度也会导致平均负载升高,此时的CPU使用率也会比价高。
上下文切换:CPU切换到另一个进程需要保存当前进程的状态并恢复另一个进程的状态:当前运行任务转为就绪(或者挂起、中断)状态,另一个被选定的就绪任务成为当前任务。进程调度包括保存当前任务的运行环境,恢复将要运行任务的运行环境。
1.vmstat使用
vmstat是一个常用的系统性能分析工具,主要用来分析系统的内存使用情况,也常来分析CPU上下文切换和中断的次数。
#每隔 5 秒输出 1 组数据
以上vmstat只给出了系统总体的上下文切换的情况,使用pidstat,并加上-w,可以查看每个进程上下文切换的情况;
例如:
这里有我们需要重点关注的对象,就是cswch(每秒自愿上下文切换)的次数,nvcswch(每秒非自愿上下文切换)的次数。它们意味着不同的性能问题:
所谓自愿上下文切换,是指进程无法获取所需资源,导致的上下文切换。比如说,I/O,内存等系统资源不足时,就会发生自愿上下文切换。
而非而非自愿上下文切换,则是指进程由于时间片已到等原因,被系统强制调度,进而发生的上下文切换。比如说,大量进程都在争抢CPU时,就容易发生非自愿上下文切换。
使用top命令查看:
一旦父进程没有处理子进程的终止,还一直保持运行状态,那么子进程就会一直处于僵尸状态。大量的僵尸进程会用尽 PID 进程号,导致新进程不能创建,所以这种情况一定要避免。
使用命令top
(1)第一种常见用法是 perf top
类似于 top,它能够实时显示占用 CPU 时钟最多的函数或者指令,因此可以用来查找热点函数,使用界面如下所示:
(2)第二种常见用法,也就是 perf record 和 perf report
perf record 则提供了保存数据的功能,保存后的数据需要你用 perf report 解析展示.
如下:
$ perf record -p -g 进程pid # 按 Ctrl+C 终止采样,加上g参数可以显示函数的调用关系
$ perf report # 展示类似于 perf top 的报告,报告展示如下:
总结:
中断是系统用来响应硬件设备请求的一种机制,它会打断进程的正常调度和执行,然后调用内核中的中断处理程序来响应设备的请求。
中断的作用:
比如说你订了一份外卖,但是不确定外卖什么时候送到,也没有别的方法了解外卖的进度,但是,配送员送外卖是不等人的,到了你这儿没人取的话,就直接走人了。所以你只能苦苦等着,时不时去门口看看外卖送到没,而不能干其他事情。
不过呢,如果在订外卖的时候,你就跟配送员约定好,让他送到后给你打个电话,那你就不用苦苦等待了,就可以去忙别的事情,直到电话一响,接电话、取外卖就可以了。
这里的“打电话”,其实就是一个中断。没接到电话的时候,你可以做其他的事情;只有接到了电话(也就是发生中断),你才要进行另一个动作:取外卖。
这个例子你就可以发现,中断其实是一种异步的事件处理机制,可以提高系统的并发处理能力.
由于中断处理程序会打断其他进程的运行,所以,为了减少对正常进程运行调度的影响,中断处理程序就需要尽可能快地运行。如果中断本身要做的事情不多,那么处理起来也不会有太大问题;但如果中断要处理的事情很多,中断服务程序就有可能要运行很长时间。
特别是,中断处理程序在响应中断时,还会临时关闭中断。这就会导致上一次中断处理完成之前,其他中断都不能响应,也就是说中断有可能会丢失。
那么还是以取外卖为例。假如你订了 2 份外卖,一份主食和一份饮料,并且是由 2 个不同的配送员来配送。这次你不用时时等待着,两份外卖都约定了电话取外卖的方式。但是,问题又来了。
当第一份外卖送到时,配送员给你打了个长长的电话,商量发票的处理方式。与此同时,第二个配送员也到了,也想给你打电话。
但是很明显,因为电话占线(也就是关闭了中断响应),第二个配送员的电话是打不通的。所以,第二个配送员很可能试几次后就走掉了(也就是丢失了一次中断)。
如果你弄清楚了“取外卖”的模式,那对系统的中断机制就很容易理解了。事实上,为了解决中断处理程序执行过长和中断丢失的问题,Linux 将中断处理过程分成了两个阶段,也就是上半部和下半部:
这样,第一个配送员不会占用你太多时间,当第二个配送员过来时,照样能正常打通你的电话。
除了取外卖,我再举个最常见的网卡接收数据包的例子,让你更好地理解。
网卡接收到数据包后,会通过硬件中断的方式,通知内核有新的数据到了。这时,内核就应该调用中断处理程序来响应它。你可以自己先想一下,这种情况下的上半部和下半部分别负责什么工作呢?
对上半部来说,既然是快速处理,其实就是要把网卡的数据读到内存中,然后更新一下硬件寄存器的状态(表示数据已经读好了),最后再发送一个软中断信号,通知下半部做进一步的处理。
而下半部被软中断信号唤醒后,需要从内存中找到网络数据,再按照网络协议栈,对数据进行逐层解析和处理,直到把它送给应用程序。
所以,这两个阶段你也可以这样理解:
实际上,上半部会打断 CPU 正在执行的任务,然后立即执行中断处理程序。而下半部以内核线程的方式执行,并且每个 CPU 都对应一个软中断内核线程,名字为 “ksoftirqd/CPU 编号”,比如说, 0 号 CPU 对应的软中断内核线程的名字就是 ksoftirqd/0。
不过要注意的是,软中断不只包括了刚刚所讲的硬件设备中断处理程序的下半部,一些内核自定义的事件也属于软中断,比如内核调度和 RCU 锁(Read-Copy Update 的缩写,RCU 是 Linux 内核中最常用的锁之一)等。
前面提到过的 proc 文件系统。它是一种内核空间和用户空间进行通信的机制,可以用来查看内核的数据结构,或者用来动态修改内核的配置。其中:
运行下面的命令,查看 /proc/softirqs 文件的内容,你就可以看到各种类型软中断在不同 CPU 上的累积运行次数:
$ cat /proc/softirqs CPU0 CPU1 HI: 0 0 TIMER: 811613 1972736 NET_TX: 49 7 NET_RX: 1136736 1506885 BLOCK: 0 0 IRQ_POLL: 0 0 TASKLET: 304787 3691 SCHED: 689718 1897539 HRTIMER: 0 0 RCU: 1330771 1354737 |
在查看 /proc/softirqs 文件内容时,你要特别注意以下这两点。
第一,要注意软中断的类型,也就是这个界面中第一列的内容。从第一列你可以看到,软中断包括了 10 个类别,分别对应不同的工作类型。比如 NET_RX 表示网络接收中断,而 NET_TX 表示网络发送中断。
第二,要注意同一种软中断在不同 CPU 上的分布情况,也就是同一行的内容。正常情况下,同一种中断在不同 CPU 上的累积次数应该差不多。比如这个界面中,NET_RX 在 CPU0 和 CPU1 上的中断次数基本是同一个数量级,相差不大。
不过你可能发现,TASKLET 在不同 CPU 上的分布并不均匀。TASKLET 是最常用的软中断实现机制,每个 TASKLET 只运行一次就会结束 ,并且只在调用它的函数所在的 CPU 上运行。
因此,使用 TASKLET 特别简便,当然也会存在一些问题,比如说由于只在一个 CPU 上运行导致的调度不均衡,再比如因为不能在多个 CPU 上并行运行带来了性能限制。
另外,软中断实际上是以内核线程的方式运行的,每个 CPU 都对应一个软中断内核线程,这个软中断内核线程就叫做 ksoftirqd/CPU 编号。那要怎么查看这些线程的运行状况呢?
其实用 ps 命令就可以做到,比如执行下面的指令:
$ ps aux | grep softirq root 7 0.0 0.0 0 0 ? S Oct10 0 : 01 [ksoftirqd/ 0 ] root 16 0.0 0.0 0 0 ? S Oct10 0 : 01 [ksoftirqd/ 1 ] |
注意,这些线程的名字外面都有中括号,这说明 ps 无法获取它们的命令行参数(cmline)。一般来说,ps 的输出中,名字括在中括号里的,一般都是内核线程。
小结:
Linux 中的中断处理程序分为上半部和下半部:
(1)使用top查看各个CPU的使用情况,如果找不到CPU使用高的应用;
(2)继续使用pidstat可以查看每个进程的CPU使用情况;
(3)使用pidstat还是找不到CPU使用高的进程,可以再次观察top 里面的信息,查看有几个正在running的进程,如果running的进程数不符合的情况下,再次使用pidstat -p 进程号 查看每个正在running的进行的CPU使用情况;
(4)如果根据第三步找不到running进程的CPU使用情况,可以交叉使用其他的工具查看一下:ps
aux | grep
24344,如果还是查看不到CPU的使用情况,那么要查看一下这个进程是不是没有了。如果查看到该进程还有,但是pid在改变,用 pstree
就可以用树状形式显示所有进程之间的关系:pstree | grep 进程的名字 。还可以用perf record -g 观察一会儿,然后用perf report 来试着查找具体导致性能问题的函数;
(5)execsnoop 就是一个专为短时进程设计的工具,用 execsnoop 监控上述案例,就可以直接得到 stress 进程的父进程 PID 以及它的命令行参数,并可以发现大量的 stress 进程在不停启动。
(1)使用perf top ,可以实时查看占用CPU最多的进程和函数;
(2)使用perf record -g 和perf report 查看分析性能问题;
使用top 查看进行的状态,D状态为不可中断进程,可能会导致I/O升高,会导致负载升高。Z状态为僵尸进行,进行结束没有被父进程回收。
iowait分析:使用dstat 1 10 ,观察CPU和I/O的使用情况;
(1)从top命令中找到D状态的进程pid,然后使用:pidstat -d -p pid 1 3 查看I/O读写情况
(2)如果没有发现异常情况,继续使用pidstat 去掉进程号,pidstat -d 1 20 来观察所有进程的I/O使用情况,找到具体导致I/O问题的进程;
(3)找到I/O问题的进程之后,使用strace -p pid 进行跟踪进程系统调用;如果没有跟踪到,看一下进程是否变成了Z状态的僵尸进程;
(4)进一步使用perf record -g ,等待一会儿之后,使用perf report 定位到我们发现的僵尸进程,按回车键展开调用栈,找到导致I/O的函数;
僵尸进程分析:先找到僵尸进程的父进程,然后在父进程里解决。
(1)使用命令:pstree -aps pid 找到父进程,查看父进程的代码;
(1)使用top查看CPU的使用情况,如果各个情况都不高,看不出什么问题,查看软中断是不是使用了主要cpu;
(2) 使用watch -d cat /proc/softirqs 查看文件内容的变化情况,查看NET_RX,也就是网络数据包接收软中断的变化速率最快。就从网络接收的软中断着手;
(3)使用sar -n DEV 1 查看网络收发情况;
(4)然后分析网络帧;
CPU密集型:
(1)使用uptime 查看平均负载;
(2)使用mpstat 查看CPU使用率的变化情况;
(3)使用pidstat -u 5 1 可以找到CPU使用高的进程;
I/O密集型:
(1)watch -d uptime 查看平均负载的变化情况;
(2)mpstat -p ALL 5 1 查看CPU使用率变化情况,查看iowait 变化是否高;
(3)使用pidstat -u 5 1 查看到底是哪个进程导致iowait升高;
大量进程场景:
(1)uptime 查看平均负载;
(2)pidstat -u 5 1查看进程情况;
(3)查看是否是大量超出CPU进程在运行导致CPU过载;
(1)vmstat 常用来分析CPU上下文切换和中断次数;
(2)pidstat -w 5 可以查看每个进程上下文切换的情况;
(3)pidstat -wt 1 表示输出线程上下文切换的指标
(4)watch -d cat /proc/interrupts 观察中断变化情况;
这张图里,列出了 top、vmstat 和 pidstat分别提供的重要的 CPU 指标,并用虚线表示关联关系,对应出了性能分析下一步的方向。
通过这张图你可以发现,这三个命令,几乎包含了所有重要的 CPU 性能指标,比如:
另外,这三个工具输出的很多指标是相互关联的,用虚线表示了它们的关联关系,举几个例子你可能会更容易理解。
第一个例子,pidstat 输出的进程用户 CPU 使用率升高,会导致 top 输出的用户 CPU 使用率升高。所以,当发现 top 输出的用户 CPU 使用率有问题时,可以跟 pidstat 的输出做对比,观察是否是某个进程导致的问题。
而找出导致性能问题的进程后,就要用进程分析工具来分析进程的行程的行为,比如使用 strace 分析系统调用情况,以及使用perf 分析调用链中各级函数的执行情况。
第二个例子,top 输出的平均负载升高,可以跟 vmstat输出的运行状态和不可中断状态的进程数做对比,观察是哪种进程导致的负载升高。
当发现 top 输出的软中断 CPU 使用率升高时,可以查看 /proc/softirqs 文件中各种类型软中断的变化情况,确定到底是哪种软中断出的问题。比如,发现是网络接收中断导致的问题,那就可以继续用网络分析工具 sar 和 tcpdump 来分析。
原文:https://www.cnblogs.com/summerxye/p/11114368.html