Java 调优 CPU 占用过高
本文最后更新于 947 天前,其中的信息可能已经有所发展或是发生改变。

前置条件

  1. 示例代码
    public class Pretend {
    
        //计算pi
        public static void pi() {
            double pi = 0;
            for (int i = 0; true; i++) {
                if (i % 2 == 0) {
                    pi = pi + ((double) 1 / (2 * i + 1));
                } else {
                    pi = pi - ((double) 1 / (2 * i + 1));
                }
                System.out.println(pi * 4);
            }
        }
    
        public static void main(String[] args) {
            pi();
        }
    }
    
  2. 编译javac Pretend.java
  3. 运行java Pretend

调优过程

  1. 定位占用CPU过高的进程top,得到PID为9932
    top - 06:51:10 up 21:33,  2 users,  load average: 0.31, 0.22, 0.54
    Tasks: 118 total,   2 running, 116 sleeping,   0 stopped,   0 zombie
    %Cpu(s): 47.8 us, 48.2 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  4.0 si,  0.0 st
    KiB Mem :   995676 total,   226200 free,   248908 used,   520568 buff/cache
    KiB Swap:  2097148 total,  2097148 free,        0 used.   570820 avail Mem
    
       PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
      9932 root      20   0 2251060  32360  12452 S 57.8  3.3   0:07.11 java
      8504 root      20   0  159224   6216   4724 S 33.2  0.6   6:36.70 sshd
      9913 root      20   0       0      0      0 S  0.7  0.0   0:00.25 kworker/0:0
        32 root      39  19       0      0      0 R  0.3  0.0   0:00.86 khugepaged
      9942 root      20   0  162096   2220   1548 R  0.3  0.2   0:00.03 top
         1 root      20   0  128152   6780   4172 S  0.0  0.7   0:06.46 systemd
    
  2. 定位占用CPU过高的线程top -H -p 9932,得到PID为9933
    top - 06:52:48 up 21:35,  2 users,  load average: 1.08, 0.52, 0.62
    Threads:  10 total,   0 running,  10 sleeping,   0 stopped,   0 zombie
    %Cpu(s): 29.8 us, 29.4 sy,  0.0 ni, 39.5 id,  0.0 wa,  0.0 hi,  1.3 si,  0.0 st
    KiB Mem :   995676 total,   223460 free,   251648 used,   520568 buff/cache
    KiB Swap:  2097148 total,  2097148 free,        0 used.   568080 avail Mem
    
        PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
        9933 root      20   0 2251060  32360  12452 S 40.7  3.3   0:46.77 java
        9932 root      20   0 2251060  32360  12452 S  0.0  3.3   0:00.00 java
        9934 root      20   0 2251060  32360  12452 S  0.0  3.3   0:00.10 VM Thread
        9935 root      20   0 2251060  32360  12452 S  0.0  3.3   0:00.00 Reference Handl
        9936 root      20   0 2251060  32360  12452 S  0.0  3.3   0:00.00 Finalizer
        9937 root      20   0 2251060  32360  12452 S  0.0  3.3   0:00.00 Signal Dispatch
        9938 root      20   0 2251060  32360  12452 S  0.0  3.3   0:00.27 C2 CompilerThre
        9939 root      20   0 2251060  32360  12452 S  0.0  3.3   0:00.05 C1 CompilerThre
        9940 root      20   0 2251060  32360  12452 S  0.0  3.3   0:00.00 Service Thread
        9941 root      20   0 2251060  32360  12452 S  0.0  3.3   0:00.06 VM Periodic Tas
    
  3. 将线程号十进制改十六进制printf "0x%x\n" 9933,输出0x26cd
  4. 定位代码块jstack -l 9932,找到nid=0x26cd如下
    "main" #1 prio=5 os_prio=0 tid=0x00007f631004b800 nid=0x26cd runnable [0x00007f6318e06000]
       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 <0x00000000f5d69a18> (a java.io.BufferedOutputStream)
            at java.io.PrintStream.write(PrintStream.java:482)
            - locked <0x00000000f5d612f8> (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 <0x00000000f5d69a58> (a java.io.OutputStreamWriter)
            at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
            at java.io.PrintStream.newLine(PrintStream.java:546)
            - eliminated <0x00000000f5d612f8> (a java.io.PrintStream)
            at java.io.PrintStream.println(PrintStream.java:779)
            - locked <0x00000000f5d612f8> (a java.io.PrintStream)
            at Pretend.calcPi(Pretend.java:11)
            at Pretend.main(Pretend.java:16)
       Locked ownable synchronizers:
            - None
    "VM Thread" os_prio=0 tid=0x00007f63100cb800 nid=0x26ce runnable
    "VM Periodic Task Thread" os_prio=0 tid=0x00007f631011e800 nid=0x26d5 waiting on condition
    JNI global references: 5
    
如果觉得本文对您有帮助,记得收藏哦~
上一篇
下一篇