0%

分析java应用cpu使用率飙升

疑惑

  • 一个 while 死循环,会不会引起 CPU 使用率飚升?
  • 频繁 Young GC 会不会引起 CPU 使用率飚升?
  • 线程数很高的应用,CPU 使用率一定高么?
  • CPU 使用率高的应用,线程数一定高么?
  • BLOCKED 状态的线程会不会引起 CPU 使用率飚升?
  • 分时操作系统 CPU 是耗费 us ? 还是耗费 sy ?

思考

1、CPU 使用率怎么计算?

CPU% = 1 - idleTime / sysTime * 100

  • idleTime:CPU处于空闲状态的时间
  • sysTime:CPU处于用户态和内核台的时间总和

2、CPU 使用率跟啥有关系?

常听说计算密集型的程序是比较耗 CPU 使用率的。

那 JAVA 应用中哪些操作是比较耗 CPU 使用的?

列举日常程序中常见的耗CPU的操作:

  • 频繁GC,访问量高时,有可能造成频繁的GC、甚至FGC。当调用量大时,内存分配过快,就会造成GC线程不停的执行,导致CPU飙高
  • 序列化与反序列化,后文中举了一个真实的案例,程序执行xml解析的时,调用量增大的情况下,导致了CPU被打满
  • 加密、解密
  • 正则表达式校验,曾经线上发生一次血案,正则校验将CPU打满。大概原因是:Java 正则表达式使用的引擎实现是 NFA 自动机,这种引擎在进行字符匹配会发生回溯(backtracking)
  • 线程上下文切换、当启动了很多线程,而这些线程都处于不断的阻塞状态(锁等待、IO等待等)和执行状态的变化过程中。当锁竞争激烈时,很容易出现这种情况
  • 某些线程在做无阻塞的运算,简单的例子while(true)中不停的做运算,没有任何阻塞。写程序时,如果需要做很久的计算,可以适当将程序sleep下

3、CPU 与进程、线程有关系么?

现在分时操作系统是通过循轮方式分配时间片进行进程调度的,如果进程在等待或阻塞,不会造成 CPU 资源使用。线程称为轻进程,共享进程资源,关于线程的调度,CPU 对于线程也是分时调度。而在 Java 中,线程的调用由 JVM 负责,线程的调度一般有两种模式,分时调度和抢占式调度。

解惑

1、一个 while 死循环,会不会引起 CPU 使用率飚升?

会的。

先不说别的,死循环会调用 CPU 寄存器进行计数,这个操作就会占用 CPU。其次,如果线程一直处于死循环状态,CPU 调用会进行线程切换么?

死循环不会让出 CPU,除非操作系统时间片到期,但死循环会不断向系统申请时间片,直到系统没有空闲时间做别的事情。

这个问题在 stackoverflow 也有人提问:why does an infinite loop of the unintended kind increase the CPU use?

地址:https://stackoverflow.com/questions/2846165/why-does-an-infinite-loop-of-the-unintended-kind-increase-the-cpu-use

2、频繁 Young GC 会不会引起 CPU 使用率飚升?

会的。

Young GC 本身是 JVM 进行垃圾回收的操作,会计算内存和调用寄存器,频繁 Young GC 一定是会占用 CPU。

之前有个一个案例,for 循环从数据库查询数据集合,二次封装新的数据集合,这时如果量比较大时,内存没有足够的空间存储,那么 JVM 就会 GC 回收那些不再使用的数据,因此量大的时候,就会收到 CPU 使用率报警。

3、线程数很高的应用,CPU 使用率一定高么?

不会。

通过 jstack 查看系统线程状态,查看整个线程数很多,但 Runable 和 Running 状态的线程不多,这时 CPU 使用率不一定会高。

之前有过一个案例,查看系统线程数 1000+,jstack 分析 900多个线程是 BLOCKED 和 WAITING 状态的,这种线程是不会占用 CPU 的。

如果线程数很高,其实大多数原因是死锁,大量线程处于 BLOCKED 和 WAITING 状态。

4、CPU 使用率高的应用,线程数一定高么?

不会。

同上,CPU 使用率高的关键因素还是计算密集型操作,一个线程如果有大量计算,也会造成 CPU 使用率高,也是现在为什么一个大数据脚本任务,要大规模集群共同运算才能运行的原因。

5、BLOCKED 状态的线程会不会引起 CPU 使用率飚升?

不一定。

CPU使用率的飙升,更多是因为上下文的切换或者runnable状态线程过多导致。Blocked状态,未必会引起CPU上升。

6、分时操作系统 CPU us高或者sy高是什么意思?

通过top命令,可以观察到CPU的us,sy值,示例如下:

这可能是全网分析java应用cpu使用率飙升最全的文章

  • us 用户空间占用CPU百分比,简单来说,us高是因为程序导致的,通过分析线程堆栈,可以很容易的定位到问题线程。
  • sy 内核空间占用CPU百分比,sy高的时候,如果是程序问题导致,基本是因为线程上下文切换造成的。

经验

平时怎么定位 CPU 使用率高的原因?网上有个教程和方法,下面简述一下分析过程。

首先发现某台应用 CPU 使用率高,一要看先线程数、JVM、系统 load 等参数,共同作证。二要打印 jstack,通过工具分析线程情况,推荐 fastThread 这个在线的 Thread 分析工具。

以下是线上发生的真实案例,简要介绍下:

某日晚,突然收到短信报警,CPU利用率100%。立刻dump该机器jstack,通过 http://fastthread.io/ 查看日志如下:

这可能是全网分析java应用cpu使用率飙升最全的文章

进一步查看具体日志:

这可能是全网分析java应用cpu使用率飙升最全的文章

通过这段日志,已经定位到了具体CPU被打满的方法,接收MQ之后,MQ消息体为xml,反序列化的时候,造成了CPU飙高。