资讯专栏INFORMATION COLUMN

【VisualVM 简明教程】(4): 分析CPU

ormsf / 412人阅读

摘要:快照,带线程命令,是显示全部进程,是显示线程,全格式输出显示进程树,不加显示所有实时快照推荐程度按数字从小到大。

有时候好好的程序放到生产服务器上一段时间后,就会发现服务器响应缓慢,进而进一步发现是cpu过高,于是就慌了,造成cpu过高的原因很多,不过大多是由于资源吃紧造成,例如:sql执行过慢,程序里存在死循环,数据库连接未释放,网络阻塞导致的第三方框架代码出现死循环,大量的操作导致死锁等

案例:死循环造成CPU过高
public class CpuTest {
 
    public static void main(String[] args) throws InterruptedException {
        loop();
        endlessLoop();
    }
 
 
    public static void endlessLoop() throws InterruptedException {
 
        while (true) {
            System.out.println("hello world! loop!");
        }
    }
 
    public static void loop(){
        for (int i = 0; i < 10000; i++) {
            System.out.println("hello world! endless loop!");
        }
    }
}

分析点击抽样器->CPU->查看CPU样例,发现endlessLoop()方法最耗CPU(这里有2个方法 loop和endlessLoop)

查看线程cpu耗时,发现main线程最耗时,点击增量,可以从此刻观察,cpu耗时的增长速率

查看线程dump,主要观察main线程,发现main线程当前状态下一直在执行CpuTest.endlessLoop(CpuTest.java:14),这里可以定位问题位置,同时细心的童鞋可以观察看后面执行System.out.println("");方法是要先加锁的。

截图一段,我生产服务器(tomcat+springmvc)main线程的情况,其实只想说明web项目启动的main方法在中间件里。

补充

VisualVm只能定位JVM的cpu情况,但是生产主机上不光是Java程序,这时我们要采取另外的方案。

1.看监控数据是否正常,cpu,mem。

CPU占用1.5左右(100-98.0id) 内存占用50%(435/100*100%=43.5%) 阿里云监控内存大小转成实际占用内存大小,类似windows ,平均负载 0.1 差不多,其他几个参数,这里暂不介绍。

2.假设异常,找到异常的PID。

这里推荐htop(清晰进程,线程,命令行,排序支持鼠标双击,过滤,kill程序,标记某个线程或者进程,安装apt-get install htop)

如果你没有服务器上安装软件的权限的话,就老老实实用top。通过top命令(默认3秒刷新,回车空格手动刷新,top -d 5 5秒刷新,也可以进入top后输入d设置刷新时间,top -p 4360 监控指定进程),然后按X ,默认按照CPU%排序,查看系统运行情况,如果想强制按CPU 降序,则输入大写P,如果强制按内存降序,则输入大写M(top命令是交互式的)。

解读
1).现在系统时间 10:18.44 ,系统一直运行了 131天16小时51分,当前有1个用户登录系统(相同账号也算不同用户),平均负载分别为0.00,0.01,0.05(分别为1分钟,5分钟,15分钟的负载情况,load average是每隔5秒钟检查一次活跃的进程数,用特定的算法得到的数值,然后除以逻辑CPU数量,如果负载持续大于cpu个数,则表明负载过高) 。大概可以看出系统负载很低,运行状态健康。

2).当前一共有103个进程,处于运行的有2个,处于休眠状态的有101个,处于停止状态的有0个,处于僵尸状态的有0个。大概可以看出系统进程总数较少,环境比较单纯,运行中的进程不多。

3).0.3 us 用户空间占用CPU 0.3%,0.7 sy内核占用CPU 0.7%,0.0 ni改变过优先级的进程占用CPU的百分比,98.0 id空闲CPU的百分比为98.0,0.3 waIO等待所占用CPU的百分比为0.3,0.3 hi硬中断(Hardware IRQ)占用CPU的百分比为0.3(外设给CPU的异步信号(中断),例如:网卡收到数据包),0.0 si软中断占用cpu的百分比为0(软件本身给操作系统内核的中断信号,通常由硬中断处理程序对操作系统内核的中断),0.3 st 虚拟机被hypervisor偷去CPU的时间。

