2012-03-20 17 views
9

Stavo creando un logger nella mia java-app (con NetBeans come IDE) quando improvvisamente ho visto un avviso che diceva: "Uso inefficiente della concatenazione di stringhe nel logger".Uso inefficiente della concatenazione di stringhe

Il mio codice oringinal è

srcLogger.getLogger().log(Level.INFO,"UploadBean.doUpload completado [" + file.getName() + "]\n"); 

ma NetBeans suggerito di convertirlo in un modello di dare questo codice (quello che un "modello" si intende qui?):

srcLogger.getLogger().log(Level.INFO, "UploadBean.doUpload completado [{0}]\n", file.getName()); 

Qual è la differenza tra questi due modi di concatenazione, non ho mai usato quest'ultimo però.

Cheers.

risposta

11

Ignorerei l'avviso (e lo spengo se è spento, se possibile). La concatenazione non è così inefficiente, perché i compilatori moderni lo sostituiscono con un'implementazione efficiente basata su StringBuilder (lo vedrai se guardi il codice byte del classfile).

La sostituzione suggerita non concatena Stringhe ma richiede un'ulteriore elaborazione per analizzare il modello e unirlo con i parametri.

Netbeans, questo è un cattivo consiglio.

Questo vale per Java 1.5+. Le vecchie versioni di Java (possono) creare un sacco di inutilizzati String casi durante la concatenazione ..

+3

Per disattivare l'avviso (in NetBeans 7.2.1): Preferenze -> Editor -> Suggerimenti -> Registrazione -> Concatenazione di stringhe nel registratore. La descrizione dice " Non è efficiente dal punto di vista delle prestazioni concatenare le stringhe nei messaggi del logger. È preferibile utilizzare un messaggio modello con segnaposti che vengono sostituiti da valori concreti solo quando il messaggio verrà realmente registrato." –

+0

In realtà ti sei perso uno dei maggiori vantaggi, aggiungerò una risposta anche se è tardi :) –

+3

Ma l'avvertimento è un'inefficienza dovuta alla concatenazione che viene sempre eseguita anziché eseguirla solo in base al livello di registrazione corrente nel caso in cui di usare il ['log (livello livello, string msg, oggetto [] params)'] (https://docs.oracle.it/javase/8/docs/api/java/util/logging/Logger.html # log-java.util.logging.Level-java.lang.String-java.lang.Object: metodo A-). – Adam

4

Poiché le stringhe sono immutabili in Java, quando si concatenano gli oggetti String si crea effettivamente un oggetto completamente nuovo. L'utilizzo di qualcosa come il modello suggerito da Netbeans o StringBuilder impedisce di dover creare tutti quegli oggetti intermedi, che richiedono tempo e risorse.

+0

Tranne che i moderni compilatori Java useranno un StringBuilder per te, non è questo il motivo. –

11

La vera vittoria qui è che non c'è bisogno di fare qualsiasi caso la movimentazione a tutti (sia la concatenazione o il modello di espansione) string il logger è configurato per non accedere al livello INFO.

Cioè, il registratore può decidere di non fare nulla senza doversi avvicinare a nessun tipo di manipolazione delle stringhe.

1

Un modello significa esattamente questo, si suppone che sia un modello per una stringa, piuttosto che una stringa stessa. L'idea è che il {0} bit verrà sostituito con il primo argomento che appare dopo di esso nell'elenco (file.getName()). Questo segue lo schema del metodo Stringformat.

Non ho visto alcun test delle prestazioni per verificare se questo sia più veloce o meno. Come altre risposte hanno sottolineato, lasciandolo così com'è, non sarà particolarmente lento in quanto uno StringBuilder verrà utilizzato al posto di una normale stringa dal compilatore. Tuttavia, come sottolinea @dty, penso che dovrebbe essere più veloce nel caso in cui il livello di registrazione sia impostato in modo tale che l'istruzione non sia effettivamente registrata, poiché non c'è lavoro richiesto per costruire la stringa da produrre. Inoltre, poiché l'intera stringa del template è un singolo letterale, questo verrà aggiunto al pool String dal compilatore. Ciò significa che tutte le istanze di questo particolare String puntano alla stessa istanza effettiva, quindi se l'istruzione non viene effettivamente registrata, non è nemmeno necessario allocare memoria per archiviare questa stringa, ma semplicemente la ricerca, che dovrebbe essere più efficiente.

1

L'avviso che si ottiene da NetBeans fornisce la giustificazione minima per evitare la concatenazione nell'istruzione del registro.

  1. I messaggi di registro che non vengono inviati al registro non vengono creati quando si utilizza lo stile modello. Puoi anche ottimizzare lo stile un po 'di più evitando le chiamate al metodo nella lista degli argomenti.

Ma ci sono altri motivi per scegliere di utilizzare lo stile modello per il messaggio di registro.

a. Evita possibili spese generali di concat. Come altri hanno sottolineato, questo non è un grosso problema con il recente javac.

b. Il tuo codice è meglio preparato per l'internazionalizzazione/localizzazione. Mentre si può pensare ... questo codice non avrà mai bisogno di quel livello di preoccupazione ... è sorprendente quanto lontano il codice vada dopo che è stato inizialmente scritto.

16

Il messaggio non si riferisce al costo della concatenazione di stringhe in sé. Le altre risposte hanno assolutamente ragione quando dicono che verrà usato un StringBuilder.

Il motivo principale per utilizzare un modello di messaggio è perché l'elaborazione viene eseguita solo quando viene visualizzato il livello di registrazione!

cerchiamo di utilizzare questi due esempi:

srcLogger.getLogger().log(Level.INFO,"UploadBean.doUpload completado [" + file.getName() + "]\n"); 
srcLogger.getLogger().log(Level.INFO, "UploadBean.doUpload completado [{0}]\n", file.getName()); 

Con livello INFO debug on: Entrambi hanno per ottenere il nome del file da File, entrambi hanno per aggiornare la stringa, generarne uno nuovo, visualizzarla.

Con livello di debug INFO off: La seconda risposta passa attraverso il nome dell'oggetto File (che è una query semplice), il metodo log() controlla il livello INFO e restituisce immediatamente. Nessuna elaborazione String eseguita affatto!

Ora immagina che invece di un semplice file.getName() stessimo registrando un oggetto più complesso, uno che aveva bisogno di un sacco di concatenazione di stringhe nel metodo toString(). Registrando tali oggetti direttamente, nessuna di tali elaborazioni viene eseguita. toString() non viene mai chiamato a meno che non venga visualizzato il livello di debug.

Quindi il modello di messaggio non è più efficiente nel caso in cui venga visualizzata la registrazione, ma è enormemente più efficiente (in particolare nei casi di registrazione non banale) quando la registrazione non viene visualizzata. Uno degli obiettivi della registrazione dovrebbe essere che se la registrazione è disattivata ha il minimo impatto possibile sulle prestazioni del sistema.

Problemi correlati