我只是在Eclipse的调试器中通过断点标准设置一个条件断点,条件温和效率低 - 检查HashMap的值列表(8个元素)是否包含Double.NaN。这导致了极其显着的性能下降 - 大约五分钟后,我放弃了。
然后我将条件粘贴到完全相同的行中的if语句中,在if中放入一个noop,并在那里设置一个正常的断点。该断点在预期的20-30秒内达到。
条件断点有什么特别之处才能让性能受到重视,或者Eclipse的实现是否有点愚蠢?看起来他们可以很容易地在幕后做同样的事情(粘贴在if和编译中)。
答案 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以检查断点条件。这就是为什么它会让你付出代价。