Skip to content

Performance issue: Boost.Log does a huge work when filtering records #202

@evgn

Description

@evgn

I worked with Boost.Log library and encountered a huge performance impact in case when all content passed to the logger supposed to be filtered.
I reduced the logger to the simplest one with a console backend and the result remained the same.

Here is the sample code:

#include <boost/log/sources/severity_feature.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/common.hpp>
#include <boost/log/utility/setup/console.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/phoenix/bind.hpp>

enum severity_level
{
    critical,
    info,
    trace
};

BOOST_LOG_ATTRIBUTE_KEYWORD(severity_level_kw, "Severity", severity_level)

using backend_type = boost::log::sinks::synchronous_sink<boost::log::sinks::basic_text_ostream_backend<char>>;

bool filter_impl(severity_level lvl) { return lvl < trace; }
bool filter(const boost::log::value_ref<severity_level, tag::severity_level_kw> & lvl) {
    return filter_impl(*lvl);
}

void logging_function() {
    auto sink = boost::make_shared<backend_type>();
    sink->set_filter(boost::phoenix::bind(&filter, severity_level_kw.or_none()));
    sink->locked_backend()->add_stream(boost::shared_ptr<std::ostream>(&std::cout, boost::null_deleter{}));
    boost::log::core::get()->add_sink(std::move(sink));

    boost::log::sources::severity_logger<severity_level> slg;
    for(int i = 0; i < 100000000; ++i) {
        // I expect this line only applies the filter and does nothing else since trace-messages supposed to be filtered
        BOOST_LOG_SEV(slg, trace) << "Trace message: " << i;
    }
}

int main()
{
    logging_function();
    return 0;
}

This simple program works for ~14 seconds.
But if I change the loop like this:

for(int i = 0; i < 100000000; ++i) {
    if(filter_impl(trace))
        std::cout << "Debug message: " << i << "\n";
}

the program completes instantly as it supposed to. And it's what I expect the log library should do.

I profiled the program with dotTrace and here is the result

image

As you can see filter function takes only 95ms and the rest time goes to another stuff including memory allocations which I wouldn't expect to see.

This problem makes Boost.Log unusable in cases when performance is a priority.

As a hot-fix one can filter records manually by introducing a special macro, for example.

But is it worth expecting this issue will be fixed?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions