1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  *     Copyright 2018 Couchbase, Inc.
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  */
17 
18 #include <benchmark/benchmark.h>
19 
20 #include <logger/logger.h>
21 #include <iostream>
22 
23 /**
24  * A fixture for benchmarking the logger.
25  */
26 class LoggerBench : public benchmark::Fixture {
27 protected:
28     void SetUp(const benchmark::State& state) override;
29 
30     void TearDown(const benchmark::State& state) override {
31         if (state.thread_index == 0) {
32             if (cb::logger::isInitialized()) {
33                 cb::logger::shutdown();
34             } else {
35                 std::cerr << "Failed to shutdown logger as it was never "
36                              "initialized in the first place";
37                 return;
38             }
39         }
40     }
41 };
42 
SetUp(const benchmark::State& state)43 void LoggerBench::SetUp(const benchmark::State& state) {
44     if (state.thread_index == 0) {
45         cb::logger::Config config{};
46         config.cyclesize = 2048;
47         config.buffersize = 8192;
48         config.unit_test = true;
49         config.console = false;
50 
51         auto init = cb::logger::initialize(config);
52         if (init) {
53             std::cerr << "Failed to initialize logger: " << *init;
54             return;
55         }
56 
57         cb::logger::get()->set_level(spdlog::level::level_enum::warn);
58     }
59 }
60 
61 class LoggerBench_Blackhole : public LoggerBench {
62 protected:
63     void SetUp(const benchmark::State& state) override {
64         if (state.thread_index == 0) {
65             cb::logger::createBlackholeLogger();
66         }
67     }
68 };
69 
70 /**
71  * Benchmark the cost of logging to a level which is dropped.
72  * We're currently using the async logging (which is the one
73  * we'll be using "in production".. except that we don't have
74  * the file-backend writing to the disk
75  */
BENCHMARK_DEFINE_F(LoggerBench, LogToLoggerWithDisabledLogLevel)76 BENCHMARK_DEFINE_F(LoggerBench, LogToLoggerWithDisabledLogLevel)
77 (benchmark::State& state) {
78     while (state.KeepRunning()) {
79         LOG_TRACE("Foo");
80     }
81 }
82 
83 /**
84  * Benchmark the cost of logging to a level which is enabled (moved
85  * to the sink).
86  * We're currently using the async logging (which is the one
87  * we'll be using "in production".. except that we don't have
88  * the file-backend writing to the disk
89  */
BENCHMARK_DEFINE_F(LoggerBench, LogToLoggerWithEnabledLogLevel)90 BENCHMARK_DEFINE_F(LoggerBench, LogToLoggerWithEnabledLogLevel)
91 (benchmark::State& state) {
92     if (state.thread_index == 0) {
93         cb::logger::get()->set_level(spdlog::level::level_enum::trace);
94     }
95     while (state.KeepRunning()) {
96         LOG_TRACE("Foo");
97     }
98 }
99 
100 /**
101  * Benchmark the cost of grabbing the logger (which means checking
102  * for it's existence and copy a shared pointer).
103  */
BENCHMARK_DEFINE_F(LoggerBench_Blackhole, GetLogger)104 BENCHMARK_DEFINE_F(LoggerBench_Blackhole, GetLogger)(benchmark::State& state) {
105     while (state.KeepRunning()) {
106         auto logger = cb::logger::get();
107         benchmark::DoNotOptimize(logger);
108     }
109 }
110 
111 BENCHMARK_REGISTER_F(LoggerBench_Blackhole, GetLogger)->Threads(1)->Threads(16);
112 BENCHMARK_REGISTER_F(LoggerBench, LogToLoggerWithDisabledLogLevel)
113         ->Threads(1)
114         ->Threads(16);
115 BENCHMARK_REGISTER_F(LoggerBench, LogToLoggerWithEnabledLogLevel)
116         ->Threads(1)
117         ->Threads(16);
118 
main(int argc, char** argv)119 int main(int argc, char** argv) {
120     ::benchmark::Initialize(&argc, argv);
121     if (::benchmark::ReportUnrecognizedArguments(argc, argv)) {
122         return EXIT_FAILURE;
123     }
124     ::benchmark::RunSpecifiedBenchmarks();
125     return EXIT_SUCCESS;
126 }
127