4).KiB Mem 代表内存占用,1016272 total 内存总的大小1g(以kb为单位),941492 used 使用中的内存总量为0.9g,74780 free空闲内存总量为74m(吓一跳吧,才74M,这个不是实际剩余的内内存大小)115900 buffers缓存的内存量为115m,389836 cached cached大小380M。空闲内存总量只有74m,如果是windows去理解的话,此台服务器已经快挂了,实际内存大小等于74M+ buffers+cached = 580m(哈哈,够用,才占用一半呢), linux的内存管理和windows是不一样的,Linux会借用空闲的内存当作磁盘缓存, 磁盘数据缓存会让linux运行的更快,它永远不会从程序中拿出内存,它没有任何缺点,只是会混淆新手,如果你的应用程序需要更多的内存,他们会回收一部分用作磁盘数据缓存的物理内存,返回给应用程序,这个过程不需要启动交换,磁盘缓存(Disk caching)是不能禁用的, 但是可以释放磁盘缓存 1).只释放pagecache(文件缓存) echo 1 > /proc/sys/vm/drop_caches 2).释放dentries和inodes echo 2 > /proc/sys/vm/drop_caches 3).释放pagecache,dentries和inodes echo 3 > /proc/sys/vm/drop_caches
具体原理可以查看linuxatemyram

我们利用free 进一步证实上面的内容


1).shared代表被线程共享的内存大小(大多数已经舍弃掉),buffer用来给块设备做缓存(记录文件系统的metadata和tracking in flight pages),cache缓存文件(第二次打开就很快),linux系统cached比较大,cached大小390m,buffers为110m。

2).435288代表 -buffers/cache (应用程序实际使用330m内存) 580984 代表 +buffers/cache(实际剩余内存大小580m)。

3).重要等式 total = used + free used(-buffers/cache) = used(Mem)-buffers(Mem)-cached(Mem) free(+buffers/cache) = free(Mem) + buffers(Mem) +cached(Mem)

4).free命令的值是从 /proc/meminfo 文件里读到的。

5).Swap 交换区 总共大小 0 kb,已经使用0kb,释放了0Kb,如果swap used > 0,则可以说明系统内存瓶颈了

6).内存总和 free -t 总和等于total(Mem) + total(Swap)。

7).一般常用命令 free -s 3 每3秒观察一次内存使用情况。

占用cpu最高的进程是java,PID为28628,USER进程所有者root,PR优先级20,NI为0(负值优先级高,正值优先级低,PR=NI+20) ,VIRT进程使用虚拟内存1G(java进程最高只能占用到1G),RES进程实际使用的物理内存270M(不包含swap和shared),SHR共享内存大小5M,S进程状态随眠状态(S睡眠,R运行,T停止或被跟踪,Z僵尸,D不可中断睡眠态),%CPU占用CPU 0.7%,%MEM占用内存27%,TIME+进程使用cpu的时间54分40.12秒。总体看java进程运行良好。

3.这里假设PID为16368的进程占用CPU比较高(因为做了多次实验,所以PID没办法和上面的28628保持一致),
先用ps -ef | grep java,也可以用htop filter java,也可以jps -v 找到 java的进程ID 16368(只能查看当前用户的java pid,不太建议使用,-v显示详细信息,也可以不加)


?代表终端设备未知,Sl代表休眠状态多线程

Linux通过进程查看线程的方法 1).htop按t(显示进程线程嵌套关系)和H(显示线程) ,然后F4过滤进程名。2).ps -eLf | grep java(快照,带线程命令,e是显示全部进程,L是显示线程,f全格式输出) 3).pstree -p (显示进程树,不加pid显示所有) 4).top -Hp (实时) 5).ps -T -p (快照) 推荐程度按数字从小到大

4.利用jstack 16368 > 2016-1-21.tdump (jstack是jdk自带的生成java stack和native stack的工具) 把threaddump输出到文件里,这里假设PID为16369(一般比进程号+1的是main线程,如果存在main线程貌似最先分配)的线程占用CPU最高,将其ID转成16进制0x3ff1(使用命令 printf "%x " 16369 输出3ff1)。

