CPU 占用过高,如何排查?

本文介绍了一种排查CPU占用过高的方法,包括使用top命令找出高CPU使用率的进程,通过ps命令定位具体线程,并利用jstack进一步分析Java程序中的问题。

测试代码

死循环,一直打印数字


package com.test.high;

public class CPUHigh {
    public static void main(String[] args) {
        long count = 0;
        while (true){
            System.out.println(count++);
        }
    }
}

排查步骤

top 查看,哪一个进程 CPU 使用高

%Cpu(s): 10.8 us, 12.3 sy,  0.0 ni, 76.8 id,  0.0 wa,  0.0 hi,  0.2 si,  0.0 st
KiB Mem :  1863020 total,  1266812 free,   224332 used,   371876 buff/cache
KiB Swap:  2097148 total,  2097148 free,        0 used.  1485416 avail Mem

   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
  2291 root      20   0 2692708  47004  12396 S  41.2  2.5   0:55.56 java
  2059 root      20   0  158944   5780   4428 S   3.3  0.3   0:07.02 sshd
  2333 root      20   0  161972   2196   1552 R   0.7  0.1   0:00.03 top
    13 root      rt   0       0      0      0 S   0.3  

可以看到 pid = 2291 这个进程 CPU 使用率高。

ps -ef | grep java

如果能确定是 java 程序可以直接使用 jps -l,查找哪一个 java 进程。

[root@s101 program]# ps -ef | grep java
root       2291   2062 40 20:59 pts/1    00:01:18 java com.test.high.CPUHigh
root       2349   2025  0 21:02 pts/0    00:00:00 grep --color=auto java

ps -mp pid -o THREAD,tid,time

查看该进程中哪一个线程占用 CPU 时长较长。

[root@s101 program]# ps -mp 2291 -o THREAD,tid,time
USER     %CPU PRI SCNT WCHAN  USER SYSTEM    TID     TIME
root     40.2   -    - -         -      -      - 00:01:24
root      0.0  19    - futex_    -      -   2291 00:00:00
root     39.5  19    - -         -      -   2292 00:01:22
root      0.0  19    - futex_    -      -   2293 00:00:00
root      0.0  19    - futex_    -      -   2294 00:00:00
root      0.0  19    - futex_    -      -   2295 00:00:00
root      0.0  19    - futex_    -      -   2296 00:00:00
root      0.0  19    - futex_    -      -   2297 00:00:00
root      0.0  19    - futex_    -      -   2298 00:00:00
root      0.1  19    - futex_    -      -   2299 00:00:00
root      0.0  19    - futex_    -      -   2300 00:00:00
root      0.0  19    - futex_    -      -   2301 00:00:00
root      0.4  19    - futex_    -      -   2302 00:00:00

可以看到 tid = 2292 这个线程占用 CPU 较长。
tid = 2292 = 0x8f4

jstack pid | grep tid(hex) -A100

注意: jstack 中 tid 使用的是十六进制。

[root@s101 program]# jstack 2291 | grep 8f4 -A100
"main" #1 prio=5 os_prio=0 tid=0x00007f903404b800 nid=0x8f4 runnable [0x00007f903e385000]
   java.lang.Thread.State: RUNNABLE
        at java.io.FileOutputStream.writeBytes(Native Method)
        at java.io.FileOutputStream.write(FileOutputStream.java:326)
        at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
        at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
        - locked <0x00000000e38431e0> (a java.io.BufferedOutputStream)
        at java.io.PrintStream.write(PrintStream.java:482)
        - locked <0x00000000e3805138> (a java.io.PrintStream)
        at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
        at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
        at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
        - locked <0x00000000e38050f0> (a java.io.OutputStreamWriter)
        at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
        at java.io.PrintStream.newLine(PrintStream.java:546)
        - locked <0x00000000e3805138> (a java.io.PrintStream)
        at java.io.PrintStream.println(PrintStream.java:751)
        - locked <0x00000000e3805138> (a java.io.PrintStream)
        at com.test.high.CPUHigh.main(CPUHigh.java:7)

"VM Thread" os_prio=0 tid=0x00007f90340d1800 nid=0x8f7 runnable

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f903405e000 nid=0x8f5 runnable

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f9034060000 nid=0x8f6 runnable

"VM Periodic Task Thread" os_prio=0 tid=0x00007f903413d000 nid=0x8fe waiting on condition

JNI global references: 5

References

  1. cpu 占用过高排查
### 生产环境中CPU占用排查工具及性能分析 在生产环境中,当遇到CPU占用的问题时,可以使用多种工具进行排查和性能分析。以下是一些常用的工具及其功能: 1. **top** `top` 是一个实时显示系统中各个进程资源占用情况的工具,可以快速查看哪些进程占用了较CPU资源。通过该工具,可以初步定位到CPU占用的进程PID。[^2] ```bash top ``` 2. **ps** `ps` 命令可以结合其他参数查看具体线程的CPU占用情况,并按CPU占用排序。例如,可以通过以下命令找到CPU占用的线程ID。 ```bash ps -mp <PID> -o THREAD,tid,time | sort -rn ``` 3. **jstack** `jstack` 是JDK自带的工具,用于生成Java进程的线程转储信息。通过线程转储,可以分析出哪个线程导致了CPU占用。将线程ID转换为十六进制后,可以在线程转储中查找对应的信息。 ```bash jstack <PID> | grep <TID_in_hex> -A 30 ``` 4. **jconsole** 和 **jvisualvm** 这两个工具是JDK自带的图形化监控工具,可以实时监控Java应用的性能指标,包括CPU、内存、线程等。它们适合用于开发环境或测试环境中的详细性能分析。[^1] 5. **Arthas** Arthas 是阿里巴巴开源的一款Java诊断工具,支持在线诊断运行中的Java应用。通过`dashboard`命令可以查看当前系统的资源使用情况,而`thread`命令可以查看线程的CPU占用情况并定位具体的业务代码。[^4] ```bash java -jar arthas-boot.jar dashboard thread -n 3 ``` 6. **strace** `strace` 是一个用于跟踪进程系统调用和信号的工具。虽然它主要用于非Java程序的调试,但在某些情况下也可以帮助分析Java程序的行为。[^2] ```bash strace -p <PID> ``` 7. **perf** `perf` 是Linux内核自带的一个性能分析工具,可以用来分析CPU热点函数。通过与`perf report`结合使用,可以找到消耗CPU最多的函数。 ```bash perf record -g -p <PID> perf report ``` 8. **sysdig** `sysdig` 是一个强大的系统级监控和故障排除工具,可以捕获和分析系统调用。它提供了更丰富的功能,适用于复杂的性能分析场景。 ```bash sysdig -p "%proc.name %cpu" evt.type=cpu ``` 9. **htop** `htop` 是`top`的增强版,提供了更友好的界面和更多的功能,如交互式进程管理、树状视图等。[^3] ```bash htop ``` ### 示例代码:模拟CPU的Java程序 以下是一个简单的Java程序,用于模拟CPU占用的情况。可以通过上述工具对其进行分析。 ```java public class CpuHighDemo { public static void main(String[] args) { while (true) { // 空循环导致CPU占用 } } } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值