java - 为什么条件调试这么慢?

标签 java debugging

我注意到,当我使用条件断点进行调试时,执行速度会大大减慢。我已经知道了一段时间,现在想了解原因。究竟发生了什么导致执行如此缓慢?我知道正在添加条件,但如果我自己添加条件,我不会减慢执行速度。

例如,假设我们有以下代码。假设我们添加了一个条件断点a=i。让我们将条件设置为 i==10000。

public class Main {

    public static void main(String[] args) {
        int a = 0;

        for (int i = 0; i<100000; i++) {
                a = i;  //put breakpoint here (if i == 10000)
        }
        System.out.println("Done! a=" + a);
    }
}

现在让我们自己编写条件。

public class Main {

    public static void main(String[] args) {
        int a = 0;

        for (int i = 0; i<100000; i++) {
            if (i == 10000)
                a = i; //put a NON-conditional breakpoint here
            else a = i;
        }
        System.out.println("Done! a=" + a);
    }
}

为什么这两者的运行时间差别如此之大?为什么第一个这么慢?

如果您想知道,我在 Linux (Ubuntu) 上使用 Oracle-JDK-8。 我使用 Eclipse 和 IntelliJ 得到了相同的结果。


实验结果

我在多个 IDE 上运行了第一个案例,看看是否有区别。这是结果

智能:

~9 秒到达断点

~90 秒完成(包括最初的 9 秒)

eclipse :

~9 秒到达断点

~90 秒完成(包括最初的 9 秒)

Netbeans:

~ 12 秒到达断点

~ 190 秒完成(包括最初的 12 秒)

所以 IntelliJ 和 Eclipse 差不多,但 Netbeans 慢得多。

第二个示例几乎可以在所有 IDE 上立即运行,所以我没有做实验。 (但我确实将这三个都运行了,看看是否有任何延迟,没有一个。)

最佳答案

我还没有实现 IDE、调试器或 JVM,所以我不能确定事情是否完全按照我将在这里解释的那样进行。

但是。当代码使用调试器运行时,JVM 会解释代码直到遇到断点。然后它停止并调用调试器 (IDE)。

JVM 不支持条件断点,因此 IDE 使用“hack”来完成此功能。 IDE 只是添加了一个正常的断点。每次遇到断点时,IDE 都会在提醒用户之前评估表达式本身,如果评估结果为假,则发送“继续”命令。

现在检查您的示例。在第二个示例中,JVM 只执行一次这样的调用。在第一个示例中,这是完成 100000 次。每次 JVM 调用调试器并等待,直到它解释条件并向 JVM 发送命令“继续”(正如您在调试代码时可以手动执行的那样)。显然100000>1,所以这个过程需要时间。

编辑:接下来的 2 段仅作为未经证实的假设编写。 OP的实验表明它们是错误的。但是我不想完全删除它们:让我们将其解释为 Eclipse 团队的理论思考和改进建议。

关于 IntelliJ 与 Eclipse。同样,这只是假设。我看到 IntelliJ 在条件断点上的工作速度要慢得多。我也知道 IntelliJ 中的条件断点不支持 java 编程语言的某些元素(例如匿名内部类)。我可以得出结论,IntelliJ 可能会使用 Java 以外的语言(例如 groovy 或其他语言)编译您编写的代码作为断点的条件。这可能会导致额外的性能下降。

我也知道 eclipse 不使用标准的 javac 编译器,而是使用它自己的编译器,它有很多很酷的特性。我可以假设 eclipase 中的条件断点可能被编译为代码的一部分,即实际上编译器会自动创建代码,例如您的示例编号 2。如果这是正确的,则此类代码的运行速度几乎与包含手动编写的代码一样快 if 语句。

关于java - 为什么条件调试这么慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24661062/

相关文章:

debugging - 彩色 grep 的等价物是什么?

javascript - 如何使用 javascript sdk 调试 facebook connect 应用程序和 xfbml 解析?

java - JSCEP-第三个参数类型错误。发现 : 'org.spongycaSTLe.pkcs.PKCS10CertificationRequest' , 需要: 'org.bouncycaSTLe.pkcs.PKCS10CertificationRequest'

java - SecurityContextHolder 可以跨用户共享吗

java - Java 堆栈, "contains"问题

java - 扩展 Eclipse JDT

java - Eclipse NullPointerException 我似乎无法修复

java - 将数据保存在内存中和将其写入驱动器之间是否存在最佳点?

c - 全局缓冲区溢出,Windows 环境

mysql - MySQL 中的多个左连接