Hi all,

TL;DR We observe a significant performance degradation after stepping over
in a debugger. By the looks of it, the interpreter only mode is entered and
never left due to this change:

https://github.com/openjdk/jdk11u/commit/dbb9eb5b9c3ddcbcfaae8ac4ca21760c9c99a15c#diff-fa220f091e99b08a3a20869c780e3529b2fee843acbc3b5748443794c4582f5d

I hope this is the correct mailing list for this. I would open an OpenJDK
bug, but I don't have an account.

To reproduce, debug the following snippet with jdb:

public class StepOver {
    public static void main(String[] args) throws Exception {
        System.out.println(); // set a breakpoint here, and step over
        System.out.println(); // press Resume when suspended here
        double[] ySeries = new double[100_000];
        for (int i = 0; i < ySeries.length; i++) {
            ySeries[i] = Math.sin(i / 20) * Math.pow(10, -21);
        }
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < ySeries.length; i++) {
            String.valueOf(ySeries[i]);
        }
        System.out.println("elapsed time: " + (System.currentTimeMillis() -
startTime));
    }
}

Breakpoint at line 3, run the snippet, step over, continue execution.
Observe execution time is very slow (8.5 sec in my case, vs. normally 0.1
sec). Omitting the step over, execution time is similar to normal
(non-debug) execution time.

We observe this bug with OpenJDK 11.0.16 and OpenJDK 17.0.4.

I've opened a RHEL bugzilla ticket, if that helps:
https://bugzilla.redhat.com/show_bug.cgi?id=2138897

I don't observe the problem with this change:

diff --git a/src/hotspot/share/prims/jvmtiEventController.cpp
b/src/hotspot/share/prims/jvmtiEventController.cpp
index 38de6383cc..22d0f40c97 100644
--- a/src/hotspot/share/prims/jvmtiEventController.cpp
+++ b/src/hotspot/share/prims/jvmtiEventController.cpp
@@ -523,7 +523,7 @@
JvmtiEventControllerPrivate::recompute_thread_enabled(JvmtiThreadState
*state) {
     JvmtiEnvThreadStateIterator it(state);
     for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets =
it.next(ets)) {
       any_env_enabled |= recompute_env_thread_enabled(ets, state);
-      has_frame_pops |= ets->has_frame_pops();
+      //has_frame_pops |= ets->has_frame_pops();
     }
   }

If I add prints to entering the interpreter only code below, I see the mode
is entered after step over, but left only after the program finishes
execution:

diff --git a/src/hotspot/share/prims/jvmtiEventController.cpp
b/src/hotspot/share/prims/jvmtiEventController.cpp
index 38de6383cc..a9764303c9 100644
--- a/src/hotspot/share/prims/jvmtiEventController.cpp
+++ b/src/hotspot/share/prims/jvmtiEventController.cpp
@@ -542,8 +542,12 @@
JvmtiEventControllerPrivate::recompute_thread_enabled(JvmtiThreadState
*state) {

   if (should_be_interp != is_now_interp) {
     if (should_be_interp) {
+      printf("entering interp only mode\n");
+      fflush(stdout);
       enter_interp_only_mode(state);
     } else {
+      printf("leaving interp only mode\n");
+      fflush(stdout);
       leave_interp_only_mode(state);
     }
   }

Sorry if I'm interpreting the code wrong and "interpreter only mode" means
something else other than, there is no JIT compiler. But judging from the
really slow execution, I assume that is the problem.

Any chance this can be looked into? Any ideas for a workaround that can be
implemented in a debugger (in our case, Eclipse, same problem as jdb)? Is
there already an open OpenJDK ticket?

Best regards and thanks,
Simeon

Reply via email to