天天看點

Log4j vs. Logback 性能比較Inside

看過源碼有段時間了,對logback中對判定是否記錄一條日志記錄的優化印象比較深刻,整理如下,希望對你有所幫助。

java的logger架構有一個重要的層級(hierarchy)的概念,按約定,是通過小數點來差別父子關系的,也就是名字為“x.y”的logger是“x.y.z”logger的parent。

hierachy的命名規則:

<dl></dl>

<dt>named hierarchy</dt>

<dd>a logger is said to be an ancestor of another logger if its name followed by a dot is a prefix of the descendant logger name. a logger is said to be a parent of a child logger if there are no ancestors between itself and the descendant logger.</dd>

這樣做的好處是我們可以靈活的指定不同logger的log level和appender targets。

logger

name

assigned

level

inherited

added

appenders

additivity

flag

output targets

comment

root

warn

a1

not applicable

the root logger is anonymous but can be accessed with the logger.getrootlogger() method.

there is no default appender attached to root.

x

info

a-x

true

a1, a-x

appenders of "x" and root.

x.y

none

a-xy

false

a1, a-x, a-xy

appenders in "x.y" , and its parents "x" and root. log level is info which is inherited from "x"

x.y.z

debug

a-xyz

appenders of "x.y.z". becuase its parent "x.y" addivitity is false, so no more appenders will be added

因為這個hierachy的關系,在做日志輸出時,logger不僅要check自己是不是滿足輸出條件,還要周遊其所有的additivity為非false的parent,看parents們能不能輸出日志。

下圖是一個filter和handler在logger hierarchy中運作的示意圖,其運作邏輯是:

when a message is passed to a <code>logger</code>, the message is passed through the <code>logger</code>'s <code>filter</code>, if the <code>logger</code>has a <code>filter</code> set. the <code>filter</code> can either accept or reject the message. if the message is accepted, the message is forwarded to the <code>handler</code>'s set on the <code>logger</code>. if no <code>filter</code> is set, the message is always accepted.

if a message is accepted by the <code>filter</code>, the message is also forwarded to the <code>handler</code>'s of the parent<code>logger</code>'s. however, when a message is passed up the hierarchy, the message is not passed through the<code>filter</code>'s of the parent <code>logger</code>'s. the <code>filter</code>'s are only asked to accept the message when the message is passed directly to the <code>logger</code>, not when the message comes from a child <code>logger</code>.

Log4j vs. Logback 性能比較Inside

log4j中是怎樣處理這個hierachy的呢?

Log4j vs. Logback 性能比較Inside

上面的實作有兩個比較損耗性能的地方:

1)當日志不需要輸出時,new loggingevent()純屬是做無用功。

2)當logger的日志自身不滿足輸出條件是,周遊parents也是在做無用功。

logback中是怎樣做優化的呢?

Log4j vs. Logback 性能比較Inside

logback還有一個比較明顯的優化點(賢亮補充)

在log4j中,當某個logger調用關聯的appenders進行輸出前會先通過synchronized加鎖,如下代碼所示:

Log4j vs. Logback 性能比較Inside

但是在logback中,隻會在某個appender要輸出日志時,使用reentrantlock來進行加鎖,如下代碼所示:

Log4j vs. Logback 性能比較Inside

這兩者的主要差別不在于reentrantlock和synchronized,因為最新的jvm中,這兩個性能不會相差太多,主要差別在于加鎖粒度上,當大并發的情況下,logback會有明顯的優勢,這個原理和concurrenthashmap的分段鎖類似。

對于其他的優化點,可以考慮自己做一些性能測試+閱讀源碼,體會會更深一些。

參考:

<a href="https://logging.apache.org/log4j/1.2/manual.html">https://logging.apache.org/log4j/1.2/manual.html</a>

<a href="http://logback.qos.ch/manual/">http://logback.qos.ch/manual/</a>