Korzystam z Log4J w mojej aplikacji do logowania. Wcześniej używałem połączenia debugowania, takiego jak:
Opcja 1:
logger.debug("some debug text");
ale niektóre linki sugerują, że lepiej isDebugEnabled()
najpierw sprawdzić , na przykład:
Opcja 2:
boolean debugEnabled = logger.isDebugEnabled();
if (debugEnabled) {
logger.debug("some debug text");
}
Więc moje pytanie brzmi: „ Czy opcja 2 poprawia wydajność w jakikolwiek sposób? ”.
Ponieważ w każdym przypadku środowisko Log4J ma takie samo sprawdzenie pod kątem debugEnabled. W przypadku opcji 2 może być korzystne, jeśli używamy wielu instrukcji debugowania w pojedynczej metodzie lub klasie, gdzie środowisko nie musi wywoływać isDebugEnabled()
metody wiele razy (przy każdym wywołaniu); w tym przypadku wywołuje isDebugEnabled()
metodę tylko raz, a jeśli Log4J jest skonfigurowany do debugowania poziomu, w rzeczywistości wywołuje isDebugEnabled()
metodę dwukrotnie:
- W przypadku przypisania wartości zmiennej debugEnabled, oraz
- W rzeczywistości wywoływany przez metodę logger.debug ().
Nie sądzę, że jeśli napiszemy wiele logger.debug()
instrukcji w metodzie lub klasie i wywołujemy debug()
metodę zgodnie z opcją 1, to jest to narzut dla frameworka Log4J w porównaniu z opcją 2. Ponieważ isDebugEnabled()
jest to bardzo mała metoda (pod względem kodu), może bądź dobrym kandydatem do inklinacji.
toString()
tylko w razie potrzeby.Ponieważ w opcji 1 ciąg komunikatu jest stały, nie ma absolutnie żadnego zysku na zawijaniu instrukcji rejestrowania warunkiem, przeciwnie, jeśli instrukcja dziennika jest włączona do debugowania, będziesz oceniać dwa razy, raz w
isDebugEnabled()
metodzie i raz wdebug()
metoda. Koszt wywołaniaisDebugEnabled()
jest rzędu od 5 do 30 nanosekund, co powinno być nieistotne dla większości praktycznych celów. Dlatego opcja 2 nie jest pożądana, ponieważ zanieczyszcza twój kod i nie zapewnia żadnych innych korzyści.źródło
Używanie
isDebugEnabled()
jest zarezerwowane do tworzenia wiadomości dziennika poprzez łączenie ciągów:Jednak w twoim przykładzie nie ma przyrostu prędkości, ponieważ po prostu rejestrujesz ciąg znaków i nie wykonujesz operacji takich jak konkatenacja. Dlatego dodajesz do swojego kodu rozdęcie i utrudniasz czytanie.
Osobiście używam wywołań w formacie Java 1.5 w klasie String w następujący sposób:
Wątpię, by było wiele optymalizacji, ale łatwiej to odczytać.
Należy jednak pamiętać, że większość interfejsów API do rejestrowania oferuje takie formatowanie od razu po wyjęciu z pudełka: na przykład slf4j zapewnia:
co jest jeszcze łatwiejsze do odczytania.
źródło
W Javie 8 nie musisz używać
isDebugEnabled()
do poprawy wydajności.https://logging.apache.org/log4j/2.0/manual/api.html#Java_8_lambda_support_for_lazy_logging
źródło
Krótka wersja: Równie dobrze możesz sprawdzić wartość logiczną isDebugEnabled ().
Powody:
1 - jeśli skomplikowana logika / ciąg konkat. jest dodawany do wyciągu debugowania, będziesz już mieć czek na miejscu.
2- Nie trzeba selektywnie dołączać instrukcji do „złożonych” instrukcji debugowania. Wszystkie oświadczenia są uwzględniane w ten sposób.
3- Wywołanie log.debug wykonuje następujące czynności przed zalogowaniem:
if(repository.isDisabled(Level.DEBUG_INT))
return;
Jest to w zasadzie to samo, co dziennik połączeń. lub kot. isDebugEnabled ().
JEDNAK! Tak myślą deweloperzy log4j (tak jak w ich javadoc i prawdopodobnie powinieneś przejść przez to.)
To jest metoda
To jest javadoc
źródło
Jak wspomnieli inni, użycie instrukcji guard jest naprawdę przydatne tylko wtedy, gdy utworzenie łańcucha jest czasochłonnym wywołaniem. Konkretnymi przykładami tego są przypadki, gdy utworzenie łańcucha spowoduje pewne leniwe ładowanie.
Warto zauważyć, że problemu tego można uniknąć, używając Simple Logging Facade for Java lub (SLF4J) - http://www.slf4j.org/manual.html . Umożliwia to wywołania metod, takie jak:
Spowoduje to konwersję przekazanych parametrów na ciągi, tylko jeśli włączone jest debugowanie. SLF4J, jak sama nazwa wskazuje, jest tylko fasadą, a wywołania rejestrowania można przekazać do log4j.
Możesz również bardzo łatwo „stworzyć własną” wersję tego.
Mam nadzieję że to pomoże.
źródło
Opcja 2 jest lepsza.
Sam w sobie nie poprawia wydajności. Ale zapewnia wydajność nie pogarsza się. Oto jak.
Zwykle oczekujemy logger.debug (someString);
Ale zwykle, gdy aplikacja rośnie, zmienia wiele rąk, szczególnie początkujących programistów, widać
logger.debug (str1 + str2 + str3 + str4);
i tym podobne.
Nawet jeśli poziom dziennika jest ustawiony na ERROR lub FATAL, konkatenacja ciągów się dzieje! Jeśli aplikacja zawiera wiele komunikatów poziomu DEBUG z łączeniem łańcuchów, to z pewnością wymaga wydajności, szczególnie w przypadku Jdk 1.4 lub niższej. (Nie jestem pewien, czy późniejsze wersje jdk internall wykonują jakiś stringbuffer.append ()).
Właśnie dlatego Opcja 2 jest bezpieczna. Nawet konkatenacje łańcuchów nie zdarzają się.
źródło
Podobnie jak @erickson, zależy. O
isDebugEnabled
ile pamiętam, jest już wbudowany wdebug()
metodę Log4j.Dopóki nie wykonujesz drogich obliczeń w instrukcjach debugowania, takich jak pętla na obiektach, wykonywanie obliczeń i łączenie ciągów, moim zdaniem jest w porządku.
byłoby lepiej jak
źródło
W przypadku pojedynczego wiersza używam trójki w komunikacie rejestrowania. W ten sposób nie wykonuję konkatenacji:
ej:
Ja robię:
Ale dla wielu wierszy kodu
ej.
Ja robię:
źródło
Ponieważ wiele osób prawdopodobnie przegląda tę odpowiedź podczas wyszukiwania log4j2 i prawie wszystkie aktualne odpowiedzi nie uwzględniają log4j2 ani ostatnich zmian w nim, mam nadzieję, że powinno to odpowiedzieć na pytanie.
log4j2 obsługuje Dostawcy (obecnie ich własna implementacja, ale zgodnie z dokumentacją planowane jest użycie interfejsu dostawcy Java w wersji 3.0). Możesz przeczytać o tym trochę więcej w instrukcji . Pozwala to umieścić kosztowne tworzenie wiadomości dziennika u dostawcy, który tworzy wiadomość tylko wtedy, gdy ma być zalogowany:
źródło
Poprawia szybkość, ponieważ często łączy się ciągi w tekście debugowania, co jest kosztowne, np .:
źródło
Od wersji Log4j
2.4
(lubslf4j-api 2.0.0-alpha1
) znacznie lepiej jest używać płynnego API (lub obsługi lambda Java 8 dla leniwego rejestrowania ), obsługującejSupplier<?>
argument komunikatu dziennika, który może podać lambda :LUB z API slf4j:
źródło
Jeśli użyjesz opcji 2, przeprowadzasz szybkie sprawdzenie logiczne. W opcji pierwszej wykonujesz wywołanie metody (wypychanie rzeczy na stos), a następnie sprawdzanie boolowskie, które jest nadal szybkie. Problem, który widzę, to spójność. Jeśli niektóre z instrukcji debugowania i informacji są opakowane, a niektóre nie, to nie jest to spójny styl kodu. Dodatkowo ktoś może później zmienić instrukcję debugowania, aby zawierała łańcuchy konkatenacji, co wciąż jest dość szybkie. Przekonałem się, że kiedy wypakowaliśmy debugowanie i instrukcję informacyjną w dużej aplikacji i profilowaliśmy ją, zaoszczędziliśmy kilka punktów procentowych wydajności. Niewiele, ale wystarczająco, by było warto. Mam teraz kilka ustawień makr w IntelliJ, aby automatycznie generować opakowane instrukcje debugowania i informacyjne.
źródło
Polecam korzystanie z Opcji 2 jako de facto dla większości, ponieważ nie jest ona bardzo droga.
Przypadek 1: log.debug („jeden ciąg”)
Przypadek 2: log.debug („jeden ciąg” + „dwa ciąg” + object.toString + object2.toString)
W momencie wywołania któregokolwiek z nich należy ocenić łańcuch parametrów w log.debug (CASE 1 lub Case2). To właśnie wszyscy rozumieją jako „drogi”. Jeśli masz przed nim warunek „isDebugEnabled ()”, nie trzeba ich oceniać, w którym zapisywana jest wydajność.
źródło
Począwszy od wersji 2.x, Apache Log4j ma tę funkcję wbudowaną, więc
isDebugEnabled()
nie jest już konieczne. Po prostu wykonaj a,debug()
a wiadomości nie zostaną włączone, jeśli nie zostaną włączone.źródło
Log4j2 pozwala sformatować parametry w szablon wiadomości, podobnie jak
String.format()
, dzięki czemu nie trzeba tego robićisDebugEnabled()
.Przykładowe proste log4j2.properties:
źródło