概述
接着上篇cpu高的怎么回事(一),通过一些实例继续分析性能问题的现象和原因,希望能给研发兄弟们一点点参考价值。
工具及版本
工具 | 版本 | |
---|---|---|
Arthas | 3.5.2 | |
perf | 3.10.0-1160.31.1.el7.x86_64.debug | |
JDK | 1.8.0_221 |
实例
常见的导致CPU飙高问题主要包含无限循环、FULLGC、资源等待造成线程池满这些。下面分别实现这两块代码来测试下当出现这些情况时,Arthas\Jstack\perf等工具会给出我们怎么样的现象表现。
- 死循环或代码中存在CPU密集计算。这种情况多核CPU us会同时上涨。
- 内存问题,导致大量FULLGC,阻塞线程。这种情况一般只有一核CPU us上涨。
- 资源等待造成线程池满,连带引发CPU上涨。这种情况下,线程池满等异常会同时出现。
- 如果非自愿上下文切换较多,说明CPU抢占较为激烈,大量进程由于时间片已到等原因,被系统强制调度,进而发生的上下文切换。
- 如果自愿上下文切换较多,说明可能存在I/O、内存等系统资源瓶颈,大量进程无法获取所需资源,导致的上下文切换。
- NET_TX & NET_RX。NET_TX是发送网络数据包的软中断,NET_RX是接收网络数据包的软中断,这两种类型的软中断较高时,系统存在网络I/O瓶颈可能性较大。
- SCHED。SCHED为进程调度以及负载均衡引起的中断,这种中断出现较多时,系统存在较多进程切换,一般与非自愿上下文切换高同时出现,可能存在CPU瓶颈。
无限循环
1,使用我们的一个无限循环例子,部署到服务器上,并触发无限循环。此时top一下可以看到cpu 100%。如下图所示:
image-20210716104731832.png2,紧接着使用jstack + top来分析
-
通过top -Hp 进程id 获取cpu飙高的线程id,如下所示:
image-20210716104901196.png -
接下来通过jstack获取cpu飙高时对应的线程的详情,很快我们就找到了线程飙高的代码,其中69b8就是对应的jstack中的nid,如下图所示:
image-20210716105010148.png image-20210716105039056.png
3,我们切换下使用arthas分析,如下图所示,2步就到位了。
image-20210716110150065.png image-20210716110200238.png4,继续使用vmstat、perf 、pidstat等工具分析
-
这里我们主要表现在cpu使用率较高,于是使用vmstat来观察下cpu的使用情况,如下图所示,发现cpu上下文切换达到1W。
image-20210716113453388.png -
但,应该不是我们这个程序导致的,于是我们通过pidstat -w -p 27029 1 100 观察该线程的上下文切换情况,发现正如我们所想,如下图所示:
-
停掉无限循环,发现如下图所示,us这个掉了。这说明无限循环会造成cpu us 飙高。
image-20210716140307493.png -
继续使用perf来观察下,命令perf top -F 99 -g -a -p 27029 ,结果如下,发现没有什么异常。
image-20210716111749370.png
FULL GC
1,为了观察full gc,我们造了个例子直接定时调用System.gc(),同时去掉-XX:+DisableExplicitGC启动配置,部署后触发,如下图执行情况:
image-20210716170002208.png2,首先使用top + jstack去分析对应的进程,相比其他线程,可以看到VM Thread线程跑得很勤快。
image-20210716170130241.png image-20210716170053461.png3,对比使用Arthas工具观察,每一次fullgc ,gc.g1_old_generation.count都会加1。同时也有VM thread线程跑得很勤。
image-20210716170210414.png4,同样使用pidstat 、vmstat、perf去分析。cpu使用率稍微有点,同时perf可以很明显看到gc线程。
image-20210716172608571.png image-20210716172635079.png
网友评论