本文最后更新于 947 天前,其中的信息可能已经有所发展或是发生改变。
前置条件
- 示例代码
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(); } } - 编译
javac Pretend.java - 运行
java Pretend
调优过程
- 定位占用CPU过高的进程
top,得到PID为9932top - 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 - 定位占用CPU过高的线程
top -H -p 9932,得到PID为9933top - 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 - 将线程号十进制改十六进制
printf "0x%x\n" 9933,输出0x26cd - 定位代码块
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