linux系统性能分析
1 top
top命令提供如下参数:
top [-] [d delay] [p pid] [q] [c] [C] [S] [s] [i] [n iter] [b]
选项名称 | 说明 |
---|---|
d delay | 指定每两次屏幕信息刷新之间的时间间隔(delay 即为具体的间隔时间数值,它的单位是秒),可以使用 s交互命令来改变之。 |
p pid | 通过指定监控进程 ID(pid)来仅仅监控某个进程的状态。 |
q | 该选项将使 top 没有任何延迟的进行刷新。如果调用程序有超级用户权限,那么 top 将以尽可能高的优先级运行。 |
c | 显示整个命令行而不只是显示命令名。 |
C | 显示 CPU 总体信息而取代分别显示每个 CPU 的信息,此参数仅对SMP 系统有效。 |
S | 指定累计模式。 |
s | 使 top 命令在安全模式中运行。这将去除交互命令所带来的潜在危险。 |
i | 使 top 不显示任何闲置或者僵死进程。 |
n | iter 指定 top命令迭代输出的次数,iter为具体的迭代次数值。 |
b | Batch方式运行top,在这种方式下,所有来自终端的输入都将被忽略(当然除了ctrl+c),该参数可以结合参数“n"运行指定迭代次数退出或者该进程被杀死。这是运行top输出到哑终端或输到非终端的默认运行方式 |
在控制台输入“top”,回车如下:
top - 14:45:50 up 18 days, 21:06, 1 user, load average: 0.08, 0.06, 0.05
Tasks: 304 total, 1 running, 303 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.3 us, 0.1 sy, 0.0 ni, 99.5 id, 0.1 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 7881536 total, 236032 free, 3669556 used, 3975948 buff/cache
KiB Swap: 8126460 total, 7967484 free, 158976 used. 3866096 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
325 root 20 0 52376 1500 1220 S 1.7 0.0 508:14.59 plymouthd
4043 jenkins 20 0 8073624 2.4g 18604 S 0.7 32.4 189:18.28 java
6048 root 20 0 162260 2504 1596 R 0.7 0.0 0:00.04 top
1968 mysql 20 0 2944832 192364 5064 S 0.3 2.4 167:49.64 mysqld
2958 root 20 0 168632 4720 3020 S 0.3 0.1 0:16.54 sshd
3299 gdm 20 0 717944 12792 3812 S 0.3 0.2 25:50.53 gsd-color
top命令输出信息包含两部分内容:
第一部分为统计信息,包含五行数据信息;第二部分为详细信息,显示了各个进程的详细信息。
1. 第一部分
第一行
- 12:53:04表示当前时间,也就是当前真实的时间。
- up 157 days 13:35,表示这个系统从启动到现在的时间,上图显示的含义就是这个系统从157天13个小时35分钟以前就启动了。
- 5 users 表示当前在使用这个机器的用户数量。
- load average: 0.00, 0.00, 0.00 ,这个值表示系统过去1分钟,5分钟,15分钟的系统负载。关于系统负载查看后文
第二行
第二行主要表示当前系统当中任务的相关情况,所谓任务就是当前系统当中一共有多少个进程。
- 652 totoal,这个表示当前系统当中一共有652个进程。
- 1 runnung,表示有一个进程正在执行。
- 651 sleeping,表示有651个进程处于睡眠状态,也就是不需要使用CPU的状态。
- 0 stoped,表示有0个进程处于stopped状态,这个状态就是被停下来的进程,比如说通过ctrl+z让一个进程停下来,你可以通过给这个进程发送一个信号SIGCONT让这个进程恢复执行,linux当中进程的状态变换如下所示:
- 0 zombie,这个就表示僵尸进程的个数,这里是0个僵尸进程,所谓僵尸进程就是一个进程执行完成了,对于C程序来说你可以理解为你的main函数执行完成了(这个不够准确,其实main函数执行完成之后还会有其他函数需要执行,但是这里你可以大致这么理解),如果这个时候(函数执行完成),这个进程的父进程却没有接受子进程发送给他的信号(子进程在执行完成之后会给父进程发送信号,父进程需要通过wait等系统调用去接受这个信号),那么子进程就处于zombie状态,处于这个状态的进程就需要父进程接受它发送的信号,然后子进程的系统资源就可以被回收了,然后子进程会彻底消亡。
我们现在花一点时间来谈一谈linux当中的进程状态。
- Ready,当进程被创建完成之后他就处于Ready状态,在这个状态下的进程只差CPU了,也就是说,他现在只需要被操作系统调度获取CPU然后他就可以执行了。
- Running,当进程从Ready状态获取CPU的执行权的时候,进程就处于Running状态,这个状态表示进程正在执行。
- traced,这个状态主要是一个进程处于调试状态,这个状态需要调试的进程给这个被调试的进程发送信号,然后和这个进程才可以继续执行。
- Zombie,当进程执行完成之后,父进程接受子进程发送的信号之前,进程就处于这个状态。
- Suspended,这个状态表示进程被挂起,当进程请求IO的时候,需要阻塞等待IO请求完成,这个时候的进程状态就是Suspened状态。
第三行
这一行主要是各种时间所占的百分比的统计,这个数据的统计时间区间是,从本次刷新到上一次刷新之间,实在这个区间统计的数据
- us,运行没有指定优先级的用户进程所消耗的CPU时间所占百分比,默认的终端执行的程序都是没有指定优先级的,我们可以使用nice这个命令来改变程序执行的优先级:
sudo nice -n -10 ./time
。 - sy,运行内核进程所消耗的CPU时间所占的百分比。
- ni,运行指定了修改过优先级之后的用户进程所占的CPU时间百分比。这里可以结合PR和NI两个字段进行分析,我们现在执行
sudo nice -n 10 ./a.out
命令,在./a.out当中我启动了10个死循环的线程,我们来看一下它的top输出结果:
从上面的结果来看我们通过nice命令修改来进程优先级,但是需要注意的是一个进程的PR值越大他的优先级越低,NI值越大优先级越低,也就是说我们上面实际上是降低了进程执行的优先级了,但是我们可以看到ni的值是发生变化了的,这也印证了上面我们所谈到的ni值发生变化的过程。我们再来看一下没有设置优先级的结果,直接执行sudo ./a.out
:
但是在实验测试的过程当中发现了一个奇怪的问题,但我们提升进程的优先级(提升优先级需要管理员权限)的时候ni的值没有发生变化,因此上面所谈到的ni的变化应该只适用于普通用户的进程(因为降低优先级不需要管理员权限)。 - id, idle进程执行所占的CPU时间百分比,当系统当中没有足够的进程让CPU执行的时候,idle进程会被调度到CPU上进行执行,这个idle进程是为了让操作系统能够良好的执行起来所设置的,idle进程主要执行HLT指令,这个指令主要是让CPU节能,不需要CPU满负荷运转,因为这个时候没有具体的进程需要执行,这个百分比越大说明系统负载越轻,CPU不繁忙。
- wa,这个很好解释,等待IO的时间。
- hi,处理硬件中断所消耗的时间。
- si,处理软件中断所消耗的时间
- st,这个时间稍微有点复杂,IBM解释原文为:
这个主要是虚拟机的虚拟CPU等待真实物理CPU的时间,可以大致认为是Ready状态到Running状态的等待时间,如果这个值越大说明虚拟机运行状态越不好,因为它等待真实CPU的时间很长。Steal time is the percentage of time a virtual CPU waits for a real CPU while the hypervisor is servicing another virtual processor.
第四行
这一行表示的是物理内存的信息,单位是KiB。
- total, 表示一共有多少内存,也就是物理内存大小。
- free, 表示还有多少物理内存没有使用。
- used, 表示使用了多少物理内存。
- buff/cache, 表示用于用于缓存的物理内存的大小。
第五行
这一行主要表示的是对交换分区的数据,所谓对换区就是当操作系统发现内存满了之后,操作系统会选择部分不常使用的页面将它放到磁盘当中当需要使用的时候再将这部分数据从磁盘当中读取出来。
- total, 表示对换区的总大小。
- free, 表示对换区当中还有多少空间没有使用。
- used, 表示对换区当中有多少空间被使用了。
- avail Mem 是一个可用于启动新程序的内存大小的估计值。
2. 第二部分
第二部分为详细信息,显示了各个进程的详细信息
表头内容含义
-
PID,表示进程号,就是每个进程的ID。
-
USER,就是用户的名称。
-
PR,优先级值。
-
NI,nice值,通过程序给进程设置的。
-
VIRT,进程使用的虚拟内存的大小,单位是KiB。
-
RES,常驻内存的内存大小,单位是KiB。
-
SHR,共享内存的大小,单位是KiB。
-
S,表示进程的状态,有以下几个状态。
D,不能够中断的睡眠状态。 R,表示程序正在CPU上执行。 S,表示进程正在睡眠。 T,进程被信号停止执行。 t,表示进程正在被调试器追踪,调试器将这个进程停了下来。 Z,zombie表示是一个僵尸进程。
-
%CPU,上次一刷新之前对应的进程对CPU的占有率,这个值是可以突破100%的,因为一个进程可以有多个线程,CPU的占有率是可以超过%100的,这个值的计算主要是在刷新之间内
一个进程消耗的CPU时间
和在这段时间内一个CPU能够产生的CPU时间
的比值
。 -
%MEM,这个主要是进程使用的内存占用实际的可用的物理内存的比例。
-
TIME+,这个表示自从进程启动以来累计消耗的CPU时间。
-
COMMAND,这个表示启动进程的时候执行的命令。
3. top命令交互操作
- c,详细显示命令行的内容,你在交互模式下直接按下键盘上的c即可
- o,在交互模式下先按下键盘上的o,然后就可以输入过滤条件,在这里掩饰的是
COMMAND=systemd
的进程
top - 11:50:26 up 7 days, 6:58, 1 user, load average: 0.00, 0.01, 0.05
Tasks: 178 total, 1 running, 177 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.2 sy, 0.0 ni, 99.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1797044 total, 876428 free, 281024 used, 639592 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 1354556 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 125748 4208 2632 S 0.0 0.2 0:02.67 systemd
590 root 20 0 39056 4076 3744 S 0.0 0.2 0:00.79 systemd-journal
626 root 20 0 45788 2248 1332 S 0.0 0.1 0:01.40 systemd-udevd
772 root 20 0 26384 1756 1464 S 0.0 0.1 0:00.63 systemd-logind
- k,shell给我们提供了一个非常方便的操作我们可以在交互模式下选择我们想要杀死的进程。我们先在交互模式下先按下键盘上的k,然后输入进程号,然后输入回车,再输入想发送的信号类型。
- u,通过用户过滤,在交互模式下按下键盘上的u键,然后就可以输入你想看那个用户的进程,输入对应的用户名称即可
- h,查看帮助信息:
- i,过滤掉CPU利用率很低的进程,很多时候我们在进行系统分析的时候需要去判断那个进程CPU占有率高,因此i是一个非常有效的方式过滤掉干扰进程。
2 关于系统负载
在Linux系统中,uptime、w、top等命令都会有系统平均负载load average的输出
load average: 0.09, 0.05, 0.01
很多人会这样理解负载均值:三个数分别代表不同时间段的系统平均负载(一分钟、五 分钟、以及十五分钟),它们的数字当然是越小越好。数字越高,说明服务器的负载越 大,这也可能是服务器出现某种问题的信号。
而事实不完全如此,是什么因素构成了负载均值的大小,以及如何区分它们目前的状况是 “好”还是“糟糕”?什么时候应该注意哪些不正常的数值?
回答这些问题之前,首先需要了解下这些数值背后的些知识。我们先用最简单的例子说明, 一台只配备一块单核处理器的服务器。
行车过桥
一只单核的处理器可以形象得比喻成一条单车道。设想下,你现在需要收取这条道路的过桥 费 — 忙于处理那些将要过桥的车辆。你首先当然需要了解些信息,例如车辆的载重、以及 还有多少车辆正在等待过桥。如果前面没有车辆在等待,那么你可以告诉后面的司机通过。 如果车辆众多,那么需要告知他们可能需要稍等一会。
因此,需要些特定的代号表示目前的车流情况,例如:
0.00 表示目前桥面上没有任何的车流。 实际上这种情况与 0.00 和 1.00 之间是相同的,总而言之很通畅,过往的车辆可以丝毫不用等待的通过。
1.00 表示刚好是在这座桥的承受范围内。 这种情况不算糟糕,只是车流会有些堵,不过这种情况可能会造成交通越来越慢。
超过 1.00,那么说明这座桥已经超出负荷,交通严重的拥堵。 那么情况有多糟糕? 例如 2.00 的情况说明车流已经超出了桥所能承受的一倍,那么将有多余过桥一倍的车辆正在焦急的等待。3.00 的话情况就更不妙了,说明这座桥基本上已经快承受不了,还有超出桥负载两倍多的车辆正在等待。
上面的情况和处理器的负载情况非常相似。一辆汽车的过桥时间就好比是处理器处理某线程 的实际时间。Unix 系统定义的进程运行时长为所有处理器内核的处理时间加上线程 在队列中等待的时间。
和收过桥费的管理员一样,你当然希望你的汽车(操作)不会被焦急的等待。所以,理想状态 下,都希望负载平均值小于 1.00 。当然不排除部分峰值会超过 1.00,但长此以往保持这 个状态,就说明会有问题,这时候你应该会很焦急。
“所以你说的理想负荷为 1.00 ?”
嗯,这种情况其实并不完全正确。负荷 1.00 说明系统已经没有剩余的资源了。在实际情况中 ,有经验的系统管理员都会将这条线划在 0.70:
“需要进行调查法则”: 如果长期你的系统负载在 0.70 上下,那么你需要在事情变得更糟糕之前,花些时间了解其原因。
“现在就要修复法则”:1.00 。 如果你的服务器系统负载长期徘徊于 1.00,那么就应该马上解决这个问题。否则,你将半夜接到你上司的电话,这可不是件令人愉快的事情。
“凌晨三点半锻炼身体法则”:5.00。 如果你的服务器负载超过了 5.00 这个数字,那么你将失去你的睡眠,还得在会议中说明这情况发生的原因,总之千万不要让它发生。
那么多个处理器呢?我的均值是 3.00,但是系统运行正常!
哇喔,你有四个处理器的主机?那么它的负载均值在 3.00 是很正常的。
在多处理器系统中,负载均值是基于内核的数量决定的。以 100% 负载计算,1.00 表示单个处理器,而 2.00 则说明有两个双处理器,那么 4.00 就说明主机具有四个处理器。
回到我们上面有关车辆过桥的比喻。1.00 我说过是“一条单车道的道路”。那么在单车道 1.00 情况中,说明这桥梁已经被车塞满了。而在双处理器系统中,这意味着多出了一倍的 负载,也就是说还有 50% 的剩余系统资源 — 因为还有另外条车道可以通行。
所以,单处理器已经在负载的情况下,双处理器的负载满额的情况是 2.00,它还有一倍的资源可以利用。
多核与多处理器
先脱离下主题,我们来讨论下多核心处理器与多处理器的区别。从性能的角度上理解,一台主 机拥有多核心的处理器与另台拥有同样数目的处理性能基本上可以认为是相差无几。当然实际 情况会复杂得多,不同数量的缓存、处理器的频率等因素都可能造成性能的差异。
但即便这些因素造成的实际性能稍有不同,其实系统还是以处理器的核心数量计算负载均值 。这使我们有了两个新的法则:
-
“有多少核心即为有多少负荷”法则: 在多核处理中,你的系统均值不应该高于处理器核心的总数量。
-
“核心的核心”法则: 核心分布在分别几个单个物理处理中并不重要,其实两颗四核的处理器 等于 四个双核处理器 等于 八个单处理器。所以,它应该有八个处理器内核。