使用 TOP
查看CPU的消耗情况
top - 11:32:49 up 26 days, 45 min, 2 users, load average: 0.20, 0.08, 0.07
Tasks: 471 total, 1 running, 470 sleeping, 0 stopped, 0 zombie
Cpu(s): 1.4%us, 0.2%sy, 0.0%ni, 98.4%id, 0.0%wa, 0.0%hi, 0.1%si, 0.0%st
Mem: 32827576k total, 29531680k used, 3295896k free, 402968k buffers
Swap: 10485752k total, 6736k used, 10479016k free, 25057232k cached
us:表示为用户进程处理所占用百分比
Sy:表示为内核线程处理所占用的百分比
ni:表示被nice命令改变优先级的任务所占用的百分比
id:表示CPU空闲时间所占用的百分比
wa:表示为在执行过程中等待IO所占用的百分比
hi:表示为硬件中断所占用的百分比。
si:表示软件中断所占用的百分比
对于多个或多核的CPU,上面的显示则会是多个CPU所占用百分比的总和,因此会出现150%us的现象。
如果查看每个核消耗情况,可进入TOP视图后按1 就会按核显示消耗的情况。
top - 11:41:52 up 26 days, 54 min, 2 users, load average: 0.47, 0.17, 0.10
Tasks: 471 total, 1 running, 470 sleeping, 0 stopped, 0 zombie
Cpu0 : 15.2%us, 1.4%sy, 0.0%ni, 82.8%id, 0.0%wa, 0.0%hi, 0.7%si, 0.0%st
Cpu1 : 0.3%us, 0.0%sy, 0.0%ni, 98.7%id, 1.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu2 : 0.7%us, 0.0%sy, 0.0%ni, 99.3%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu3 : 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu4 : 0.7%us, 0.0%sy, 0.0%ni, 99.3%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu5 : 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 32827576k total, 29631908k used, 3195668k free, 403248k buffers
Swap: 10485752k total, 6736k used, 10479016k free, 25152116k cached
默认情况下TOP视图中显示的未进程的CPU消耗状况,在TOP视图中按shift+h 后可按线程查看CPU
的消耗状况。
如图:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
28849 www 20 0 16.9g 2.5g 12m S 854.1 7.8 0:25.82 java
28851 www 20 0 16.9g 2.5g 12m S 852.5 7.8 0:25.77 java
28850 www 20 0 16.9g 2.5g 12m S 851.8 7.8 0:25.75 java
28848 www 20 0 16.9g 2.5g 12m S 851.1 7.8 0:25.73 java
30421 root 20 0 164m 4124 2948 S 3.6 0.0 815:12.96 python
此时的PID为线程ID。其后的%CPU表示该线程所消耗的CPU百分比。
除了TOP,常用的还有pidstat.
pidstat 是SYSSTAT中的工具,如需使用pidstat请先安装SYSSTAT
输入pidstat 1 2 ,在console上将会每隔1秒输出目前活动进程的CPU消耗状况,共输出两次
10:22:21 PID %usr %system %guest %cpu CPU Command
10:22:21 29500 10.11 0.11 0.11 10.42 2 java
其中CPU表示的为当前进程所使用的CPU个数,如需查看某个进程中线程消耗的状况,可输入
pidstat -p [pid] -t 1 5 这样的方式来查看,执行后输出
10:22:21 TGID TID %usr %system %guest %cpu CPU COMMAND
10:22:21 29500 - 62.00 0.00 0.00 62.00 2 JAVA
10:22:21 - 29500 0.00 0.00 0.00 0.00 2 |_JAVA
10:22:21 - 29501 14.00 0.00 0.00 14.00 2 |_JAVA
图中的TID即为线程ID,将之TOP而言,pidstat好处为可查看每个线程的具体CPU利用率的状况
(例如%system)
除了以上两种方式Linux还可以使用vmstat 来采样(例如每秒 vmstat 1)查看CPU上下文切换,
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
0 0 100828 4662444 915256 5713284 0 0 1 24 1 1 1 0 98 0 0
0 0 100828 4662436 915256 5713284 0 0 0 0 536 1017 0 0 100 0 0
0 0 100828 4662436 915256 5713284 0 0 0 0 516 1016 0 0 99 0 0
0 0 100828 4662436 915256 5713284 0 0 0 0 596 1081 0 0 100 0 0
运行队列,利用率的具体信息,ps Hh -eo tid ,pcpu方式也可用来查看具体线程的CPU消耗状况;
sar 来查看一定时间范围内以及历史的CPU消耗状况。
cs:CPU上下文频繁切换、
内存相关的是memory下的:swpd,free,buff,cache以及swap下的si,so
其中swpd是指虚拟内存已使用的部分,单位为KB,free表示空闲的物理内存,buff表示用于缓冲的内存。
cache 表示用户缓存的内存.
swap下的si是每秒从disk读取到内存的数据量。
so是指每秒从内存中写入disk的数量
swpd值过高通常是由于物理内存不够了,os将物理内存中的一部分数据转为存放到硬盘上进行存储,
已腾出足够的空间给当前运行的程序使用。在目前运行的程序变化后,即从硬盘上重新读取数据到内存,
已便恢复程序的运行,这个过程会产生swap IO ,因此看swap的消耗情况主要要关注的是swap IO的状况,
如swap io 发生得较频繁,那么会严重影响系统的性能。
由于Java应用是单进程应用,因此只要JVM的内存设置不是过大,是不会操作到swap区域的,物理内存消耗过高可能是由于JVM内存设置过大,创建的Java线程过多或通过Direct ByteBuffer往物理内存中放置了过多的对象造成的。
1. 确定占用cpu高的线程id:
方法一: 直接使用 ps Hh -eo pid,tid,pcpu | sort -nk3 |tail 获取对于的进程号和线程号,然后跳转到3.
方法二: . 查看哪个进程线程占用cpu过高; top / ps -aux, 获得进程号
. 确定哪个线程占用cpu过高,进入进程号的目录:/proc/pid/task,
执行:grep SleepAVG **/status | sort -k2,2 | head, 确定cpu占用较高的线程号。
2.使用:jstack pid, 或者kill -3 pid 会打印线程堆栈的情况。 jstack输出到当前命令的标准输出,kill -3 输出到当前进程jvm的标准输出。
根据第二步中获取的线程号,查询堆栈中正在执行的代码。输出示例如下:
Thread 2060: (state = BLOCKED)
- java.lang.Object.wait(long) @bci=0 (Compiled frame; information may be imprecise)
Error occurred during stack walking:
Thread 2059: (state = IN_NATIVE)
- java.net.PlainSocketImpl.socketAccept(java.net.SocketImpl) @bci=0 (Interpreted frame)
- java.net.PlainSocketImpl.accept(java.net.SocketImpl) @bci=7, line=384 (Interpreted frame)
- java.net.ServerSocket.implAccept(java.net.Socket) @bci=50, line=450 (Interpreted frame)
- java.net.ServerSocket.accept() @bci=48, line=421 (Interpreted frame)
- org.apache.jk.common.ChannelSocket.accept(org.apache.jk.core.MsgContext) @bci=46, line=293 (Interpret
ed frame)
- org.apache.jk.common.ChannelSocket.acceptConnections() @bci=68, line=647 (Interpreted frame)
- org.apache.jk.common.ChannelSocket$SocketAcceptor.runIt(java.lang.Object[]) @bci=4, line=857 (Interpr
eted frame)
- org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run() @bci=167, line=684 (Interpreted frame
----------------------------------
us 高
当us值过高时,表示运行的应用消耗了大部分的CPU,这种情况下,对于JAVA应用而言,最重要的是找到具体消耗CPU所执行的代码。
可采用如下方式做到。
首先通过Linux 提供的线程命令找到到消耗CPU严重的线程及其ID,将此线程转化为十六进制的值,之后通过kill -3 [javapid]
或jstack 的方式Dump出应用的线程信息,通过之前转化出的十六进制的值找到对应的nid值的线程,该线程即为消耗CPU的线程,在
采样时需多执行几次上诉的过程,已确保找到真实的消耗CPU的线程。
Java 应用造成US高的主要原因是线程一直处于可运行(Runnable)状态,通常是这些线程在执行无柱塞,循环,正则或纯粹的计算等动作
造成,另外一个可能也会造成US高的原因是频繁的FULL GC。
如每次请求都需要分配较多内存,当访问量高的时候就将导致不断的进行GC,系统响应速度下降,进而造成堆积的请求更多,消耗的内存更
严重,最严重的时候也可能导致系统不断的Full GC ,对于频繁的GC的状况要通过分析JVM内存的消耗来查找原因。
sy高
当sy高表示Linux花费了更多的时间在上下文切换,Java应用造成这种现象的主要原因是启动的线程比较多,且这些线程多数都处于不断的柱塞,
例如锁等待,IO等待等等
可采用的方法为通过KILL -3 [JAVAPID] 或jstack -l [javapid] 的方式dump 出JAVA 应用程序的线程信息,查看线程的状态信息以及锁信息,
找出等待状态或锁竞争过多的线程。
结合vmstat 1 查看CPU消耗状况
CPU在cs(上下文切换)以及sy上消耗很大,运行时采用jstack -l 查看程序的线程状况,可看到启动了很多线程,并且很多的线程都处于TIME_WAITING(on object monitor)
状态和Runnable 状态的转换中,通过on object monitor对应的堆栈信息,可查看到系统中锁竞争激烈的代码。
这是造成系统更多时间耗费在线程上下文切换的原因。
文件IO消耗分析
Linux在操作文件时,将数据放入文件缓存区,知道内存不够或系统要释放内存给用户进程使用,因此在查看Linux 内存状况是经常会发现free的物理内存不多,
但cache用了很多,这是linux 提升文件IO速度的一种做法。如物理空间内存够用,通常Linux只有些文件和第一次读取文件时会产生真正的IO。
在Linux 中要跟踪线程文件IO的消耗,主要方法是通过pidstat来查找。
pidstat -d -t -p [pid] 1 100
iostat
直接输入iostat可查看各个设备的IO历史状况
iostat
Linux 2.6.32-220.el6.x86_64 (idc01-sys-mo-01) 11/30/2013 _x86_64_ (16 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
6.52 0.00 4.19 0.62 0.00 88.66
Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn
sdb 0.00 0.00 0.00 3898 0
sda 4.10 12.64 385.83 24686188 753810672
sdd 0.00 0.00 0.00 6369 192
sdc 0.00 0.00 0.00 5200 0
sde 1.29 1.41 46.07 2751953 90012888
sdf 31.91 288.92 2232.85 564471380 4362395168
Device:表示设备卷标名或分区名,
TPS:表示每秒IO请求数,这也是IO消耗情况中值得关注的数字。
Blk_read/s :是指每秒读的块数量,通常块的大小512字节
Blk_wrtn/s :每秒写入的块数
Blk_read :总共读取的块数
Blk_wrtn:总共写入的块数。
还可以输入 iostat -x xvda 3 5 这样的方式来定时采样查看IO的消耗状况
iostat -x xvda 3 5
Linux 2.6.32-220.el6.x86_64 (idc01-sys-mo-01) 11/30/2013 _x86_64_ (16 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
6.52 0.00 4.19 0.62 0.00 88.66
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
avg-cpu: %user %nice %system %iowait %steal %idle
8.31 0.00 7.27 0.50 0.00 83.93
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
avg-cpu: %user %nice %system %iowait %steal %idle
8.66 0.00 7.10 0.46 0.00 83.78
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
avg-cpu: %user %nice %system %iowait %steal %idle
8.19 0.00 7.67 0.85 0.00 83.28
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
avg-cpu: %user %nice %system %iowait %steal %idle
5.45 0.00 7.07 0.33 0.00 87.14
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await svctm %util
r/s:每秒读的请求数
w/s:每秒写的请求数
await:平均每次IO操作等待时间,单位毫秒