File: record_emission.cpp

package info (click to toggle)
boost1.90 1.90.0-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 593,120 kB
  • sloc: cpp: 4,190,908; xml: 196,648; python: 34,618; ansic: 23,145; asm: 5,468; sh: 3,774; makefile: 1,161; perl: 1,020; sql: 728; ruby: 676; yacc: 478; java: 77; lisp: 24; csh: 6
file content (130 lines) | stat: -rw-r--r-- 4,091 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 *          Copyright Andrey Semashev 2007 - 2015.
 * Distributed under the Boost Software License, Version 1.0.
 *    (See accompanying file LICENSE_1_0.txt or copy at
 *          http://www.boost.org/LICENSE_1_0.txt)
 */
/*!
 * \file   record_emission.cpp
 * \author Andrey Semashev
 * \date   22.03.2009
 *
 * \brief  This code measures performance of log record emission
 */

// #define BOOST_LOG_USE_CHAR
// #define BOOST_ALL_DYN_LINK 1
// #define BOOST_LOG_DYN_LINK 1
#define BOOST_NO_DYN_LINK 1

#include <vector>
#include <chrono>
#include <thread>
#include <iomanip>
#include <iostream>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>

#include <boost/log/core.hpp>
#include <boost/log/common.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/sinks/basic_sink_backend.hpp>
#include <boost/log/sources/logger.hpp>

#include <boost/log/expressions.hpp>

#include <boost/log/attributes/scoped_attribute.hpp>

#include "test_barrier.hpp"

enum config
{
    RECORD_COUNT = 20000000,
    THREAD_COUNT = 8,
    SINK_COUNT = 3
};

namespace logging = boost::log;
namespace expr = boost::log::expressions;
namespace sinks = boost::log::sinks;
namespace attrs = boost::log::attributes;
namespace src = boost::log::sources;
namespace keywords = boost::log::keywords;

enum severity_level
{
    normal,
    warning,
    error
};

BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_level)

namespace {

    //! A fake sink backend that receives log records
    class fake_backend :
        public sinks::basic_sink_backend< sinks::concurrent_feeding >
    {
    public:
        void consume(logging::record_view const& rec)
        {
        }
    };

} // namespace

void test(unsigned int record_count, test_barrier& bar)
{
    BOOST_LOG_SCOPED_THREAD_TAG("ThreadID", boost::this_thread::get_id());
    src::severity_logger< severity_level > slg;
//    src::logger lg;
    bar.arrive_and_wait();

    for (unsigned int i = 0; i < record_count; ++i)
    {
        BOOST_LOG_SEV(slg, warning) << "Test record";
//        BOOST_LOG(lg) << "Test record";
    }
}

int main(int argc, char* argv[])
{
    std::cout << "Test config: " << THREAD_COUNT << " threads, " << SINK_COUNT << " sinks, " << RECORD_COUNT << " records" << std::endl;
//    typedef sinks::unlocked_sink< fake_backend > fake_sink;
//    typedef sinks::synchronous_sink< fake_backend > fake_sink;
    typedef sinks::asynchronous_sink< fake_backend > fake_sink;
    for (unsigned int i = 0; i < SINK_COUNT; ++i)
        logging::core::get()->add_sink(boost::make_shared< fake_sink >());

    logging::core::get()->add_global_attribute("LineID", attrs::counter< unsigned int >(1));
    logging::core::get()->add_global_attribute("TimeStamp", attrs::local_clock());
    logging::core::get()->add_global_attribute("Scope", attrs::named_scope());

//    logging::core::get()->set_filter(severity > normal); // all records pass the filter
//    logging::core::get()->set_filter(severity > error); // all records don't pass the filter

//    logging::core::get()->set_filter(severity > error); // all records don't pass the filter

    const unsigned int record_count = RECORD_COUNT / THREAD_COUNT;
    test_barrier bar(THREAD_COUNT);
    std::vector< std::thread > threads(THREAD_COUNT - 1);

    for (unsigned int i = 0; i < THREAD_COUNT - 1; ++i)
        threads[i] = std::thread([&bar, record_count]() { test(record_count, bar); });

    const auto start = std::chrono::steady_clock::now();
    test(record_count, bar);
    for (unsigned int i = 0; i < THREAD_COUNT - 1; ++i)
        threads[i].join();
    const auto finish = std::chrono::steady_clock::now();

    unsigned long long duration_us = std::chrono::duration_cast< std::chrono::microseconds >(finish - start).count();

    std::cout << "Test duration: " << duration << " us ("
        << std::fixed << std::setprecision(3) << static_cast< double >(RECORD_COUNT) / (static_cast< double >(duration) / 1000000.0)
        << " records per second)" << std::endl;

    return 0;
}