[infinispan-dev] trace vs log.isTraceEnabled
David M. Lloyd
david.lloyd at redhat.com
Wed Dec 7 13:10:35 EST 2011
On 12/07/2011 11:10 AM, Sanne Grinovero wrote:
> On 7 December 2011 17:04, Emmanuel Bernard<emmanuel at hibernate.org> wrote:
>>
>> Just to put some perspectives on things.
>> Yes the code will waste some cycles checking for trace level but I'd rather have you guys invent a better distro or local / tx / lock algorithm that will speed Infinispan by 10x rather than chasing 1/10 of a %. Just saying :)
>>
>> Profilers are fun but they tend to make you lose the big picture.
>
> Absolutely, it's dangerous to play with profilers :)
> But in this case it might be a simple solution, and we're speaking
> about an overall 4% CPU time overall, and benefitting all projects
> using JBoss Logger not just Infinispan. So that might be worth it..
> but as mentioned I don't intend to spend "official" time on it because
> I do fundamentally agree.
Something you should be aware of is that the main time consumer here
probably isn't JBoss Logging but log4j, which has a comparatively slow
level check. It has to recursively traverse log categories which
includes a loop and many dereferences.
If you use JBoss LogManager instead (like AS 6 and 7 do) then the level
check is a single volatile int read which is very cheap; the expense of
level propagation is placed upon the setLevel() caller which is
obviously done far less frequently. When I first replaced log4j with
JBoss LogManager in AS6, server boot time improved by nearly 10%, to
give you an idea of how big of a difference this can make.
We do use an enum for levels in JBoss Logging, which *should* be "fast"
though I don't have up-to-date measurements on that. For log4j, the
level enum is switched to translate to the log4j level, which then does
the aforementioned log4j level check. For JBoss LogManager, the level
enum is switched to a LogManager Level. I could probably speed this up
a little by going right to the integer value though.
I think the best strategy to follow for computation-intensive code
(especially when you expect that log4j is likely to be used) would be to
try to only do the trace level check once per "operation", in the event
that you are doing a lot of trace logging per operation. This is
equivalent to Sanne's example code:
> final boolean trace = log.isTraceEnabled();
> for(int i=1; i<=10; i++) {
> ....//other statements
> if (trace) log.trace( ...{preferrabily a JBLogger format}... );
> ...//other statements
> }
This will probably give at least a small benefit even if you are using a
"fast" log backend, because in this case "trace" is a local variable so
it's highly likely to be available in a cache line.
Note that it's important to check on a per-operation basis so that the
user can enable and disable trace logging during runtime and have their
change take effect.
For non-computationally-intensive code, just relying on the per-method
level checks whenever it is practical to do so is still what I
recommend, just for simplicity's sake.
Really the best policy is to look at the code, think about what it is
doing, and make an informed decision as to the best way to handle
logging on a case-by-case basis; there really isn't one single best
answer for all situations.
--
- DML
More information about the infinispan-dev
mailing list