23

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.

Marcus Leon
  • 55,199
  • 118
  • 297
  • 429

6 Answers6

44

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.
  • 58,739
  • 8
  • 81
  • 86
  • Thanks. Can you elaborate on this optimization process? – Marcus Leon Feb 03 '10 at 21:58
  • 14
    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. Feb 03 '10 at 22:02
7

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
  • 15,650
  • 9
  • 43
  • 50
  • 3
    Thanks so much for this. I was losing loads of time because, and couldn't figure out why, my remote debug sessions on a process which had been performing fine for many iterations started to run consistently slow. I never thought till I read this that it might be impacted by breakpoints I had set (not breakpoints hit, but just set). Disabling all my breakpoints and re-enabling more selectively sorted the problem. – ewan.chalmers May 23 '11 at 10:42
  • 1
    It appears that number of breakpoints alone can be a factor. I experimented a bit with enable/disable. In my current environment, the whole process (from startup onwards) becomes very slow whenever >39 breakpoints are enabled. Doesn't matter which ones. – ewan.chalmers May 23 '11 at 10:57
5

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,101
  • 1
  • 10
  • 21
2

You do need to consider that another program -- the debugger -- is hooked into your program and is watching it for things like exceptions. It's also monitoring the current line in order to react to breakpoints or user requested interruptions (like a pause request or watch condition).

Frank V
  • 25,141
  • 34
  • 106
  • 144
1

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
  • 133,303
  • 56
  • 317
  • 449
1

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
  • 7,054
  • 3
  • 41
  • 48