為什么記錄debug和info日志前要加個判斷?其實原因很簡單:提高效率!如上代碼所示,在記錄日志時進行了字符串拼接,要知道這是會消耗一定資源的。假如當前log日志級別是error,則debug和info是不會被輸出的,如果加了if判斷則log.debug/info中的字符串拼接就不會執行,自然提高了效率。
些人不明白為什么要這樣寫。有些人認為這樣是為了能夠控制日志的輸出,對於下面這行代碼:
- logger.debug(message);
他們的看法是:如果這樣寫的話,就算你把日志級別調整為info, 這里也會輸出日志。
其實,在debug()方法里面,就已經叛斷了日志的級別。以下是isDebugEnabled()的源碼:
- public boolean isDebugEnabled() {
- if(repository.isDisabled( Level.DEBUG_INT))
- return false;
- return Level.DEBUG.isGreaterOrEqual(this.getEffectiveLevel());
- }
以下是debug()的源碼:
- public void debug(Object message) {
- if(repository.isDisabled(Level.DEBUG_INT))
- return;
- if(Level.DEBUG.isGreaterOrEqual(this.getEffectiveLevel())) {
- forcedLog(FQCN, Level.DEBUG, message, null);
- }
- }
我們可以看到,在debug()方法里做了跟isDebugEnabled()方法一樣的判斷。
在這里,我們不禁會想,那我們凡是要輸日志的地方,都不判斷isDebugEnabled,直接調debug方法,不更省事嗎?
官方的說法是:出於效率考慮,看具體情況而定.
我們來看下面一行代碼:
- logger.debug("The money is " + getTotalMoney());
假設我們的日志級別設置為info,那這句話不會輸出日志,但這個方法還是會調用。要調用這個方法,必須提供參數。getTotalMoney()方法返回的結果就是參數的一部分。假設getTotalMoney()要執行10秒鍾,10秒鍾后,進入到debug()方法里,碰到了第一個判斷:
- if(repository.isDisabled(Level.DEBUG_INT))
- return;
在這里就返回了。結果是日志雖然沒有輸出,卻花費了10秒鍾來構造參數。很顯然這里得不償失的。盡管實際應用中幾乎不可能有這種花10秒鍾來構造這樣一個參數的情況,但如果並發數大的話,這樣寫還是會影響系統的性能的。這個時候,就應該寫成:
- if(logger.isDebugEnabled()){
- logger.debug("The money is " + getTotalMoney());
- }
如果debug的參數很簡單的話,也可以直接寫 logger.debug(message)的。官方的說法,執行一次logger.isDebugEnabled()這樣的判斷花費的時間大概是寫日志時間的萬分之一.雖然這個比例很小,
在小系統看不出差距,但如果是高並發的系統下,少執行一句代碼能明顯減小服務器的壓力。