Why does the JDWP agent cause significant deoptimization during stress tests?

62 Views Asked by At

I've been conducting a stress test using async-profiler to generate a flame graph and happened to notice that, when JDWP is attached, there are frequent cases of deoptimization consuming a significant amount of CPU time.

Here is the flame graph with JDWP attached:

-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005

enter image description here

Here is the flame graph without JDWP attached: enter image description here

I tried adding the -XX:+PrintCompilation parameter but only observed minimal deoptimization logs.

I also attempted to use JFR (Java Flight Recorder), but I didn't receive any deoptimization events: enter image description here

This has been quite perplexing for me because when using async-profiler, I can observe a significant amount of CPU time being consumed by deoptimization, but when using JFR, deoptimization seems to disappear.

And by the way, this holds true for both Java 8 and Java 17.

> /Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home/bin/java -version
java version "1.8.0_371"
Java(TM) SE Runtime Environment (build 1.8.0_371-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.371-b11, mixed mode)

> /Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home/bin/java -version
openjdk version "17.0.3" 2022-04-19 LTS
OpenJDK Runtime Environment Zulu17.34+19-CA (build 17.0.3+7-LTS)
OpenJDK 64-Bit Server VM Zulu17.34+19-CA (build 17.0.3+7-LTS, mixed mode, sharing)

Edit:

After looking through the mailing list and JDK bug lists with the keyword deoptimization, I have found two cases reported before that are very similar:

Running the code provided by JDK-8243615 without JDWP, I do reproduce the problem:

// javac UnstableIfTest.java
// java -XX:PerMethodRecompilationCutoff=4 UnstableIfTest
public class UnstableIfTest {
    static int compute(double x)
    {
        return (int) (Math.sin(x) + Math.cos(x));
    }
    static void hotMethod(int iteration)
    {
        if (iteration < 20) {
            compute(78.3);
        }
        else if (iteration < 40) {
            compute(78.3);
        }
        else if (iteration < 60) {
            compute(78.3);
        }
        else if (iteration < 80) {
            compute(78.3);
        } else if (iteration < 100) {
            compute(78.3);
        } else {
            compute(78.3);
        }
    }
    static void hotMethodWrapper(int iteration)
    {
        int count = 100_000;
        for (int i = 0; i < count; i++) {
            hotMethod(iteration);
        }
    }
    public static void main(String[] args)
    {
        for (int k = 0; k < 100; k++) {
            long start = System.nanoTime();
            hotMethodWrapper(k + 1);
            System.out.println("iteration " + k + ": " + (System.nanoTime() - start) / 1_000_000 + "ms");
        }
    }
}

enter image description here

So for now,my guess is this:there is a bug in JIT that causes a lot of unnecessary deoptimization sometimes, but not sure if there' any relation between JDWP, async-profiler, and JFR.

0

There are 0 best solutions below