【问题标题】:Question About Eclipse Java Debugger Conditional Breakpoints Inefficiency关于 Eclipse Java 调试器条件断点效率低下的问题
【发布时间】:2010-05-14 11:22:50
【问题描述】:
我只是在 Eclipse 的调试器中设置了一个条件断点,断点标准的条件有点低效 - 检查 HashMap 的值列表(8 个元素)是否包含 Double.NaN。这导致性能显着下降 - 大约五分钟后,我放弃了。
然后我将条件复制粘贴到完全相同的行的 if 语句中,在 if 中放置一个 noop,并在那里设置一个正常的断点。该断点在预期的 20-30 秒内到达。
条件断点有什么特别之处可以使性能受到影响,还是 Eclipse 的实现有点愚蠢?似乎他们可以很容易地在幕后做完全相同的事情(粘贴在 if 中并编译)。
【问题讨论】:
标签:
java
eclipse
performance
debugging
【解决方案1】:
有趣!
我使用了一些源代码来查看使用和不使用条件断点会发生什么。附在下面。
在带有条件断点的调试器中执行:
持续时间: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);
}
}
【解决方案2】:
断点经过了多少次?可能是调试器在触发之前必须多次测试断点条件。我不知道它是如何实现的,但如果调试器执行条件的效率比正常编译的 Java 低很多,我不会感到惊讶。也许只是它从 JIT 中得到的关注较少。也许它甚至根本没有完全编译成 Java,而是被解释了。
【解决方案3】:
Eclipse 需要停止整个 JVM 以检查断点条件。这就是它让您付出代价的原因。