background image

cpu us 消耗高
  当出现 cpu us 消耗高时,通常的排查方法如下。
  从经验上来说,有些时候是由于频繁 cms gc 或 fgc 造成的(频繁的意思是差不多每
次 cms gc 或 fgc 一结束后又立刻继续),在 gc log 是记录的情况下(-Xloggc:),可通过
gc log 看看,如果没打开 gc log,可通过 jstat -gcutil 来查看,如是 gc 频繁造成的,

 

则可跳到后面的内存问题 | GC 频繁部分看排查方法。

如不是上面的原因,可使用 top -H 查看线程的 cpu 消耗状况,这里有可能会看到有

个别线程是 cpu 消耗的主体,这种情况通常会比较好解决,可根据 top 看到的线程 id 进
行十六进制的转换,用转换出来的值和 jstack 出来的 java 线程堆栈的 nid=0x[十六进
制的线程 id]进行关联,即可看到此线程到底在做什么动作,这个时候需要进一步的去排
查到底是什么原因造成的,例如有可能是正则计算,有可能是很深的递归或循环,也有
可能是错误的在并发场景使用 HashMap 等,例如这里还有一段随即生成字符串的耗
cpu 的代码 case。

如 top -H 看到的消耗 cpu 的线程是不断变化的,就比较麻烦了,有个同学写了个脚

本自动的去通过 top -H 看到的消耗 cpu 的线程找到对应的 Java 线程堆栈,在这种情况
下可以用这个脚本去试试,如果看到的线程堆栈确实是比较耗 cpu 的动作,则基本可以
定位到。

  如仍然看不出,则可以尝试多 jstack 看看,然后多看看是否经常有一些耗 cpu

的动作在不同的线程不断的出现。

  如可使用 perf,则可用 perf top 看看 cpu 消耗的热点,不过默认的版本上只能

看到 jit 后的代码,因此可能会比较难对应到具体的代码,这里有一个基于 perf 排查的
Java 应用 cpu us 诡异现象的 case。

  总结来说,cpu us 消耗高的问题排查还是有一定复杂性,例如之前我碰到过反

序列化的对象比较大,请求又非常频繁,导致 cpu us 消耗增高了很多,但当时的机器内
核版本不够,不支持 perf,从 jstack 等等上都看不出什么,后来是由于从业务监控的变
化上才排查出问题。