views:

416

answers:

6

Some CPU intensive routines get dramatically slower when run through a debugger. Why is this?

Currently I'm just using IntelliJ to step through code running in JBoss. When I start JBoss, I use these options:

set JAVA_OPTS=-Xms512m -Xmx1024m -XX:MaxPermSize=256m -Xdebug -Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=n %JAVA_OPTS%

Is there a way to speed up the execution? Or to speed up certain method executions that I don't need to step through?


Update: Seems if I don't step over/into the CPU intensive routines (ie: Just run til a breakpoint set right after the routine), then the execution time is as if not in a debugger.

+12  A: 

Some CPU intensive routines get dramatically slower when run through a debugger. Why is this?

Because the JITter won't optimize code as much (often, not at all) when debugging is enabled.

Anon.
Thanks. Can you elaborate on this optimization process?
Marcus
Most virtual machines don't read a bytecode, execute the equivalent instruction, and repeat. That's just way too slow. What they instead do is take the bytecode as a whole, convert it into equivalent native code, and then execute the native code. If you're running under a debugger (and thus saying that you might step over it at some point), you're placing some pretty hefty constraints on what can actually be done.
Anon.
A: 

It also depends on the "breakpoints-style". E.g. having watchpoints on variables or putting breakpoints on interface level (debugger will stop on all method-implementations when they're executed) often dramatically slows down the process time.

manuel aldana
+4  A: 

When debugging, in addition to running your application, you are also running a debugger.

The code is compiled in debug mode with metadata symbols about local variables and other source-level information. The debugger reads to know which line of source code corresponds with the current instruction. The process is called symbolic debugging. The stored symbols increase code size and interpreting them increases execution time.

Some debuggers actually interpret the code on the fly, which is almost always a major performance hit.

More information about Java's debug compilation mode, which is performed by javac and includes debug information in class files: Java Language Compiler Options. For example: -g generates all debugging information, including local variables.

Abboq
+1 since this happens never to me (slow connection to db) it's most probable
stacker
When you say the code is compiled in debug mode, you're referring to the JVM compiling the Java byte code to native machine code?
Marcus
A: 

Top Tip: in IDEA you can use ALT+F9 to run to where you have the cursor placed rather than set an extra breakpoint.

I have found anecdotally that debugging becomes very slow in IDEA if you are walking through code where there is a lot of data accessible from the stack. Don't forget, IDEA collects this data (anything currently in the lexical scope) and presents it up to you as a tree of objects to browse whether you are "watching" or not and does this at every subsequent step (maybe it re-creates the tree each time?).

This is especially apparent when, for example, there is a large collection as an instance variable of the "current" object.

oxbow_lakes
+1  A: 

You do need to consider that another program -- the debugger -- is hooked in to your program and is watching it for things like exceptions. It's also monitoring the line it's on so that it can stop at break points. The debugger likely also is checking for user requested interrupts -- IE, you click the pause button (if available).

Frank V
A: 

Debugging the optimized code produced by the JIT would be very hard, because there isn't a direct relationship between a range of native instructions and a line of Java code like there is a relationship between a range of Java bytecode and a line of Java code.

So breaking into a function in the debugger forces the JVM to deoptimize the method you are stepping through. Hotspot doesn't generate native code at all and just interprets the bytecode of the method.

Prior to JDK 1.4.1 starting with debugging enabled forced the JVM to only use the interpreter: http://java.sun.com/products/hotspot/docs/whitepaper/Java_Hotspot_v1.4.1/Java_HSpot_WP_v1.4.1_1002_3.html#full

Dan Berindei