2010-02-03 3 views
18

Alcune routine intensive della CPU diventano notevolmente più lente quando vengono eseguite attraverso un debugger. Perchè è questo?Perché il codice Java rallenta nel debugger?

Attualmente sto usando solo IntelliJ per eseguire il codice in esecuzione in JBoss. Quando avvio JBoss, utilizzo queste opzioni:

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

C'è un modo per accelerare l'esecuzione? O per accelerare certe esecuzioni di metodi che non ho bisogno di passare?


Aggiornamento: Sembra se non scavalcare/nelle routine di CPU intensive (vale a dire: Basta eseguire fino un punto di interruzione impostato subito dopo la routine), quindi il tempo di esecuzione è come se non in un debugger.

risposta

40

Alcune routine intensive della CPU diventano notevolmente più lente quando vengono eseguite attraverso un debugger. Perchè è questo?

Poiché JITter non ottimizza il codice tanto (spesso, per niente) quando il debug è abilitato.

+0

Grazie. Puoi approfondire questo processo di ottimizzazione? –

+12

La maggior parte delle macchine virtuali non legge un bytecode, esegue l'istruzione equivalente e ripete. È troppo lento. Ciò che invece fanno è prendere il bytecode nel suo complesso, convertirlo in codice nativo equivalente e quindi eseguire il codice nativo. Se stai usando un debugger (e quindi dicendo che potresti scavalcarlo a un certo punto), stai ponendo dei vincoli piuttosto pesanti su ciò che può effettivamente essere fatto. –

7

Dipende anche dallo "stile breakpoint". Per esempio. avere watchpoint su variabili o mettere breakpoint a livello di interfaccia (il debugger si fermerà su tutte le implementazioni dei metodi quando vengono eseguiti) spesso rallenta notevolmente il tempo di elaborazione.

+3

Grazie mille per questo. Stavo perdendo un sacco di tempo perché, e non riuscivo a capire perché, le mie sessioni di debug remoto su un processo che stava funzionando bene per molte iterazioni iniziarono ad essere costantemente lente. Non ho mai pensato fino a quando ho letto questo che potrebbe essere influenzato dai punti di interruzione che avevo impostato (non i punti di interruzione colpiti, ma appena impostato). Disabilitando tutti i miei punti di interruzione e riattivando in modo più selettivo il problema è stato risolto. – sudocode

+1

Sembra che il numero di punti di interruzione da solo possa essere un fattore. Ho sperimentato un po 'con l'abilitazione/disabilitazione. Nel mio ambiente corrente, l'intero processo (dall'avvio in poi) diventa molto lento quando sono abilitati> 39 punti di interruzione. Non importa quali. – sudocode

5

Durante il debug, oltre all'esecuzione dell'applicazione, si esegue anche un debugger.

Il codice è compilato in modalità di debug con simboli di metadati sulle variabili locali e altre informazioni a livello di origine. Il debugger legge per sapere quale riga di codice sorgente corrisponde all'istruzione corrente. Il processo è chiamato debugging simbolico. I simboli memorizzati aumentano le dimensioni del codice e interpretarli aumenta il tempo di esecuzione.

Alcuni debugger in realtà interpretano il codice al volo, che è quasi sempre un grande successo in termini di prestazioni.

ulteriori informazioni sulla modalità di compilazione di debug di Java, che viene eseguito da javac e include informazioni di debug nei file di classe: Java Language Compiler Options. Ad esempio: -g genera tutte le informazioni di debug, incluse le variabili locali.

+0

+1 poiché questo non accade mai a me (connessione lenta a db) è più probabile – stacker

+0

Quando dici che il codice è compilato in modalità debug, ti riferisci alla JVM che compila il codice byte Java al codice macchina nativo? –

0

Suggerimento: in IDEA è possibile utilizzare ALT + F9 per eseguire dove è posizionato il cursore anziché impostare un punto di interruzione aggiuntivo.

ho trovato anecdotally che il debug diventa molto lento nel IDEA se siete a piedi attraverso il codice dove c'è un sacco di dati accessibili dalla pila. Non dimenticare, IDEA raccoglie questi dati (qualsiasi cosa attualmente in ambito lessicale) e te li presenta come un albero di oggetti per cercare se stai "guardando" o meno e lo fa a ogni passo successivo (forse ricrea l'albero ogni volta?).

Ciò è particolarmente evidente quando, ad esempio, esiste una grande raccolta come variabile di istanza dell'oggetto "corrente".

2

È necessario considerare che un altro programma, il debugger, è collegato al programma e lo sta osservando per cose come le eccezioni. Sta inoltre monitorando la linea corrente per reagire ai breakpoint o alle interruzioni richieste dall'utente (come una richiesta di pausa o una condizione di visualizzazione).

1

Il debug del codice ottimizzato prodotto dalla JIT sarebbe molto difficile, perché non esiste una relazione diretta tra una serie di istruzioni native e una linea di codice Java come esiste una relazione tra un intervallo di bytecode Java e un linea di codice Java.

Quindi, l'interruzione di una funzione nel debugger forza la JVM a deottimizzare il metodo che si sta attraversando. L'hotspot non genera affatto codice nativo e interpreta semplicemente il bytecode del metodo.

Prima di JDK 1.4.1 iniziando con il debug attivato costretto la JVM di utilizzare solo l'interprete: http://java.sun.com/products/hotspot/docs/whitepaper/Java_Hotspot_v1.4.1/Java_HSpot_WP_v1.4.1_1002_3.html#full

0

Se si utilizza Java 5, il parametro per il debug è:

-agentlib: JDWP = trasporti = dt_socket, server = y, sospendere = n, indirizzo =

e prima di Java 5

-Xdebug -Xrunjdwp: trasporti = dt_socket, indirizzo = 5005, server = y, sospendere = n