<div class="gmail_quote"><div>Thanks for a quick reply.<br><br>With that performance figures while using logback, I agree this is not an improvement. <br><br>The other best we can do is to have a convenience method in logback api which accepts format, and args directly; in addition to the current api which just accepts a msgStr.<br>
<br>Maybe this clutters api, with more methods. Considering improved performance with logback, I think what we have is fine.<br><br>Regards,<br>Srini<br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
<br>
Message: 1<br>
Date: Thu, 23 Oct 2008 19:20:52 +0200<br>
From: Ceki Gulcu &lt;listid@qos.ch&gt;<br>
Subject: Re: [slf4j-user] Double Checking log level when logging with<br>
 &nbsp; &nbsp; &nbsp; &nbsp;log4j<br>
To: User list for the slf4j project &lt;<a href="mailto:user@slf4j.org">user@slf4j.org</a>&gt;<br>
Message-ID: &lt;4900B274.9020309@qos.ch&gt;<br>
Content-Type: text/plain; charset=UTF-8; format=flowed<br>
<br>
Hello Srinivasan,<br>
<br>
The logger.isEnabledFor(...) operation takes about 25 nanoseconds with log4j and<br>
about 10 nanoseconds with logback. new InterpolatedMessage probably takes longer<br>
than that..<br>
<br>
Srinivasan Raguraman wrote:<br>
&gt; When we are using log4j as underlying logger, sl4j actually does double<br>
&gt; checking of &#39;isErrorEnabled()&#39; for every Log, if that LEVEL is enabled.<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; public void error(String format, Object arg) {<br>
&gt;<br>
&gt; &nbsp; &nbsp; if (logger.isEnabledFor(Level.ERROR)) {<br>
&gt;<br>
&gt; &nbsp; &nbsp; &nbsp; String msgStr = MessageFormatter.format(format, arg);<br>
&gt;<br>
&gt; &nbsp; &nbsp; &nbsp; logger.log(FQCN, Level.ERROR, msgStr, null);<br>
&gt;<br>
&gt; &nbsp; &nbsp; }<br>
&gt;<br>
&gt; &nbsp; }<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; This is because, once we pass the message to log4j<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; logger.log(FQCN, Level.ERROR, msgStr, null);<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; log4j library again does the check isErrorEnabled() before the actual<br>
&gt; logging. This code is the same as the isErrorEnabled check.<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; *public*<br>
&gt;<br>
&gt; &nbsp; *void* log(String callerFQCN, Priority level, Object message,<br>
&gt; Throwable t) {<br>
&gt;<br>
&gt; &nbsp; &nbsp; *if*(repository.isDisabled(level.level)) {<br>
&gt;<br>
&gt; &nbsp; &nbsp; &nbsp; *return*;<br>
&gt;<br>
&gt; &nbsp; &nbsp; }<br>
&gt;<br>
&gt; &nbsp; &nbsp; *if*(level.isGreaterOrEqual(*this*.getEffectiveLevel())) {<br>
&gt;<br>
&gt; &nbsp; &nbsp; &nbsp; forcedLog(callerFQCN, level, message, t);<br>
&gt;<br>
&gt; &nbsp; &nbsp; }<br>
&gt;<br>
&gt; &nbsp; }<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; To avoid this double checking why don&#39;t we wrap the format, arguments<br>
&gt; inside an Object, and use log4j renderer for that object to generate the<br>
&gt; final message? Or even override toString() method of that object to<br>
&gt; return the formatted message.<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; Instead of this:<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; logger.log(FQCN, Level.ERROR, msgStr, null);<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; It could be something like:<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; public void error(String format, Object arg) {<br>
&gt;<br>
&gt; &nbsp; &nbsp; &nbsp; logger.log(FQCN, Level.ERROR, new InterpolatedMessage(formate, arg), null);<br>
&gt;<br>
&gt; }<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; Where<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; public final class InterpolatedMessage {<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; private final String format;<br>
&gt;<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; private final Object arg;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public InterpolatedMessage(final String format, final Object<br>
&gt; arg) {<br>
&gt;<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.format = format;<br>
&gt;<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.arg = arg;<br>
&gt;<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override<br>
&gt;<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public String toString() {<br>
&gt;<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return MessageFormatter.format(this.format,<br>
&gt; this.arg);<br>
&gt;<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; }<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; As you see, this will<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; &nbsp; &nbsp; * Delay the message construction unless it really going to be used.<br>
&gt; &nbsp; &nbsp; * Avoid double checking with if LevelEnabled, when that level is<br>
&gt; &nbsp; &nbsp; &nbsp; actually enabled<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; The negatives are<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; &nbsp; &nbsp; * Creation of InterpolatedMessage Object for every log statement ?<br>
&gt; &nbsp; &nbsp; &nbsp; since the object is just going to hold the reference of the format<br>
&gt; &nbsp; &nbsp; &nbsp; and args, this may not be expensive?<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; o as it avoids construction of log message<br>
&gt; &nbsp; &nbsp; * Using toString() method of interpolated message is a trick! &nbsp;-<br>
&gt; &nbsp; &nbsp; &nbsp; Yes, for that we can otherwise add log4j renderer for objects of<br>
&gt; &nbsp; &nbsp; &nbsp; InterpolatedMessage type.<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; I just gave my thoughts here; let me know what you guys think. I could<br>
&gt; follow up or help to verify if this will really gives us performance<br>
&gt; advantage.<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; Regards,<br>
&gt;<br>
&gt; Srini<br>
&gt;<br>
&gt;<br>
&gt; ------------------------------------------------------------------------<br>
&gt;<br>
&gt; _______________________________________________<br>
&gt; user mailing list<br>
&gt; <a href="mailto:user@slf4j.org">user@slf4j.org</a><br>
&gt; <a href="http://www.slf4j.org/mailman/listinfo/user" target="_blank">http://www.slf4j.org/mailman/listinfo/user</a><br>
<br>
--<br>
Ceki G?lc?<br>
Logback: The reliable, generic, fast and flexible logging framework for Java.<br>
<a href="http://logback.qos.ch" target="_blank">http://logback.qos.ch</a><br>
<br>
<br>
------------------------------<br>
<br>
_______________________________________________<br>
user mailing list<br>
<a href="mailto:user@slf4j.org">user@slf4j.org</a><br>
<a href="http://www.slf4j.org/mailman/listinfo/user" target="_blank">http://www.slf4j.org/mailman/listinfo/user</a><br>
<br>
End of user Digest, Vol 26, Issue 12<br>
************************************<br>
</blockquote></div><br><br clear="all"><br>-- <br>Regards,<br>Srini<br>