Ich verwende Log4J in meiner Anwendung für die Protokollierung. Zuvor verwendete ich einen Debug-Aufruf wie:
Option 1:
logger.debug("some debug text");
Einige Links deuten jedoch darauf hin, dass es besser ist, isDebugEnabled()
zuerst zu überprüfen , z.
Option 2:
boolean debugEnabled = logger.isDebugEnabled();
if (debugEnabled) {
logger.debug("some debug text");
}
Meine Frage lautet also " Verbessert Option 2 die Leistung in irgendeiner Weise? ".
Denn in jedem Fall hat das Log4J-Framework die gleiche Prüfung für debugEnabled. Für Option 2 kann es vorteilhaft sein, wenn wir mehrere Debug-Anweisungen in einer einzelnen Methode oder Klasse verwenden, wobei das Framework die isDebugEnabled()
Methode nicht mehrmals (bei jedem Aufruf) aufrufen muss. In diesem Fall wird die isDebugEnabled()
Methode nur einmal aufgerufen. Wenn Log4J für die Debug-Ebene konfiguriert ist, wird die isDebugEnabled()
Methode tatsächlich zweimal aufgerufen :
- Im Fall der Zuweisung eines Werts zur debugEnabled-Variablen und
- Wird tatsächlich von der Methode logger.debug () aufgerufen.
Ich denke nicht, dass wenn wir mehrere logger.debug()
Anweisungen in Methode oder Klasse schreiben und debug()
Methode gemäß Option 1 aufrufen , dies für das Log4J-Framework im Vergleich zu Option 2 isDebugEnabled()
ein Overhead ist. Da es sich um eine sehr kleine Methode handelt (in Bezug auf Code), könnte dies der Fall sein sei ein guter Kandidat für Inlining.
toString()
nur bei Bedarf auf.Da in Option 1 die Nachrichtenzeichenfolge eine Konstante ist, ist es absolut kein Vorteil, die Protokollierungsanweisung mit einer Bedingung zu versehen. Wenn die Protokollanweisung dagegen debuggen aktiviert ist, werden Sie zweimal ausgewertet, einmal in der
isDebugEnabled()
Methode und einmal indebug()
Methode. Die Kosten für das AufrufenisDebugEnabled()
liegen in der Größenordnung von 5 bis 30 Nanosekunden, was für die meisten praktischen Zwecke vernachlässigbar sein sollte. Daher ist Option 2 nicht wünschenswert, da sie Ihren Code verschmutzt und keinen anderen Gewinn bietet.quelle
Die Verwendung von
isDebugEnabled()
ist reserviert, wenn Sie Protokollnachrichten durch Verketten von Strings erstellen:In Ihrem Beispiel gibt es jedoch keinen Geschwindigkeitsgewinn, da Sie nur einen String protokollieren und keine Vorgänge wie die Verkettung ausführen. Daher fügen Sie Ihrem Code nur Aufblähung hinzu und erschweren das Lesen.
Ich persönlich verwende die Aufrufe im Java 1.5-Format in der String-Klasse wie folgt:
Ich bezweifle, dass es viel Optimierung gibt, aber es ist einfacher zu lesen.
Beachten Sie jedoch, dass die meisten Protokollierungs-APIs eine sofort einsatzbereite Formatierung bieten: slf4j bietet beispielsweise Folgendes:
das ist noch einfacher zu lesen.
quelle
In Java 8 müssen Sie nicht verwenden
isDebugEnabled()
, um die Leistung zu verbessern.https://logging.apache.org/log4j/2.0/manual/api.html#Java_8_lambda_support_for_lazy_logging
quelle
Kurzversion: Sie können auch die boolesche Prüfung isDebugEnabled () durchführen.
Gründe:
1- Wenn komplizierte Logik / String concat. Wird Ihrer Debug-Anweisung hinzugefügt, ist die Prüfung bereits vorhanden.
2- Sie müssen die Anweisung nicht selektiv in "komplexe" Debug-Anweisungen aufnehmen. Alle Aussagen sind auf diese Weise enthalten.
3- Wenn Sie log.debug aufrufen, wird vor dem Protokollieren Folgendes ausgeführt:
if(repository.isDisabled(Level.DEBUG_INT))
return;
Dies entspricht im Wesentlichen dem Aufruf des Protokolls. oder Katze. isDebugEnabled ().
JEDOCH! Dies ist, was die log4j-Entwickler denken (wie es in ihrem Javadoc ist und Sie sollten es wahrscheinlich befolgen.)
Dies ist die Methode
Dies ist der Javadoc dafür
quelle
Wie andere bereits erwähnt haben, ist die Verwendung der Guard-Anweisung nur dann wirklich nützlich, wenn das Erstellen der Zeichenfolge ein zeitaufwändiger Aufruf ist. Spezifische Beispiele hierfür sind, dass beim Erstellen der Zeichenfolge ein verzögertes Laden ausgelöst wird.
Es ist erwähnenswert, dass dieses Problem mithilfe von Simple Logging Facade für Java oder (SLF4J) - http://www.slf4j.org/manual.html vermieden werden kann . Dies ermöglicht Methodenaufrufe wie:
Dadurch werden die übergebenen Parameter nur in Zeichenfolgen konvertiert, wenn das Debuggen aktiviert ist. SLF4J ist, wie der Name schon sagt, nur eine Fassade, und die Protokollierungsaufrufe können an log4j weitergeleitet werden.
Sie könnten auch sehr leicht "Ihre eigene" Version davon rollen.
Hoffe das hilft.
quelle
Option 2 ist besser.
An sich verbessert es die Leistung nicht. Es stellt jedoch sicher, dass die Leistung nicht beeinträchtigt wird. Hier ist wie.
Normalerweise erwarten wir logger.debug (someString);
Aber normalerweise, wenn die Anwendung wächst, wechselt man viele Hände, besonders Anfänger, wie man sehen kann
logger.debug (str1 + str2 + str3 + str4);
und dergleichen.
Selbst wenn die Protokollstufe auf ERROR oder FATAL eingestellt ist, kommt es zu einer Verkettung von Zeichenfolgen! Wenn die Anwendung viele Nachrichten auf DEBUG-Ebene mit Zeichenfolgenverkettungen enthält, ist ein Leistungseinbruch besonders bei JDK 1.4 oder niedriger erforderlich. (Ich bin nicht sicher, ob spätere Versionen von jdk intern stringbuffer.append () ausführen).
Deshalb ist Option 2 sicher. Sogar die String-Verkettungen treten nicht auf.
quelle
Wie bei @erickson kommt es darauf an. Wenn ich mich recht erinnere,
isDebugEnabled
ist bereits in derdebug()
Methode von Log4j gebaut.Solange Sie in Ihren Debug-Anweisungen keine teuren Berechnungen durchführen, z. B. Schleifen für Objekte, Berechnungen durchführen und Zeichenfolgen verketten, ist dies meiner Meinung nach in Ordnung.
wäre besser als
quelle
Für eine einzelne Zeile verwende ich eine ternäre Nachricht innerhalb der Protokollierungsnachricht. Auf diese Weise mache ich keine Verkettung:
ej:
Ich mache:
Aber für mehrere Codezeilen
ej.
Ich mache:
quelle
Da diese Antwort wahrscheinlich von vielen Personen bei der Suche nach log4j2 angezeigt wird und fast alle aktuellen Antworten log4j2 oder die jüngsten Änderungen nicht berücksichtigen, sollte dies hoffentlich die Frage beantworten.
log4j2 unterstützt Lieferanten (derzeit eigene Implementierung, laut Dokumentation ist jedoch geplant, die Lieferantenschnittstelle von Java in Version 3.0 zu verwenden). Mehr dazu lesen Sie im Handbuch . Auf diese Weise können Sie die Erstellung teurer Protokollnachrichten einem Lieferanten zuweisen, der die Nachricht nur erstellt, wenn sie protokolliert werden soll:
quelle
Es verbessert die Geschwindigkeit, da es üblich ist, Zeichenfolgen im Debug-Text zu verketten, was teuer ist, z.
quelle
Seit der Log4j- Version
2.4
(oderslf4j-api 2.0.0-alpha1
) ist es viel besser, eine fließende API (oder Java 8-Lambda-Unterstützung für die verzögerte Protokollierung ) zu verwenden, die dasSupplier<?>
Argument der Protokollnachricht unterstützt , das von Lambda angegeben werden kann :ODER mit slf4j API:
quelle
Wenn Sie Option 2 verwenden, führen Sie eine schnelle Boolesche Prüfung durch. In Option eins führen Sie einen Methodenaufruf durch (Verschieben von Daten auf den Stapel) und führen dann eine Boolesche Prüfung durch, die immer noch schnell ist. Das Problem, das ich sehe, ist die Konsistenz. Wenn einige Ihrer Debug- und Info-Anweisungen eingeschlossen sind und andere nicht, handelt es sich nicht um einen konsistenten Codestil. Außerdem könnte später jemand die Debug-Anweisung so ändern, dass sie verkettete Zeichenfolgen enthält, was immer noch ziemlich schnell ist. Ich habe festgestellt, dass wir beim Einpacken der Debug- und Info-Anweisung in eine große Anwendung und beim Profilieren ein paar Prozentpunkte an Leistung eingespart haben. Nicht viel, aber genug, um die Arbeit wert zu machen. Ich habe jetzt ein paar Makros in IntelliJ eingerichtet, um automatisch umschlossene Debug- und Info-Anweisungen für mich zu generieren.
quelle
Ich würde empfehlen, Option 2 für die meisten de facto zu verwenden, da es nicht sehr teuer ist.
Fall 1: log.debug ("eine Zeichenfolge")
Fall 2: log.debug ("eine Zeichenfolge" + "zwei Zeichenfolgen" + object.toString + object2.toString)
Zum Zeitpunkt des Aufrufs muss die Parameterzeichenfolge in log.debug (sei es CASE 1 oder Case2) ausgewertet werden. Das ist es, was jeder unter "teuer" versteht. Wenn Sie die Bedingung 'isDebugEnabled ()' vor sich haben, müssen diese nicht ausgewertet werden. Hier wird die Leistung gespeichert.
quelle
Ab 2.x ist in Apache Log4j diese Prüfung integriert, sodass dies
isDebugEnabled()
nicht mehr erforderlich ist.debug()
Wenn Sie einfach a ausführen, werden die Nachrichten unterdrückt, wenn sie nicht aktiviert sind.quelle
Mit Log4j2 können Sie Parameter in eine Nachrichtenvorlage formatieren, ähnlich wie in Log4j2
String.format()
, wodurch die Notwendigkeit entfälltisDebugEnabled()
.Beispiel für einfache log4j2.properties:
quelle