JAVA CPU,IO 消耗分析

12 篇文章 0 订阅

使用 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操作等待时间,单位毫秒

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值