1 // Copyright 2024 The gRPC 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 <benchmark/benchmark.h>
16 #include <grpcpp/ext/otel_plugin.h>
17
18 #include <memory>
19
20 #include "absl/log/absl_check.h"
21 #include "absl/strings/string_view.h"
22 #include "opentelemetry/sdk/metrics/meter_provider.h"
23 #include "src/core/lib/event_engine/channel_args_endpoint_config.h"
24 #include "src/core/telemetry/metrics.h"
25 #include "test/core/test_util/fake_stats_plugin.h"
26 #include "test/core/test_util/test_config.h"
27 #include "test/cpp/microbenchmarks/helpers.h"
28 #include "test/cpp/util/test_config.h"
29
30 namespace {
31
32 constexpr const absl::string_view kMetricName = "test.counter";
33 constexpr const absl::string_view kMetricNameWithLabels =
34 "test.counter_with_labels";
35
36 const auto kCounterHandle =
37 grpc_core::GlobalInstrumentsRegistry::RegisterUInt64Counter(
38 kMetricName, "A simple test counter", "{count}", true)
39 .Build();
40
41 const auto kCounterWithLabelsHandle =
42 grpc_core::GlobalInstrumentsRegistry::RegisterUInt64Counter(
43 kMetricNameWithLabels, "A simple test counter with labels", "{count}",
44 true)
45 .Labels("key1", "key2", "key3")
46 .OptionalLabels("opt_key1", "opt_key2", "opt_key3")
47 .Build();
48
BM_AddCounterWithFakeStatsPlugin(benchmark::State & state)49 void BM_AddCounterWithFakeStatsPlugin(benchmark::State& state) {
50 grpc_core::GlobalStatsPluginRegistryTestPeer::
51 ResetGlobalStatsPluginRegistry();
52 grpc_core::FakeStatsPluginBuilder().BuildAndRegister();
53 grpc_event_engine::experimental::ChannelArgsEndpointConfig endpoint_config;
54 auto stats_plugin_group =
55 grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
56 grpc_core::experimental::StatsPluginChannelScope("", "",
57 endpoint_config));
58 for (auto _ : state) {
59 stats_plugin_group.AddCounter(kCounterHandle, 1, {}, {});
60 }
61 }
62 BENCHMARK(BM_AddCounterWithFakeStatsPlugin);
63
BM_AddCounterWithLabelsWithFakeStatsPlugin(benchmark::State & state)64 void BM_AddCounterWithLabelsWithFakeStatsPlugin(benchmark::State& state) {
65 grpc_core::GlobalStatsPluginRegistryTestPeer::
66 ResetGlobalStatsPluginRegistry();
67 grpc_core::FakeStatsPluginBuilder().BuildAndRegister();
68 grpc_event_engine::experimental::ChannelArgsEndpointConfig endpoint_config;
69 auto stats_plugin_group =
70 grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
71 grpc_core::experimental::StatsPluginChannelScope("", "",
72 endpoint_config));
73 for (auto _ : state) {
74 stats_plugin_group.AddCounter(kCounterWithLabelsHandle, 1,
75 {"val1", "val2", "val3"},
76 {"opt_val1", "opt_val2", "opt_val3"});
77 }
78 }
79 BENCHMARK(BM_AddCounterWithLabelsWithFakeStatsPlugin);
80
BM_AddCounterWithOTelPlugin(benchmark::State & state)81 void BM_AddCounterWithOTelPlugin(benchmark::State& state) {
82 grpc_core::GlobalStatsPluginRegistryTestPeer::
83 ResetGlobalStatsPluginRegistry();
84 auto meter_provider =
85 std::make_shared<opentelemetry::sdk::metrics::MeterProvider>();
86 auto status = grpc::OpenTelemetryPluginBuilder()
87 .EnableMetrics({kMetricName})
88 .SetMeterProvider(std::move(meter_provider))
89 .BuildAndRegisterGlobal();
90 CHECK(status.ok());
91 grpc_event_engine::experimental::ChannelArgsEndpointConfig endpoint_config;
92 auto stats_plugin_group =
93 grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
94 grpc_core::experimental::StatsPluginChannelScope("", "",
95 endpoint_config));
96 for (auto _ : state) {
97 stats_plugin_group.AddCounter(kCounterHandle, 1, {}, {});
98 }
99 }
100 BENCHMARK(BM_AddCounterWithOTelPlugin);
101
BM_AddCounterWithLabelsWithOTelPlugin(benchmark::State & state)102 void BM_AddCounterWithLabelsWithOTelPlugin(benchmark::State& state) {
103 grpc_core::GlobalStatsPluginRegistryTestPeer::
104 ResetGlobalStatsPluginRegistry();
105 auto meter_provider =
106 std::make_shared<opentelemetry::sdk::metrics::MeterProvider>();
107 auto status = grpc::OpenTelemetryPluginBuilder()
108 .EnableMetrics({kMetricName})
109 .SetMeterProvider(std::move(meter_provider))
110 .BuildAndRegisterGlobal();
111 CHECK(status.ok());
112 grpc_event_engine::experimental::ChannelArgsEndpointConfig endpoint_config;
113 auto stats_plugin_group =
114 grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
115 grpc_core::experimental::StatsPluginChannelScope("", "",
116 endpoint_config));
117 for (auto _ : state) {
118 stats_plugin_group.AddCounter(kCounterWithLabelsHandle, 1,
119 {"val1", "val2", "val3"},
120 {"opt_val1", "opt_val2", "opt_val3"});
121 }
122 }
123 BENCHMARK(BM_AddCounterWithLabelsWithOTelPlugin);
124
BM_AddCounterWithNoPlugin(benchmark::State & state)125 void BM_AddCounterWithNoPlugin(benchmark::State& state) {
126 grpc_core::GlobalStatsPluginRegistryTestPeer::
127 ResetGlobalStatsPluginRegistry();
128 grpc_event_engine::experimental::ChannelArgsEndpointConfig endpoint_config;
129 auto stats_plugin_group =
130 grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
131 grpc_core::experimental::StatsPluginChannelScope("", "",
132 endpoint_config));
133 for (auto _ : state) {
134 stats_plugin_group.AddCounter(kCounterHandle, 1, {}, {});
135 }
136 }
137 BENCHMARK(BM_AddCounterWithNoPlugin);
138
BM_AddCounterWithLabelsWithNoPlugin(benchmark::State & state)139 void BM_AddCounterWithLabelsWithNoPlugin(benchmark::State& state) {
140 grpc_core::GlobalStatsPluginRegistryTestPeer::
141 ResetGlobalStatsPluginRegistry();
142 grpc_event_engine::experimental::ChannelArgsEndpointConfig endpoint_config;
143 auto stats_plugin_group =
144 grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
145 grpc_core::experimental::StatsPluginChannelScope("", "",
146 endpoint_config));
147 for (auto _ : state) {
148 stats_plugin_group.AddCounter(kCounterWithLabelsHandle, 1,
149 {"val1", "val2", "val3"},
150 {"opt_val1", "opt_val2", "opt_val3"});
151 }
152 }
153 BENCHMARK(BM_AddCounterWithLabelsWithNoPlugin);
154
155 } // namespace
156
157 // Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
158 // and others do not. This allows us to support both modes.
159 namespace benchmark {
RunTheBenchmarksNamespaced()160 void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
161 } // namespace benchmark
162
main(int argc,char ** argv)163 int main(int argc, char** argv) {
164 grpc::testing::TestEnvironment env(&argc, argv);
165 LibraryInitializer libInit;
166 ::benchmark::Initialize(&argc, argv);
167 grpc::testing::InitTest(&argc, &argv, false);
168 benchmark::RunTheBenchmarksNamespaced();
169 return 0;
170 }
171