Sam's Notes | Sam Blog

梦想还是要有的,万一实现了呢

0%

JVM线上调优(二) CPU调优

主要内容

JVM调优的工具和方法 深入浅出,分如下3节介绍,可以解决实际问题。
本章解决java线上CPU调优

  • 工具介绍
    公欲善其事,必先利其器
    jps, jstat, jmap, jhat, jstack, jinfo, JConsole, VisualVM, Eclipse Memory Analyzer(MAT)

  • CPU调优
    还我CPU

  • Memory调优
    吃我的吐出来

更新历史


定位线程

  • TOP命令查看到CPU的占用情况
    TOP –> P : 按CPU使用率排序

  • 具体线程
    Java是一个多线程应用,进程是由多个线程构成的,上面看到的是这个进程的CPU占用率,导致这个进程CPU偏高的是其中某个或某几个线程,因而我们需要找到这些线程。
    ps命令查看指定进程的线程情况

    1
    ps -mp <pid> -o THREAD,tid,time


    线程tid为 9100 的线程,CPU占用率达到了99.8%, 就是这个线程的问题。

  • 具体线程方法2

    1
    top -H -p <pid>

具体分析

请出 jstack 分析具体线程。

** 注意: 进制转换 **
ps命令查看到的线程ID 9100 是十进制,jstack 命令输出的线程ID可能是十六进制,查看 nid 的值, 如果是十六进制, 使用如下命令转换

1
2
╰─$ printf "%x\n" 9100
238c

然后使用 jstack 定位具体的问题

1
2
3
4
5
6
╰─$ jstack 9078|grep 238c -A 15
"Thread-0" #10 prio=5 os_prio=0 tid=0x00007fbea0821800 nid=0x238c runnable [0x00007fbe8bbfa000]
java.lang.Thread.State: RUNNABLE
at com.xxx.xxx.MyClassLoader$1.run(MyClassLoader.java:19)

...

最后结合源码检查就ok。

或者可以dump当前进程完整thread,排名前面的都是耗时较多的,问题可能就是他们其中之一

1
jstack 9078 > thread_dump.txt

辅助

vmstat

可以实时显示系统的虚拟内存、进程、CPU活动等信息

1
2
# 每隔1秒采样一次,共采样5次。
vmstat 1 5
  • 输出结果解释
    vmstat命令的输出结果包括以下几个部分:
    进程(procs)
    r:运行队列中的进程数。
    b:等待IO的进程数。
    内存(memory)
    swpd:使用的交换空间(单位:KB)。
    free:空闲内存(单位:KB)。
    buff:用于缓冲的内存(单位:KB)。
    cache:用于缓存的内存(单位:KB)。
    交换(swap)
    si:每秒从交换区写到内存的数据量。
    so:每秒从内存写到交换区的数据量。
    IO
    bi:每秒从磁盘读取的数据量(单位:块)。
    bo:每秒写入磁盘的数据量(单位:块)。
    系统(system)
    in:每秒的中断次数。
    cs:每秒的上下文切换次数。
    CPU
    us:用户进程使用CPU的时间比例。
    sy:系统进程使用CPU的时间比例。
    id:CPU空闲时间比例。

  • 样例值参考

    指标 样例值 状态 诊断说明
    cs (Context Switch) 90万 ~ 109万 极度异常 正常服务器通常在几千或一两万。百万级别意味着 CPU 几乎没在干活,全在忙着在线程之间切换。
    in (Interrupts) 44万 ~ 54万 极度异常 中断数极高,通常伴随着高频的系统调用或时钟中断。
    r (Running) 7 ~ 15 高排队 等待 CPU 时间片的线程数较多,说明 CPU 资源已经过饱和。
    sy (System) 25 ~ 29 过高 依然占据了近 1/3 的算力。