Eclipse Question Java Debugger Conditional Breakpoints Inefficiency

I just set a conditional breakpoint in the Eclipse debugger with a mildly ineffective breakpoint-standard conditional - checks if a list of HashMap values ​​(8 elements) contains Double.NaN. This resulted in an extremely noticeable slowdown in performance - after about five minutes I gave up.

Then I'll copy that condition into an if statement on the same line, put a noop in the if, and set a normal breakpoint there. This breakpoint was hit in the expected 20-30 seconds.

Is there something special about conditional breakpoints making the performance value useful, or does Eclipse's implementation look just silly? It looks like they could just simply do the same thing (insert into an if and compile) behind the scenes.

+2


a source to share


3 answers


Interesting!

I played with some source code to see what happens with and without a conditional breakpoint. Attached below.

Execution in debugger with conditional breakpoint:
Duration: 1210623 microseconds

Execution in debugger without conditional breakpoint:
Duration: 24 microseconds



IMHO VM is not stopped because the second thread continues to run side by side. Eclipse needs to inject the breakpoint code into the current class. Perhaps it does this on every call, and perhaps it has to recompile the class on every call. Checking the Eclipse sources would reveal exactly what is going on.

My experience of executing conditional breakpoints in C # and Visual Studio is even worse: my belly feeling is orders of magnitude worse.

public class BreakPointPlay {

static int breakpointHits;

static volatile int modifiedBySecondThread;

static volatile boolean stopped;

public static void main(String[] args) throws InterruptedException {

    Thread secondThread = startSecondThread();

    final long LOOPS = 1000;
    long counter = 0;
    long start = System.nanoTime();
    for (long i = 0; i < LOOPS; i++) {

        // place breakpoint here and set the condition to the
        // #breakPointCondition() method.
        counter += i;

    }
    long stop = System.nanoTime();
    long nanos = stop - start;
    long micros = nanos / 1000;

    System.out.println("\nDuration: " + micros + " microseconds\n");

    printInfo();
    stopped = true;

    secondThread.join();
}

private static Thread startSecondThread() {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            while(! stopped){
                modifiedBySecondThread++;
            }
        }
    });
    thread.start();
    return thread;
}

private static void printInfo() {
    printModifiedBySecondThread();
    printThread();
    printClassLoader();
    printStackTrace();
    printModifiedBySecondThread();
}

private static void printStackTrace() {
    Exception exception = new Exception();
    exception.fillInStackTrace();
    exception.printStackTrace(System.out);
}

private static void printModifiedBySecondThread() {
    print("modifiedBySecondThread " + modifiedBySecondThread);
}

public static boolean breakPointCondition(){
    breakpointHits++;
    if(breakpointHits == 100){
        printInfo();
    }
    return false;
}

private static void printClassLoader() {
    print("ClassLoader " + new BreakPointPlay().getClass().getClassLoader());
}

private static void printThread() {
    print("Thread " + Thread.currentThread());
}

private static void print(String msg){
    System.out.println(msg);
}


}

      

+2


a source


How many times has a breakpoint passed? The debugger may have had to check the breakpoint condition many times before running it. I don't know how this is implemented, but I wouldn't be surprised if the debugger's execution of this condition is much less efficient than normally compiled Java. Perhaps it's just that he's getting less attention from the JIT. It may not even be fully compiled for Java and interpreted.



0


a source


Eclipse has to stop the whole JVM in order to check the breakpoint condition. This is why it costs you.

0


a source







All Articles