On Tue, Dec 25, 2012 at 5:45 PM, Vinay Sajip <vinay_sajip@yahoo.co.uk> wrote:
Rene Nejsum <rene@...> writes:

> So doing:
>
> if log.debug.enabled():
>       log.debug( bla. bla. )
>
> Add's 5-10% extra code lines, whereas if we could do:
>
> log.debug( bla. bla )
>
> at the same cost would save a lot of lines.

Bearing in mind that the first statement in the debug (and analogous methods) is
a check for the level, the only thing you gain by having the same check outside
the call is the cost of evaluating arguments. But you can also do this by
passing an arbitrary class as the message object, which lazily evaluates only
when needed. Contrived example:

class Message(object):
    def __init__(self, func, x, y): # params should be cheap to evaluate
        self.func = func
        self.x = x
        self.y = y

    def __str__(self):
        return str(self.func(self.x**self.y)) # expense is incurred here

logger.debug(Message(factorial, 2, 15))

With this setup, no if statements are needed in your code, and the expensive
computations only occur when required.

That's still two function calls and three assignments per logging call. Too expensive and syntax unwieldy. I think everybody agrees now that for existing CPython implementation there is really no solution for the problem of expensive logging calls vs code clarity. You have to implement optimization workaround at the cost of readability.

The idea is to fix the interpreter, introducing a "feature block" - execution block that works only if it is enabled. Execution block for logging example below is defined by function name "debug" and braces ().

    debug( <block contents> )

debug is an object of 'feature' type, which is only executed/evaluated, if the feature is enabled in a table of features.

It might be possible to implement this as a custom version of PyPy. Then by hardcoding logic for treating logging call as 'featured'  should give an immediate performance boost to any project. Still it would be nice if logging was build with supported layout for easy optimization or for 'from __future__ import features.logging' .