关于Eclipse Java调试器条件断点低效率的问题

时间:2010-05-14 11:22:50

标签: java eclipse performance debugging

我只是在Eclipse的调试器中通过断点标准设置一个条件断点,条件温和效率低 - 检查HashMap的值列表(8个元素)是否包含Double.NaN。这导致了极其显着的性能下降 - 大约五分钟后,我放弃了。

然后我将条件粘贴到完全相同的行中的if语句中,在if中放入一个noop,并在那里设置一个正常的断点。该断点在预期的20-30秒内达到。

条件断点有什么特别之处才能让性能受到重视,或者Eclipse的实现是否有点愚蠢?看起来他们可以很容易地在幕后做同样的事情(粘贴在if和编译中)。

3 个答案:

答案 0 :(得分:2)

有趣!

我使用了一些源代码来查看有和没有条件断点的情况。附在下面。

使用条件断点在调试器中执行:
持续时间:1210623微秒

在没有条件断点的情况下在调试器中执行:
持续时间:24微秒

恕我直言,VM没有停止,因为第二个线程继续并排运行。 Eclipse必须将断点代码注入当前类。也许它会在每次调用时都这样做,也许它必须在每次调用时重新编译该类。检查Eclipse源代码将揭示正在发生的事情。

我在C#和Visual Studio中运行条件断点的经验更糟糕:我的胃口感觉是那里的事情差了几个数量级。

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);
}


}

答案 1 :(得分:0)

断点传递了多少次?可能是调试器必须在触发之前多次测试断点条件。我不知道它是如何实现的,但如果调试器执行条件的效率远低于正常编译的Java,我也不会感到惊讶。也许只是因为它得到了JIT的较少关注。也许它根本没有完全编译成Java并被解释。

答案 2 :(得分:0)

Eclipse需要停止整个JVM以检查断点条件。这就是为什么它会让你付出代价。