Print

Print


Hi K-T -

See my response below. . .

-- Bill

On May 23, 2014, at 6:01 AM, Kian-Tat Lim <[log in to unmask]> wrote:

> Bill,
> 
> 	Have you tried something like this for the boost::format style
> interface?
> 
> static boost::format empty("");
> empty.exceptions(boost::io::no_error_bits);
> static logger eater(empty);
> 
> if (threshold met) {
>    return logger(boost::format(message));
> } else {
>    return logger(eater);
> }
This is interesting. I'll look into this.

> 
>> == streaming style interface ==
>> int data = 99;
>> LOG("myLogger", LOG_WARN_LVL, "This is a warning about data = " << data << ". So you have been warned!");
>> LOG_WARN("This is a warning about data = " <<  data << ". So you have been warned!");
> 
> 	How does this manage to run fast?  (What does the macro expand
> to, and how come operator% can't be made to work in the same way?)
The short answer: since all of the streaming is placed within the macro's parentheses, the macro can expand such that it occurs within a conditional statement. In online log4cxx tutorials you often see things like:
LOG4CXX_WARN(logger, "This is a warning about data = " <<  data << ". So you have been warned!");
which expands to:
{       
    if (logger->isWarnEnabled()) {
        ::log4cxx::helpers::MessageBuffer oss_;
        logger->forcedLog(::log4cxx::Level::getWarn(), oss_.str(oss_ << "This is a warning about data = " <<  data << ". So you have been warned!"), LOG4CXX_LOCATION);
    }
}
So, the streaming never occurs if threshold is not met.

The situation is different when writing something like:
LOG_WARN("This is a warning about data = %d. So you have been warned!") % data;
because operator% is outside the parentheses. In the latter case, the macro must instantiate and return something that implements operator%.

> 
> 	Also, does it make sense to offer a variety of LOG() that uses a
> pre-looked-up logger, or is it better to just set the default logger to
> that logger and use LOG_WARN?
Ah, this already exists! The LOG() macro will accept either a loggername or an actual logger object that was previously retrieved using LOG_GET(). Using a pre-looked-up logger in this way, a statement like:
LOG(logger, LOG_WARN_LVL, "This is a warning about data = %d. So you have been warned!") % data;
takes about 320ns on lsst-dev03. Meanwhile, a similar statement using the streaming interface:
LOG(logger, LOG_WARN_LVL, "This is a warning about data = " << data << ". So you have been warned!");
takes about 230ns (the varargs version is comparable). The 90ns difference between these two is the time required to instantiate the formatter object. The other 200ns is from an overloaded function call (allows us to use either a loggername or logger object with a single macro) and the level lookup. I suspect we could speed this up if we chose to use distinct macros for the loggername vs logger object use-cases.

> 
> -- 
> Kian-Tat Lim, LSST Data Management, [log in to unmask]

########################################################################
Use REPLY-ALL to reply to list

To unsubscribe from the QSERV-L list, click the following link:
https://listserv.slac.stanford.edu/cgi-bin/wa?SUBED1=QSERV-L&A=1