1 /*
2 *
3 * Copyright 2015 gRPC authors.
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
19 /* This benchmark exists to ensure that the benchmark integration is
20 * working */
21
22 #include <benchmark/benchmark.h>
23 #include <grpc/grpc.h>
24 #include <grpc/support/log.h>
25 #include <grpcpp/completion_queue.h>
26 #include <grpcpp/impl/grpc_library.h>
27 #include "test/cpp/microbenchmarks/helpers.h"
28 #include "test/cpp/util/test_config.h"
29
30 #include "src/core/lib/surface/completion_queue.h"
31
32 namespace grpc {
33 namespace testing {
34
35 auto& force_library_initialization = Library::get();
36
BM_CreateDestroyCpp(benchmark::State & state)37 static void BM_CreateDestroyCpp(benchmark::State& state) {
38 TrackCounters track_counters;
39 while (state.KeepRunning()) {
40 CompletionQueue cq;
41 }
42 track_counters.Finish(state);
43 }
44 BENCHMARK(BM_CreateDestroyCpp);
45
46 /* Create cq using a different constructor */
BM_CreateDestroyCpp2(benchmark::State & state)47 static void BM_CreateDestroyCpp2(benchmark::State& state) {
48 TrackCounters track_counters;
49 while (state.KeepRunning()) {
50 grpc_completion_queue* core_cq =
51 grpc_completion_queue_create_for_next(nullptr);
52 CompletionQueue cq(core_cq);
53 }
54 track_counters.Finish(state);
55 }
56 BENCHMARK(BM_CreateDestroyCpp2);
57
BM_CreateDestroyCore(benchmark::State & state)58 static void BM_CreateDestroyCore(benchmark::State& state) {
59 TrackCounters track_counters;
60 while (state.KeepRunning()) {
61 // TODO: sreek Templatize this benchmark and pass completion type and
62 // polling type as parameters
63 grpc_completion_queue_destroy(
64 grpc_completion_queue_create_for_next(nullptr));
65 }
66 track_counters.Finish(state);
67 }
68 BENCHMARK(BM_CreateDestroyCore);
69
DoneWithCompletionOnStack(void * arg,grpc_cq_completion * completion)70 static void DoneWithCompletionOnStack(void* arg,
71 grpc_cq_completion* completion) {}
72
73 class DummyTag final : public internal::CompletionQueueTag {
74 public:
FinalizeResult(void ** tag,bool * status)75 bool FinalizeResult(void** tag, bool* status) override { return true; }
76 };
77
BM_Pass1Cpp(benchmark::State & state)78 static void BM_Pass1Cpp(benchmark::State& state) {
79 TrackCounters track_counters;
80 CompletionQueue cq;
81 grpc_completion_queue* c_cq = cq.cq();
82 while (state.KeepRunning()) {
83 grpc_cq_completion completion;
84 DummyTag dummy_tag;
85 grpc_core::ExecCtx exec_ctx;
86 GPR_ASSERT(grpc_cq_begin_op(c_cq, &dummy_tag));
87 grpc_cq_end_op(c_cq, &dummy_tag, GRPC_ERROR_NONE, DoneWithCompletionOnStack,
88 nullptr, &completion);
89
90 void* tag;
91 bool ok;
92 cq.Next(&tag, &ok);
93 }
94 track_counters.Finish(state);
95 }
96 BENCHMARK(BM_Pass1Cpp);
97
BM_Pass1Core(benchmark::State & state)98 static void BM_Pass1Core(benchmark::State& state) {
99 TrackCounters track_counters;
100 // TODO: sreek Templatize this benchmark and pass polling_type as a param
101 grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
102 gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
103 while (state.KeepRunning()) {
104 grpc_cq_completion completion;
105 grpc_core::ExecCtx exec_ctx;
106 GPR_ASSERT(grpc_cq_begin_op(cq, nullptr));
107 grpc_cq_end_op(cq, nullptr, GRPC_ERROR_NONE, DoneWithCompletionOnStack,
108 nullptr, &completion);
109
110 grpc_completion_queue_next(cq, deadline, nullptr);
111 }
112 grpc_completion_queue_destroy(cq);
113 track_counters.Finish(state);
114 }
115 BENCHMARK(BM_Pass1Core);
116
BM_Pluck1Core(benchmark::State & state)117 static void BM_Pluck1Core(benchmark::State& state) {
118 TrackCounters track_counters;
119 // TODO: sreek Templatize this benchmark and pass polling_type as a param
120 grpc_completion_queue* cq = grpc_completion_queue_create_for_pluck(nullptr);
121 gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
122 while (state.KeepRunning()) {
123 grpc_cq_completion completion;
124 grpc_core::ExecCtx exec_ctx;
125 GPR_ASSERT(grpc_cq_begin_op(cq, nullptr));
126 grpc_cq_end_op(cq, nullptr, GRPC_ERROR_NONE, DoneWithCompletionOnStack,
127 nullptr, &completion);
128
129 grpc_completion_queue_pluck(cq, nullptr, deadline, nullptr);
130 }
131 grpc_completion_queue_destroy(cq);
132 track_counters.Finish(state);
133 }
134 BENCHMARK(BM_Pluck1Core);
135
BM_EmptyCore(benchmark::State & state)136 static void BM_EmptyCore(benchmark::State& state) {
137 TrackCounters track_counters;
138 // TODO: sreek Templatize this benchmark and pass polling_type as a param
139 grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
140 gpr_timespec deadline = gpr_inf_past(GPR_CLOCK_MONOTONIC);
141 while (state.KeepRunning()) {
142 grpc_completion_queue_next(cq, deadline, nullptr);
143 }
144 grpc_completion_queue_destroy(cq);
145 track_counters.Finish(state);
146 }
147 BENCHMARK(BM_EmptyCore);
148
149 } // namespace testing
150 } // namespace grpc
151
152 // Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
153 // and others do not. This allows us to support both modes.
154 namespace benchmark {
RunTheBenchmarksNamespaced()155 void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
156 } // namespace benchmark
157
main(int argc,char ** argv)158 int main(int argc, char** argv) {
159 ::benchmark::Initialize(&argc, argv);
160 ::grpc::testing::InitTest(&argc, &argv, false);
161 benchmark::RunTheBenchmarksNamespaced();
162 return 0;
163 }
164