1/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 *     Copyright 2016 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 <condition_variable>
19#include <string>
20#include <thread>
21
22#include <benchmark/benchmark.h>
23#include <phosphor/category_registry.h>
24#include <utils/memory.h>
25
26#include "barrier.h"
27#include "bench_common.h"
28
29using namespace phosphor;
30
31/*
32 * This benchmark continually makes new categories in a registry
33 * (roughly 1/<# threads> calls to getStatus will be a new category).
34 *
35 * It is primarily to trigger a TSan race but is useful as a general
36 * benchmark of status gathering.
37 */
38void NewCategories(benchmark::State& state) {
39    // Registry comes with 3 items already in it
40    static std::array<std::string, (CategoryRegistry::registry_size - 3)> categories;
41    static std::unique_ptr<CategoryRegistry> registry;
42    static Barrier barrier{0};
43
44    if (state.thread_index == 0) {
45        size_t i = 1;
46        for (auto& category : categories) {
47            category = std::string("A", i++);
48        }
49        registry = utils::make_unique<CategoryRegistry>();
50        barrier.reset(state.threads);
51    }
52
53    while (state.KeepRunning()) {
54        for (const auto& category : categories) {
55            registry->getStatus(category.c_str());
56        }
57        state.PauseTiming();
58
59        // Wait for all the threads to sync up so we can reset
60        // the category registry.
61        barrier.wait([](){
62            registry = utils::make_unique<CategoryRegistry>();
63        });
64
65        state.ResumeTiming();
66    }
67}
68
69BENCHMARK(NewCategories)->ThreadRange(1, phosphor::benchNumThreads());
70
71BENCHMARK_MAIN()
72