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 <boost/optional/optional.hpp>
21#include <logger/logger.h>
22#include <logger/logger_config.h>
23#include <iostream>
24
25/**
26 * A fixture for benchmarking the logger.
27 */
28class LoggerBench : public benchmark::Fixture {
29protected:
30    void SetUp(const benchmark::State& state) override;
31
32    void TearDown(const benchmark::State& state) override {
33        if (state.thread_index == 0) {
34            if (cb::logger::isInitialized()) {
35                cb::logger::shutdown();
36            } else {
37                std::cerr << "Failed to shutdown logger as it was never "
38                             "initialized in the first place";
39                return;
40            }
41        }
42    }
43};
44
45void LoggerBench::SetUp(const benchmark::State& state) {
46    if (state.thread_index == 0) {
47        cb::logger::Config config{};
48        config.cyclesize = 2048;
49        config.buffersize = 8192;
50        config.unit_test = true;
51        config.console = false;
52
53        auto init = cb::logger::initialize(config);
54        if (init) {
55            std::cerr << "Failed to initialize logger: " << *init;
56            return;
57        }
58
59        cb::logger::get()->set_level(spdlog::level::level_enum::warn);
60    }
61}
62
63class LoggerBench_Blackhole : public LoggerBench {
64protected:
65    void SetUp(const benchmark::State& state) override {
66        if (state.thread_index == 0) {
67            cb::logger::createBlackholeLogger();
68        }
69    }
70};
71
72/**
73 * Benchmark the cost of logging to a level which is dropped.
74 * We're currently using the async logging (which is the one
75 * we'll be using "in production".. except that we don't have
76 * the file-backend writing to the disk
77 */
78BENCHMARK_DEFINE_F(LoggerBench, LogToLoggerWithDisabledLogLevel)
79(benchmark::State& state) {
80    while (state.KeepRunning()) {
81        LOG_TRACE("Foo");
82    }
83}
84
85/**
86 * Benchmark the cost of logging to a level which is enabled (moved
87 * to the sink).
88 * We're currently using the async logging (which is the one
89 * we'll be using "in production".. except that we don't have
90 * the file-backend writing to the disk
91 */
92BENCHMARK_DEFINE_F(LoggerBench, LogToLoggerWithEnabledLogLevel)
93(benchmark::State& state) {
94    if (state.thread_index == 0) {
95        cb::logger::get()->set_level(spdlog::level::level_enum::trace);
96    }
97    while (state.KeepRunning()) {
98        LOG_TRACE("Foo");
99    }
100}
101
102/**
103 * Benchmark the cost of grabbing the logger (which means checking
104 * for it's existence and copy a shared pointer).
105 */
106BENCHMARK_DEFINE_F(LoggerBench_Blackhole, GetLogger)(benchmark::State& state) {
107    while (state.KeepRunning()) {
108        auto logger = cb::logger::get();
109        benchmark::DoNotOptimize(logger);
110    }
111}
112
113BENCHMARK_REGISTER_F(LoggerBench_Blackhole, GetLogger)->Threads(1)->Threads(16);
114BENCHMARK_REGISTER_F(LoggerBench, LogToLoggerWithDisabledLogLevel)
115        ->Threads(1)
116        ->Threads(16);
117BENCHMARK_REGISTER_F(LoggerBench, LogToLoggerWithEnabledLogLevel)
118        ->Threads(1)
119        ->Threads(16);
120
121int main(int argc, char** argv) {
122    ::benchmark::Initialize(&argc, argv);
123    if (::benchmark::ReportUnrecognizedArguments(argc, argv)) {
124        return EXIT_FAILURE;
125    }
126    ::benchmark::RunSpecifiedBenchmarks();
127    return EXIT_SUCCESS;
128}
129