常用性能调试手段

原创
2015/07/30 14:31
阅读数 2.6K

在开发过程中经常会出现这样那样的性能问题,让人很纠结,下面我会列举一些常用的性能调试手段来找出对应的性能问题的原因

一、CPU过高
这是最常发生的让人很纠结的问题,CPU 100%了 ,但到底是什么引发的呢?
使用Jprofiler之类的工具可以查看CPU问题,能列出CPU具体堆栈,但是有个问题是Jprofiler本身会占用很高的CPU,用Jprofiler来查看CPU问题的时候会很不靠谱。
下面介绍一些比较简单的查看CPU高的方法。
首先来看哪些线程占用了最多的CPU
(1)ps  -eLo pid,lwp,pcpu | grep  <pid>|sort -nk 3
   该方法可以找到CPU占用前3的线程
 (2) top -H 
   该方法能列出占用最高的那些线程
通过上述方法可以知道有问题的线程的pid,然后将该线程号由10进制改为16进制。
接下来来看线程的堆栈
jstack -l <pid>
该方法打出进程的所有线程堆栈,查找16进制的线程号,nid=0x17a1  这个就是线程号的位置
比如
"FelixStartLevel-SendThread(db-3.photo.163.org:2181)" daemon prio=10 tid=0x00007fba6406a800 nid=0x17a1 runnable [bidw:0x000000004027c000]
   java.lang.Thread.State: RUNNABLE
        at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
        at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:228)
        at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:83)
        at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87)
        - locked <0x00007fba7d9c2d80> (a sun.nio.ch.Util$1)
        - locked <0x00007fba7d9c31c0> (a java.util.Collections$UnmodifiableSet)
        - locked <0x00007fba7d9c2dd8> (a sun.nio.ch.EPollSelectorImpl)
        at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:98)
        at org.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1107)
   Locked ownable synchronizers:
        - None
这个jstack只是一个采样的方法,看当前线程执行的位置。
但我们可以假设在CPU100%的情况下,你基本上采样都是在出问题的语句上。因此这个堆栈的第一行
 at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
就是CPU出问题的地方。可以多用jstack采样几次 ,看看是否都在同一个地方。
这个方法很简单,屡试不爽,也不需要安装软件,方便使用。

二、内存OOM

内存OOM是大家常见的问题,线上遇到OOM不要慌,别先记着重启,第一步先把内存堆栈打印出来
jmap -dump:live,format=b,file=<filename>

如果线上经常经常出现OOM问题也可以在JVM参数里加上-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<filePath>  在进程OOM时自动dump出内存堆栈

有了内存堆栈就好办了,给大家介绍个工具MAT,是我觉得最好用的内存分析工具http://www.eclipse.org/mat/
      leak suspects帮助你分析内存泄露可能的地方,像我上面的例子就看出ShutDownHook有问题,溢出了
    但是溢出的对象从哪里来,可以在details中点击list objects-> Incoming references

 就能够看到引用对象的引用来源,这样就一目了然了哪里有泄露
三、句柄泄露

这是大部分java开发者不太会关心的一个问题,写过C程序的开发者会比较容易重视这个问题。正因为不重视所以还是很容易出现的。
大部分的监控平台都有CPU、内存、硬盘的监控,但很多没有句柄的监控。最后程序发生too many open files了,却不知道。

句柄泄露的查看方式很简单,可以用lsof -p <pid>,查看进程所占用的所有句柄,当句柄泄露的时候肯定会有部分句柄出现极为异常的数量。
lsof -p 6022 
java    6022   fs    1w   REG                8,8     5006   3014678 /home/xxx/log.log
java    6022   fs    2w   REG                8,8     5006   3014678 /home/xxx/log.log
需要仔细检查句柄占用过多的文件代码是否有问题。

我之前就发生过一次句柄泄露。也是代码写的有问题(第三方软件内部源码没研究透),不断重复开FileInputStream而没有复用,导致句柄泄露。哎。。。没监控,搞得很大个事
性能问题大家都容易碰到,分享一些个人的心得,帮助大家定位性能问题。大家有更好的方法也告诉我。


展开阅读全文
打赏
4
98 收藏
分享
加载中
Tex
赞一个,很实用
2015/07/31 17:13
回复
举报
更多评论
打赏
1 评论
98 收藏
4
分享
返回顶部
顶部