Skip to content
This repository was archived by the owner on Jul 31, 2023. It is now read-only.

Commit cb475e9

Browse files
authored
Add a benchmark for stats. (#16)
Presently covering aggregation / aggregation window combinations and varying numbers of views.
1 parent 76e7fc0 commit cb475e9

2 files changed

Lines changed: 140 additions & 0 deletions

File tree

opencensus/stats/BUILD

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,23 @@ cc_test(
205205
"@com_google_googletest//:gtest_main",
206206
],
207207
)
208+
209+
# Benchmarks
210+
# ========================================================================= #
211+
cc_binary(
212+
name = "stats_manager_benchmark",
213+
testonly = 1,
214+
srcs = ["internal/stats_manager_benchmark.cc"],
215+
copts = TEST_COPTS,
216+
linkopts = ["-pthread"], # Required for absl/synchronization bits.
217+
linkstatic = 1,
218+
deps = [
219+
":core",
220+
":export",
221+
":recording",
222+
"@com_google_absl//absl/memory",
223+
"@com_google_absl//absl/strings",
224+
"@com_google_absl//absl/time",
225+
"@com_google_benchmark//:benchmark",
226+
],
227+
)
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// Copyright 2018, OpenCensus Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include <memory>
16+
17+
#include "absl/memory/memory.h"
18+
#include "absl/strings/str_cat.h"
19+
#include "absl/time/time.h"
20+
#include "benchmark/benchmark.h"
21+
#include "opencensus/stats/measure.h"
22+
#include "opencensus/stats/measure_registry.h"
23+
#include "opencensus/stats/recording.h"
24+
#include "opencensus/stats/view.h"
25+
26+
namespace opencensus {
27+
namespace stats {
28+
namespace {
29+
30+
// Generates unique measure names. Since the registry does not support
31+
// unregistering, all measure names must be different across test cases.
32+
// In the present implementation, the number of measures should not affect the
33+
// performance of other measures--in the absence of the ability to reset state,
34+
// that is the best we can do.
35+
std::string MakeUniqueName() {
36+
static int counter;
37+
return absl::StrCat("name", counter++);
38+
}
39+
40+
// A set of utility types that allow "templating" a benchmark by
41+
// Aggregation/AggregationWindow.
42+
struct SumAggregation {
43+
Aggregation operator()(const BucketBoundaries& bucketer) {
44+
return Aggregation::Sum();
45+
}
46+
};
47+
struct CountAggregation {
48+
Aggregation operator()(const BucketBoundaries& bucketer) {
49+
return Aggregation::Count();
50+
}
51+
};
52+
struct DistributionAggregation {
53+
Aggregation operator()(const BucketBoundaries& bucketer) {
54+
return Aggregation::Distribution(bucketer);
55+
}
56+
};
57+
struct CumulativeWindow {
58+
AggregationWindow operator()(absl::Duration interval) {
59+
return AggregationWindow::Cumulative();
60+
}
61+
};
62+
struct IntervalWindow {
63+
AggregationWindow operator()(absl::Duration interval) {
64+
return AggregationWindow::Interval(interval);
65+
}
66+
};
67+
68+
// Benchmarks recording against various numbers of views on a single measure
69+
// with a small number of tags.
70+
template <class AggregationFactory, class AggregationWindowFactory>
71+
void BM_Record(benchmark::State& state) {
72+
const std::string tag_key_1 = "tag_key_1";
73+
const std::string tag_key_2 = "tag_key_2";
74+
const std::string measure_name = MakeUniqueName();
75+
MeasureDouble measure = MeasureRegistry::RegisterDouble(measure_name, "", "");
76+
std::vector<std::unique_ptr<View>> views;
77+
for (int i = 0; i < state.range(0); ++i) {
78+
// The view_key_* tag key is necessary to prevent these from being merged by
79+
// the StatsManager.
80+
const ViewDescriptor descriptor =
81+
ViewDescriptor()
82+
.set_measure(measure_name)
83+
.set_name("count")
84+
.set_aggregation(
85+
AggregationFactory()(BucketBoundaries::Exponential(10, 10, 2)))
86+
.set_aggregation_window(AggregationWindowFactory()(absl::Hours(1)))
87+
.add_column(tag_key_1)
88+
.add_column(absl::StrCat("view_key_", i));
89+
views.push_back(absl::make_unique<View>(descriptor));
90+
}
91+
std::vector<std::string> tag_values(100);
92+
for (int i = 0; i < 100; ++i) {
93+
tag_values[i] = absl::StrCat("value", i);
94+
}
95+
int iteration = 0;
96+
while (state.KeepRunning()) {
97+
Record({{measure, static_cast<double>(iteration)}},
98+
{{tag_key_1, tag_values[iteration % tag_values.size()]},
99+
{tag_key_2, ""}});
100+
++iteration;
101+
}
102+
}
103+
BENCHMARK_TEMPLATE2(BM_Record, SumAggregation, CumulativeWindow)->Range(1, 16);
104+
BENCHMARK_TEMPLATE2(BM_Record, SumAggregation, IntervalWindow)->Range(1, 16);
105+
BENCHMARK_TEMPLATE2(BM_Record, CountAggregation, CumulativeWindow)
106+
->Range(1, 16);
107+
BENCHMARK_TEMPLATE2(BM_Record, CountAggregation, IntervalWindow)->Range(1, 16);
108+
BENCHMARK_TEMPLATE2(BM_Record, DistributionAggregation, CumulativeWindow)
109+
->Range(1, 16);
110+
BENCHMARK_TEMPLATE2(BM_Record, DistributionAggregation, IntervalWindow)
111+
->Range(1, 16);
112+
113+
// TODO: Other useful benchmarks:
114+
// - Multithreaded recording against one/different measures.
115+
// - Recording with parameterized numbers of tag keys.
116+
117+
} // namespace
118+
} // namespace stats
119+
} // namespace opencensus
120+
BENCHMARK_MAIN();

0 commit comments

Comments
 (0)