5.搜索threaddump文件,nid= 0x3ff1的线程堆栈,通过堆栈信息,就可以定位到占用CPU最高的代码地方(这里是正常的)。

好啦,CPU冲高问题排查完毕,有了这样的知识体系,以后完全可以举一反三,coder君同时附上其他常用配合命令。

每隔一秒显示新生代,老年代,持久代垃圾回收情况

jstat -gcutil 16368 1000ms 参考jstat -help,也可以查看远程主机的GC情况,需要远程主机开启jstatd服务。

观察堆内存情况

jmap -dump:format=b,file=2016-1-21.mdump 16368 生成堆dump,放到mat或者vvm进行分析,上篇分析OOM有讲到。

查看jvm系统参数

jinfo 16368

参考资料

性能分析神器VisualVM

vvm命令

感谢您的耐心阅读,如果您发现文章中有一些没表述清楚的,或者是不对的地方,请给我留言,你的鼓励是作者写作最大的动力,
如果您认为本文质量不错,读后觉得收获很大,不妨小额赞助我一下,让我更有动力继续写出高质量的文章。

支付宝

微信

作 者 : @mousycoder

原文出处 : http://mousycoder.com/2016/02...

创作时间:2016-2-14

更新时间:2016-2-14

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/65479.html

相关文章

  • VisualVM 简明教程】(5): 分析线程

    摘要:是代表的主机第一个请求服务,使用线程池,生成一个单独的线程来处理请请求。单个线程详细的数据查看线程的堆栈生成某个时刻的线程这些线程的来由一清二楚,很快就能定位问题所在。 VisualVM提供分析图形化监控线程的运行状态,有时候可能不是我们自己代码没写好造成资源的浪费,而是系统引入了很多第三方包(也包括容器)的时候,他们可能私自建立线程,如果逻辑处理不当,可能会造成资源的浪费。 以下均用...

    Prasanta 评论0 收藏0
  • JVM详解3.JDK监控和故障处理工具

    摘要:点击进入我的博客命令行工具这些工具大多数是类库的一层薄的包装,它们的主要功能代码是在类库中实现的。可视化工具是到目前为止随发布的功能最强大的运行监视和故障处理程序,并且可以预见在未来一段时间内都是官方主力发展的虚拟机故障处理工具。 点击进入我的博客 3.1 JDK命令行工具 showImg(https://segmentfault.com/img/remote/14600000174...

    Keven 评论0 收藏0
  • 细述 Java垃圾回收机制→Java Garbage Collection Monitoring a

    摘要:垃圾回收监控和分析工具是在安装时免费提供的。监控现在可以监控垃圾回收过程了。至少我们可以知道程序中存在和对象内存分配和垃圾回收相关的问题。到此为止,关于垃圾回收的系列文章已经完结了。 本文非原创,翻译自Java Garbage Collection Monitoring and Analysis在Java中为对象分配和释放内存空间都是由垃圾回收线程自动执行完成的。和C语言不一样的是Ja...

    xuhong 评论0 收藏0
  • 使用JDK自带的VisualVM进行Java程序的性能分析

    摘要:是什么是自带的一个用于程序性能分析的工具,安装完毕后就有啦,在安装目录的文件夹下能找到名称为。假设我自己实现了一个快速排序算法,我想测一测它的性能。首先我在下图代码第行执行我的快速排序算法之处设置一个断点。回到,按结束应用程序的执行。 VisualVM是什么? showImg(https://segmentfault.com/img/remote/1460000016730111); ...

    piapia 评论0 收藏0
  • VisualVM 简明教程】(6): 检测死锁

    摘要:并且分别给出了,线程的堆栈,就可以很快定位代码。避免无限期等待当一个线程必须等待另外一个线程的时候,最好加上一个等待时间。 运行了一段时间的程序,可能因为不小心的一些修改,造成死锁,本人就VisualVM简单的介绍下死锁的检测。 死锁程序 package jvisualVM; public class DeadLock { public static void main(S...

    oneasp 评论0 收藏0

发表评论

0条评论

ormsf

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<