JAVA 应用 CPU 使用率为什么飚升?

王洪涛

京东商城,商家研发部架构师。丰富的构建高性能高可用大规模分布式系统的研发、架构经验。2015年加入京东,目前负责服务市场的系统研发工作。

我的疑惑

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

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

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

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

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

分时操作系统 CPU 是耗费 us ? 还是耗费 sy ?

我的思考

CPU 使用率怎么算?

CPU% = 1 - idleTime / sysTime * 100

  • idleTime:CPU处于空闲状态的时间

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

CPU 使用率跟啥有关系?

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

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

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

  • 频繁GC,访问量高时,有可能造成频繁的GC、甚至FGC。当调用量大时,内存分配过快,就会造成GC线程不停的执行,导致CPU飙高。

  • 序列化与反序列化,后文中举了一个真实的案例,程序执行xml解析的时,调用量增大的情况下,导致了CPU被打满。

  • 加密、解密。

  • 正则表达式校验,曾经线上发生一次血案,正则校验将CPU打满。大概原因是:Java 正则表达式使用的引擎实现是 NFA 自动机,这种引擎在进行字符匹配会发生回溯(backtracking)。

  • 线程上下文切换、当启动了很多线程,而这些线程都处于不断的阻塞状态(锁等待、IO等待等)和执行状态的变化过程中。当锁竞争激烈时,很容易出现这种情况。

  • 某些线程在做无阻塞的运算,简单的例子while(true)中不停的做运算,没有任何阻塞。写程序时,如果需要做很久的计算,可以适当将程序sleep下。

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

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

我的解惑

一个 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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • Us 用户空间占用CPU百分比,简单来说,us高是因为我们的程序导致的,通过分析线程堆栈,可以很容易的定位到问题线程。

  • Sy 内核空间占用CPU百分比,sy高的时候,如果是程序问题导致,基本是因为线程上下文切换造成的。

我的经验

平时怎么定位 CPU 使用率高的原因的?

其实网上有个教程和方法,我简述我的分析过程。

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

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

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

进一步查看具体日志:

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

希望本文对大家有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值