您的位置:首页 > 其它

怎样定位CPU占用率高的问题

2013-07-15 17:18 330 查看
怎样定位CPU占用率高的问题
在某些时候系统出现cpu占用率高的问题。当然,CPU占有率高不一定是问题。如果系统没有太多业务的情况下,CPU一直居高不下,这个时候就需要检查一下,为什么CPU使用率一直偏高。
下面介绍定位CPU偏高问题的一般步骤。 定位CPU过高实际上就是确定系统中哪些线程处于忙的状态,然后再检查该线程一直在忙,是正常的还是异常的。我们可以使用当前进程的堆栈信息来对线程进行分析。
首先可以通过kill -3 pid(unix下)
或 <ctrl>+<break>( windows下)
获取一个堆栈信息,几分钟之后再获取一个,通过两个堆栈信息对比,找到线程忙得一个,然后定位到代码位置。
第一步:通过kill -3 java_pid
获取当前堆栈信息。
第二步:等待1-5分钟之后。
第三步:同样在获取一下当前堆栈信息。
第四步:预处理前两个获取的堆栈信息,去掉处于sleeping或waiting的状态的线程。例如如下线程处于wait或者sleep状态,这种线程是不消耗CPU的,因此这些线程可以直接忽略掉,重点关注其它线程:
"EventManager-Worker-1" daemon prio=8 tid=0x00c3ea58 nid=0x14a in Object.wait() [935ff000..935ffc28]
at java.lang.Object.wait(Native Method) //该线程已挂起,忽略掉
- waiting on <0xbb9515a8> (a org.exolab.core.util.FifoQueue)
at java.lang.Object.wait(Object.java:429)
at org.exolab.core.util.FifoQueue.waitWhileEmpty(FifoQueue.java:308)
- locked <0xbb9515a8> (a org.exolab.core.util.FifoQueue)
at org.exolab.core.util.FifoQueue.get(FifoQueue.java:207)
- locked <0xbb9515a8> (a org.exolab.core.util.FifoQueue)
at org.exolab.core.threadPool.ThreadPoolWorker.runWork(ThreadPoolWorker.java:176)
at org.exolab.core.threadPool.ThreadPoolWorker.access$000(ThreadPoolWorker.java:67)
at org.exolab.core.threadPool.ThreadPoolWorker$1.run(ThreadPoolWorker.java:122)
at java.lang.Thread.run(Thread.java:534)
"RMI LeaseChecker" daemon prio=8 tid=0x00cafae0 nid=0xff waiting on condition [947ff000..947ffc28]
at java.lang.Thread.sleep(Native Method) //该线程已挂起,忽略掉
at sun.rmi.transport.DGCImpl$LeaseChecker.run(DGCImpl.java:307)
at java.lang.Thread.run(Thread.java:534)
第五步:对比预处理后的1,2堆栈信息,找出处于busy状态的线程,该类线程可能是导致cpu高占用率的嫌疑人。例如:(下面的是在第一个堆栈信息中找到的处于active
活跃状态的线程)
"http-80-Processor6" daemon prio=5 tid=0x013ea770 nid=0x143 runnable [92eff000..92f019c0]
at com.huawei.u_sys.common.licmgr.LicenseIntf.nativeCheckLicense(Native Method)
at com.huawei.u_sys.common.licmgr.LicenseIntf.checkLicense(LicenseIntf.java:168)
at com.huawei.u_sys.meetingone.sysmgr.ejb.LicRelateBean.updateLic(LicRelateBean.java:80)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at com.huawei.dopra.ejb.container.stateless.StatelessContainer.invoke(StatelessContainer.java:172)
at com.huawei.dopra.ejb.container.stateless.StatelessContainer.businessMethod(StatelessContainer.java:121)
at com.huawei.dopra.ejb.container.BaseContainer.invokeMethod(BaseContainer.java:186)
at com.huawei.dopra.ejb.container.BaseContainer.invoke(BaseContainer.java:160)
at com.huawei.dopra.ejb.container.ConcurrentExecutor.execute(ConcurrentExecutor.java:18)
at com.huawei.dopra.ejb.adapter.corba.LocalInvocationHandler.invoke(LocalInvocationHandler.java:136) at com.huawei.dopra.ejb.adapter.corba.LocalProxyInvocationHandler.invoke(LocalProxyInvocationHandler.java:256)
at $Proxy46.updateLic(Unknown Source)
at com.huawei.u_sys.meetingone.sysmgr.bo.LicRelateBOEJB.updateLic(LicRelateBOEJB.java:44)
at com.huawei.u_sys.meetingone.sysmgr.action.UploadLicenseAction.upload(UploadLicen
同一个线程在第二个堆栈信息中仍处于活跃状态。
"http-80-Processor6" daemon prio=5 tid=0x013ea770 nid=0x143 runnable [92eff000..92f019c0]
at com.huawei.u_sys.common.licmgr.LicenseIntf.nativeCheckLicense(Native Method) //The same thread is also working after 5 minutes
该线程已运行了5分钟
at com.huawei.u_sys.common.licmgr.LicenseIntf.checkLicense(LicenseIntf.java:168)
at com.huawei.u_sys.meetingone.sysmgr.ejb.LicRelateBean.updateLic(LicRelateBean.java:80)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at com.huawei.dopra.ejb.container.stateless.StatelessContainer.invoke(StatelessContainer.java:172)
at com.huawei.dopra.ejb.container.stateless.StatelessContainer.businessMethod(StatelessContainer.java:121)
at com.huawei.dopra.ejb.container.BaseContainer.invokeMethod(BaseContainer.java:186)
at com.huawei.dopra.ejb.container.BaseContainer.invoke(BaseContainer.java:160)
at com.huawei.dopra.ejb.container.ConcurrentExecutor.execute(ConcurrentExecutor.java:18)
at com.huawei.dopra.ejb.adapter.corba.LocalInvocationHandler.invoke(LocalInvocationHandler.java:136)
at com.huawei.dopra.ejb.adapter.corba.LocalProxyInvocationHandler.invoke(LocalProxyInvocationHandler.java:256)
at $Proxy46.updateLic(Unknown Source)
如上tid=0x013ea770
的线程5分钟里一直处于工作状态,这是一个可疑的线程,在这个案例中,nativeCheckLicense位于JNI代码中,因此下一步是定位JNI代码为什么一直处于忙的状态。(如果是纯java代码,那么下一步直接阅读源代码,检查该处代码是不是应该一直忙)。
查找JNI的堆栈信息,可以用pstack pid(unix)命令。如下:
native中的第一个堆栈信息

----------------- lwp# 320 / thread# 319 --------------------
9e7932c8 scan_info (1516900, 15168b4, 1516930, b68, 800, b1c) + f8
9e793628 parse (1516900, 15168b4, 1516924, 1516930, 9e793544, 332a8) + e4
9e78cc90 init (1516948, 549, 1516900, 15168b4, 1516924, 1516930) + 188
9e78cf54 LicFileParseInit (1516948, 549, 15168b4, 1516900, 1516924, 1516930) + 4c
9e79d484 AdaptiveLMStandAloneInitEx (15168b4, 1516930, 9e7c8ebc, 549, 9e7a9df3, 9e7a9dfe) + 480
9e78b04c AdaptiveLMStandAloneInit (1516718, 2c6f, 9e7c8ebc, 549, 9e7a9df3, 9e7a9dfe) + 2c
9e78a3e0 __1cLLicenseInit6Fpkc1_i_ (64df28, 64df28, 0, 7efefeff, 81010100, ff00) + 278
9e78a7c0 Java_com_huawei_u_1sys_common_licmgr_LicenseIntf_nativeCheckLicense (ff33a4, 932ff308, 932ff384, 932ff380, 70, 0) + 80
f980b96c ???????? (932ff384, b8, 0, bbd7f4d0, 0, 0)
f9805774 ???????? (932ff41c, b6, 0, f9816250, 8, 932ff320)
f9805774 ???????? (932ff4dc, 0, 0, f9815e98, c, 932ff3b0)
f980010c ???????? (932ff568, 932ff6a0, a, eaf4c430, 8, 932ff478)
fe15bd28 __1cJJavaCallsLcall_helper6FpnJJavaValue_pnMmethodHandle_pnRJavaCallArguments_pnGThread__v_ (932ff698, 932ff694, 932ff6cc, ff3310,
ff3310, fe216c2c) + 27c
fe216d74 __1cKReflectionGinvoke6FnTinstanceKlassHandle_nMmethodHandle_nGHandle_inOobjArrayHandle_nJBasicType_4ipnGThread__pnHoopDesc__ (0, 9
32ff7f8, fe5d5e40, 1, e940f0f0, a) + f0c
fe2a31c4 __1cKReflectionNinvoke_method6FpnHoopDesc_nGHandle_nOobjArrayHandle_pnGThread__2_ (bb779b10, 932ff880, 932ff87c, ff3310, fe2aa474,
932ffa98) + 238
fe2aa5c0 JVM_InvokeMethod (932ff9e8, 932ff9e4, fe5c9a00, fe5cc1d0, c, 932ffb20) + 254
fe79f104 Java_sun_reflect_NativeMethodAccessorImpl_invoke0 (ff33a4, 932ff960, 932ff9ec, 932ff9e8, 932ff9e4, 0) + 10
f980b96c ???????? (932ff9ec, b8, 0, f98147e0, 0, 0)
f9805750 ???????? (932ffa58, b5, 0, f9816250, c, 932ff978)
f9836880 ???????? (bd85a1d0, bc1c0b90, adf90e50, f9815028, c, 932ffa10)
f9a90870 ???????? (bd8571c0, bc1c0b90, adf90e50, f9815028, eae5e4a8, 0)
五分钟后再获取一次,如下,获取JNI的第二个堆栈信息
----------------- lwp# 320 / thread# 319 --------------------
9e7932c8 scan_info (1516900, 15168b4, 1516930, b68, 800, b1c) + f8
9e793628 parse (1516900, 15168b4, 1516924, 1516930, 9e793544, 332a8) + e4
9e78cc90 init (1516948, 549, 1516900, 15168b4, 1516924, 1516930) + 188
9e78cf54 LicFileParseInit (1516948, 549, 15168b4, 1516900, 1516924, 1516930) + 4c
9e79d484 AdaptiveLMStandAloneInitEx (15168b4, 1516930, 9e7c8ebc, 549, 9e7a9df3, 9e7a9dfe) + 480
9e78b04c AdaptiveLMStandAloneInit (1516718, 2c6f, 9e7c8ebc, 549, 9e7a9df3, 9e7a9dfe) + 2c
9e78a3e0 __1cLLicenseInit6Fpkc1_i_ (64df28, 64df28, 0, 7efefeff, 81010100, ff00) + 278
9e78a7c0 Java_com_huawei_u_1sys_common_licmgr_LicenseIntf_nativeCheckLicense (ff33a4, 932ff308, 932ff384, 932ff380, 70, 0) + 80
f980b96c ???????? (932ff384, b8, 0, bbd7f4d0, 0, 0)
f9805774 ???????? (932ff41c, b6, 0, f9816250, 8, 932ff320)
f9805774 ???????? (932ff4dc, 0, 0, f9815e98, c, 932ff3b0)
f980010c ???????? (932ff568, 932ff6a0, a, eaf4c430, 8, 932ff478)
fe15bd28 __1cJJavaCallsLcall_helper6FpnJJavaValue_pnMmethodHandle_pnRJavaCallArguments_pnGThread__v_ (932ff698, 932ff694, 932ff6cc, ff3310,
ff3310, fe216c2c) + 27c
fe216d74 __1cKReflectionGinvoke6FnTinstanceKlassHandle_nMmethodHandle_nGHandle_inOobjArrayHandle_nJBasicType_4ipnGThread__pnHoopDesc__ (0, 9
32ff7f8, fe5d5e40, 1, e940f0f0, a) + f0c
fe2a31c4 __1cKReflectionNinvoke_method6FpnHoopDesc_nGHandle_nOobjArrayHandle_pnGThread__2_ (bb779b10, 932ff880, 932ff87c, ff3310, fe2aa474,
932ffa98) + 238
fe2aa5c0 JVM_InvokeMethod (932ff9e8, 932ff9e4, fe5c9a00, fe5cc1d0, c, 932ffb20) + 254
fe79f104 Java_sun_reflect_NativeMethodAccessorImpl_invoke0 (ff33a4, 932ff960, 932ff9ec, 932ff9e8, 932ff9e4, 0) + 10
f980b96c ???????? (932ff9ec, b8, 0, f98147e0, 0, 0)
f9805750 ???????? (932ffa58, b5, 0, f9816250, c, 932ff978)
f9836880 ???????? (bd85a1d0, bc1c0b90, adf90e50, f9815028, c, 932ffa10)
f9a90870 ???????? (bd8571c0, bc1c0b90, adf90e50, f9815028, eae5e4a8, 0)
以同样的思路可以分析出线程lwp# 320 / thread# 319一直运行。该线程被定位为可疑线程。通过上面的操作,定位是license模块的问题,怀疑该模块中有死循环。后来通过这种方式定位出是由于license
lib不是安全线程。如果外部没进行线程同步,可能造成license native lib死循环。通过如上步骤,通过多次打印堆栈信息,查找出忙的线程,再通过阅读源代码,一般能够很容易定位出问题的根本位置。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: