2010-08-10 15 views
7

Ho letto abbastanza spesso, che l'uso di try-catch è piuttosto lento rispetto al normale codice. Ora mi chiedo se il numero di eccezioni rilevate influisce sul rendimento del codice oppure no.Il numero di eccezioni rilevate influisce sulle prestazioni del codice try?

Così è

try{ 
    ... 
} 
catch(StrangeException e){ 
    ... 
} 

più lento rispetto

try{ 
    ... 
} 
catch(StrangeException e){ 
    ... 
} 
catch(MysteriousException e){ 
    ... 
} 
catch(FrighteningException e){ 
    ... 
} 

?

Ovviamente mi riferisco solo al codice nella clausola try e se non viene rilevata alcuna eccezione.

risposta

2

Il costo di un blocco try/catch è essenzialmente zero se non vengono effettivamente lanciate eccezioni. Il numero di clausole di cattura non fa differenza.

Il costo di eccezioni si verifica solo quando in realtà vengono gettati:

  • Costruire l'oggetto eccezione è molto costoso, a causa del costo del passo fillInStackTrace(). Questo deve creare e inizializzare una struttura dati contenente i dettagli chiave di tutti i frame sullo stack di thread corrente. Nel peggiore dei casi, ce ne potrebbero essere migliaia.

  • Le eccezioni di lancio e di cattura sono un po 'costose. Nel peggiore dei casi, la JVM deve fare l'equivalente di un instanceof per ogni clausola catch di ciascun blocco try/catch. Questo è dove avere molte clausole catch potrebbe fare la differenza per le prestazioni.

0

L'unico modo per conoscere con certezza le domande relative alle prestazioni è testarlo attentamente.

Ma se mi chiedeste di scommettere, scommetterei che non fa alcuna differenza misurabile, e che anche usando try/catch rispetto a non usarlo non fa molta differenza, a patto che non vengono effettivamente lanciate eccezioni (che non dovrebbero essere, nel caso normale).

5

Quello che hai letto è sbagliato. Un notevole overhead si verifica quando un'eccezione viene effettivamente generata - normalmente il sovraccarico è minimo quando non ci sono eccezioni. Un'eccezione a questo è che potrebbe influire sull'inlining, quindi se si dispone di un metodo che viene chiamato in un ciclo chiuso, è possibile che non si inline se ha dei blocchi try/catch. Allo stesso modo solo la presenza di codice può influenzare la coerenza della cache e altre sottigliezze ... ma nella maggior parte dei casi questo non sarà un collo di bottiglia.

Non credo di aver visto in una situazione di vita reale in cui non vengono generate eccezioni, ma il tentativo di rilevare blocchi è stato un problema di prestazioni. Come sempre, dovresti scrivere il codice più pulito che puoi e testarne il rendimento. Considerare solo la possibilità di piegare il design ideale per motivi di prestazioni quando si ha una chiara dimostrazione che le modifiche sono entrambe necessarie e utili.

+1

Come corollario, se hai il codice in cui il volume di eccezioni è un problema di prestazioni, molto probabilmente non utilizzi le eccezioni correttamente. –

+0

@John: concordato - anche se in questo caso l'OP ha esplicitamente dichiarato di essere interessato alle prestazioni in cui non vengono * lanciate eccezioni *. –

0

Per quanto posso ricordare dai miei vecchi giorni di lettura bytecode, il numero di clausole catch non ha alcun effetto significativo sulle prestazioni.

Quando si verifica un'eccezione, la JVM sa passare alla sequenza bytecode che implementa la clausola catch osservando l'eccezione in una tabella che fa parte del codice byte della classe. In generale, ogni metodo che intercetta un'eccezione è associato a una tabella delle eccezioni che fa parte del file di classe, insieme al codice byte del metodo. La tabella delle eccezioni contiene una voce per ogni eccezione che viene rilevata da ciascun blocco try. Ogni voce contiene: i punti iniziale e finale, l'offset del programma (PC) all'interno della sequenza di bytecode da saltare a, e un indice di pool costante del tipo di eccezione (cioè la classe) che viene catturato.

Se viene generata un'eccezione durante l'esecuzione di un metodo, la JVM ricerca nella corrispondenza la tabella delle eccezioni per una corrispondenza. Si verifica una corrispondenza se il PC corrente si trova nell'intervallo specificato dalla voce e se la classe di eccezione generata è quella specificata dalla voce (o è una sottoclasse di essa).

Quindi la risposta alla tua domanda dipende da come questa ricerca viene implementata. Per quanto ne so, la JVM cerca nella tabella nello stesso ordine in cui le voci appaiono nella tabella e quando viene trovata la prima corrispondenza, la JVM imposta il PC nella nuova posizione e continua l'esecuzione da lì.

Penso che a meno che non ci siano MOLTE eccezioni non si noterebbe un impatto significativo, ma se fossi in te e se questo problema fosse fondamentale per me, lo farei un benchmark sulla particolare JVM che stai usando .

Ori

0

mi ricordo di aver letto che qualcuno ha testato questo e ha scoperto che le prestazioni in realtà è stato influenzato in questo caso, anche se probabilmente non ci si aspetterebbe che fosse. (Una rapida ricerca su Google non lo mostra, quindi non ricordo quanti blocchi di catch esistessero o quale versione di Java è stata trovata.)

Problemi correlati