1*cc02d7e2SAndroid Build Coastguard Worker //
2*cc02d7e2SAndroid Build Coastguard Worker //
3*cc02d7e2SAndroid Build Coastguard Worker // Copyright 2015 gRPC authors.
4*cc02d7e2SAndroid Build Coastguard Worker //
5*cc02d7e2SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
6*cc02d7e2SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
7*cc02d7e2SAndroid Build Coastguard Worker // You may obtain a copy of the License at
8*cc02d7e2SAndroid Build Coastguard Worker //
9*cc02d7e2SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
10*cc02d7e2SAndroid Build Coastguard Worker //
11*cc02d7e2SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
12*cc02d7e2SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
13*cc02d7e2SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*cc02d7e2SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
15*cc02d7e2SAndroid Build Coastguard Worker // limitations under the License.
16*cc02d7e2SAndroid Build Coastguard Worker //
17*cc02d7e2SAndroid Build Coastguard Worker //
18*cc02d7e2SAndroid Build Coastguard Worker
19*cc02d7e2SAndroid Build Coastguard Worker // This benchmark exists to ensure that the benchmark integration is
20*cc02d7e2SAndroid Build Coastguard Worker // working
21*cc02d7e2SAndroid Build Coastguard Worker
22*cc02d7e2SAndroid Build Coastguard Worker #include <benchmark/benchmark.h>
23*cc02d7e2SAndroid Build Coastguard Worker
24*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/grpc.h>
25*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/support/log.h>
26*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/completion_queue.h>
27*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/impl/grpc_library.h>
28*cc02d7e2SAndroid Build Coastguard Worker
29*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/lib/gprpp/crash.h"
30*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/lib/iomgr/exec_ctx.h"
31*cc02d7e2SAndroid Build Coastguard Worker #include "src/core/lib/surface/completion_queue.h"
32*cc02d7e2SAndroid Build Coastguard Worker #include "test/core/util/test_config.h"
33*cc02d7e2SAndroid Build Coastguard Worker #include "test/cpp/microbenchmarks/helpers.h"
34*cc02d7e2SAndroid Build Coastguard Worker #include "test/cpp/util/test_config.h"
35*cc02d7e2SAndroid Build Coastguard Worker
36*cc02d7e2SAndroid Build Coastguard Worker namespace grpc {
37*cc02d7e2SAndroid Build Coastguard Worker namespace testing {
38*cc02d7e2SAndroid Build Coastguard Worker
BM_CreateDestroyCpp(benchmark::State & state)39*cc02d7e2SAndroid Build Coastguard Worker static void BM_CreateDestroyCpp(benchmark::State& state) {
40*cc02d7e2SAndroid Build Coastguard Worker for (auto _ : state) {
41*cc02d7e2SAndroid Build Coastguard Worker CompletionQueue cq;
42*cc02d7e2SAndroid Build Coastguard Worker }
43*cc02d7e2SAndroid Build Coastguard Worker }
44*cc02d7e2SAndroid Build Coastguard Worker BENCHMARK(BM_CreateDestroyCpp);
45*cc02d7e2SAndroid Build Coastguard Worker
46*cc02d7e2SAndroid Build Coastguard Worker // Create cq using a different constructor
BM_CreateDestroyCpp2(benchmark::State & state)47*cc02d7e2SAndroid Build Coastguard Worker static void BM_CreateDestroyCpp2(benchmark::State& state) {
48*cc02d7e2SAndroid Build Coastguard Worker for (auto _ : state) {
49*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue* core_cq =
50*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue_create_for_next(nullptr);
51*cc02d7e2SAndroid Build Coastguard Worker CompletionQueue cq(core_cq);
52*cc02d7e2SAndroid Build Coastguard Worker }
53*cc02d7e2SAndroid Build Coastguard Worker }
54*cc02d7e2SAndroid Build Coastguard Worker BENCHMARK(BM_CreateDestroyCpp2);
55*cc02d7e2SAndroid Build Coastguard Worker
BM_CreateDestroyCore(benchmark::State & state)56*cc02d7e2SAndroid Build Coastguard Worker static void BM_CreateDestroyCore(benchmark::State& state) {
57*cc02d7e2SAndroid Build Coastguard Worker for (auto _ : state) {
58*cc02d7e2SAndroid Build Coastguard Worker // TODO(sreek): Templatize this benchmark and pass completion type and
59*cc02d7e2SAndroid Build Coastguard Worker // polling type as parameters
60*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue_destroy(
61*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue_create_for_next(nullptr));
62*cc02d7e2SAndroid Build Coastguard Worker }
63*cc02d7e2SAndroid Build Coastguard Worker }
64*cc02d7e2SAndroid Build Coastguard Worker BENCHMARK(BM_CreateDestroyCore);
65*cc02d7e2SAndroid Build Coastguard Worker
DoneWithCompletionOnStack(void *,grpc_cq_completion *)66*cc02d7e2SAndroid Build Coastguard Worker static void DoneWithCompletionOnStack(void* /*arg*/,
67*cc02d7e2SAndroid Build Coastguard Worker grpc_cq_completion* /*completion*/) {}
68*cc02d7e2SAndroid Build Coastguard Worker
DoneWithCompletionOnHeap(void *,grpc_cq_completion * completion)69*cc02d7e2SAndroid Build Coastguard Worker static void DoneWithCompletionOnHeap(void* /*arg*/,
70*cc02d7e2SAndroid Build Coastguard Worker grpc_cq_completion* completion) {
71*cc02d7e2SAndroid Build Coastguard Worker delete completion;
72*cc02d7e2SAndroid Build Coastguard Worker }
73*cc02d7e2SAndroid Build Coastguard Worker
74*cc02d7e2SAndroid Build Coastguard Worker class PhonyTag final : public internal::CompletionQueueTag {
75*cc02d7e2SAndroid Build Coastguard Worker public:
FinalizeResult(void **,bool *)76*cc02d7e2SAndroid Build Coastguard Worker bool FinalizeResult(void** /*tag*/, bool* /*status*/) override {
77*cc02d7e2SAndroid Build Coastguard Worker return true;
78*cc02d7e2SAndroid Build Coastguard Worker }
79*cc02d7e2SAndroid Build Coastguard Worker };
80*cc02d7e2SAndroid Build Coastguard Worker
BM_Pass1Cpp(benchmark::State & state)81*cc02d7e2SAndroid Build Coastguard Worker static void BM_Pass1Cpp(benchmark::State& state) {
82*cc02d7e2SAndroid Build Coastguard Worker CompletionQueue cq;
83*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue* c_cq = cq.cq();
84*cc02d7e2SAndroid Build Coastguard Worker for (auto _ : state) {
85*cc02d7e2SAndroid Build Coastguard Worker grpc_cq_completion completion;
86*cc02d7e2SAndroid Build Coastguard Worker PhonyTag phony_tag;
87*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx exec_ctx;
88*cc02d7e2SAndroid Build Coastguard Worker GPR_ASSERT(grpc_cq_begin_op(c_cq, &phony_tag));
89*cc02d7e2SAndroid Build Coastguard Worker grpc_cq_end_op(c_cq, &phony_tag, absl::OkStatus(),
90*cc02d7e2SAndroid Build Coastguard Worker DoneWithCompletionOnStack, nullptr, &completion);
91*cc02d7e2SAndroid Build Coastguard Worker
92*cc02d7e2SAndroid Build Coastguard Worker void* tag;
93*cc02d7e2SAndroid Build Coastguard Worker bool ok;
94*cc02d7e2SAndroid Build Coastguard Worker cq.Next(&tag, &ok);
95*cc02d7e2SAndroid Build Coastguard Worker }
96*cc02d7e2SAndroid Build Coastguard Worker }
97*cc02d7e2SAndroid Build Coastguard Worker BENCHMARK(BM_Pass1Cpp);
98*cc02d7e2SAndroid Build Coastguard Worker
BM_Pass1Core(benchmark::State & state)99*cc02d7e2SAndroid Build Coastguard Worker static void BM_Pass1Core(benchmark::State& state) {
100*cc02d7e2SAndroid Build Coastguard Worker // TODO(sreek): Templatize this benchmark and pass polling_type as a param
101*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
102*cc02d7e2SAndroid Build Coastguard Worker gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
103*cc02d7e2SAndroid Build Coastguard Worker for (auto _ : state) {
104*cc02d7e2SAndroid Build Coastguard Worker grpc_cq_completion completion;
105*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx exec_ctx;
106*cc02d7e2SAndroid Build Coastguard Worker GPR_ASSERT(grpc_cq_begin_op(cq, nullptr));
107*cc02d7e2SAndroid Build Coastguard Worker grpc_cq_end_op(cq, nullptr, absl::OkStatus(), DoneWithCompletionOnStack,
108*cc02d7e2SAndroid Build Coastguard Worker nullptr, &completion);
109*cc02d7e2SAndroid Build Coastguard Worker
110*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue_next(cq, deadline, nullptr);
111*cc02d7e2SAndroid Build Coastguard Worker }
112*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue_destroy(cq);
113*cc02d7e2SAndroid Build Coastguard Worker }
114*cc02d7e2SAndroid Build Coastguard Worker BENCHMARK(BM_Pass1Core);
115*cc02d7e2SAndroid Build Coastguard Worker
BM_Pluck1Core(benchmark::State & state)116*cc02d7e2SAndroid Build Coastguard Worker static void BM_Pluck1Core(benchmark::State& state) {
117*cc02d7e2SAndroid Build Coastguard Worker // TODO(sreek): Templatize this benchmark and pass polling_type as a param
118*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue* cq = grpc_completion_queue_create_for_pluck(nullptr);
119*cc02d7e2SAndroid Build Coastguard Worker gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
120*cc02d7e2SAndroid Build Coastguard Worker for (auto _ : state) {
121*cc02d7e2SAndroid Build Coastguard Worker grpc_cq_completion completion;
122*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx exec_ctx;
123*cc02d7e2SAndroid Build Coastguard Worker GPR_ASSERT(grpc_cq_begin_op(cq, nullptr));
124*cc02d7e2SAndroid Build Coastguard Worker grpc_cq_end_op(cq, nullptr, absl::OkStatus(), DoneWithCompletionOnStack,
125*cc02d7e2SAndroid Build Coastguard Worker nullptr, &completion);
126*cc02d7e2SAndroid Build Coastguard Worker
127*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue_pluck(cq, nullptr, deadline, nullptr);
128*cc02d7e2SAndroid Build Coastguard Worker }
129*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue_destroy(cq);
130*cc02d7e2SAndroid Build Coastguard Worker }
131*cc02d7e2SAndroid Build Coastguard Worker BENCHMARK(BM_Pluck1Core);
132*cc02d7e2SAndroid Build Coastguard Worker
BM_EmptyCore(benchmark::State & state)133*cc02d7e2SAndroid Build Coastguard Worker static void BM_EmptyCore(benchmark::State& state) {
134*cc02d7e2SAndroid Build Coastguard Worker // TODO(sreek): Templatize this benchmark and pass polling_type as a param
135*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
136*cc02d7e2SAndroid Build Coastguard Worker gpr_timespec deadline = gpr_inf_past(GPR_CLOCK_MONOTONIC);
137*cc02d7e2SAndroid Build Coastguard Worker for (auto _ : state) {
138*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue_next(cq, deadline, nullptr);
139*cc02d7e2SAndroid Build Coastguard Worker }
140*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue_destroy(cq);
141*cc02d7e2SAndroid Build Coastguard Worker }
142*cc02d7e2SAndroid Build Coastguard Worker BENCHMARK(BM_EmptyCore);
143*cc02d7e2SAndroid Build Coastguard Worker
144*cc02d7e2SAndroid Build Coastguard Worker // Helper for tests to shutdown correctly and tersely
shutdown_and_destroy(grpc_completion_queue * cc)145*cc02d7e2SAndroid Build Coastguard Worker static void shutdown_and_destroy(grpc_completion_queue* cc) {
146*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue_shutdown(cc);
147*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue_destroy(cc);
148*cc02d7e2SAndroid Build Coastguard Worker }
149*cc02d7e2SAndroid Build Coastguard Worker
150*cc02d7e2SAndroid Build Coastguard Worker static gpr_mu shutdown_mu, mu;
151*cc02d7e2SAndroid Build Coastguard Worker static gpr_cv shutdown_cv, cv;
152*cc02d7e2SAndroid Build Coastguard Worker
153*cc02d7e2SAndroid Build Coastguard Worker // Tag completion queue iterate times
154*cc02d7e2SAndroid Build Coastguard Worker class TagCallback : public grpc_completion_queue_functor {
155*cc02d7e2SAndroid Build Coastguard Worker public:
TagCallback(int * iter)156*cc02d7e2SAndroid Build Coastguard Worker explicit TagCallback(int* iter) : iter_(iter) {
157*cc02d7e2SAndroid Build Coastguard Worker functor_run = &TagCallback::Run;
158*cc02d7e2SAndroid Build Coastguard Worker inlineable = false;
159*cc02d7e2SAndroid Build Coastguard Worker }
~TagCallback()160*cc02d7e2SAndroid Build Coastguard Worker ~TagCallback() {}
Run(grpc_completion_queue_functor * cb,int ok)161*cc02d7e2SAndroid Build Coastguard Worker static void Run(grpc_completion_queue_functor* cb, int ok) {
162*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_lock(&mu);
163*cc02d7e2SAndroid Build Coastguard Worker GPR_ASSERT(static_cast<bool>(ok));
164*cc02d7e2SAndroid Build Coastguard Worker *static_cast<TagCallback*>(cb)->iter_ += 1;
165*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_signal(&cv);
166*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_unlock(&mu);
167*cc02d7e2SAndroid Build Coastguard Worker };
168*cc02d7e2SAndroid Build Coastguard Worker
169*cc02d7e2SAndroid Build Coastguard Worker private:
170*cc02d7e2SAndroid Build Coastguard Worker int* iter_;
171*cc02d7e2SAndroid Build Coastguard Worker };
172*cc02d7e2SAndroid Build Coastguard Worker
173*cc02d7e2SAndroid Build Coastguard Worker // Check if completion queue is shut down
174*cc02d7e2SAndroid Build Coastguard Worker class ShutdownCallback : public grpc_completion_queue_functor {
175*cc02d7e2SAndroid Build Coastguard Worker public:
ShutdownCallback(bool * done)176*cc02d7e2SAndroid Build Coastguard Worker explicit ShutdownCallback(bool* done) : done_(done) {
177*cc02d7e2SAndroid Build Coastguard Worker functor_run = &ShutdownCallback::Run;
178*cc02d7e2SAndroid Build Coastguard Worker inlineable = false;
179*cc02d7e2SAndroid Build Coastguard Worker }
~ShutdownCallback()180*cc02d7e2SAndroid Build Coastguard Worker ~ShutdownCallback() {}
Run(grpc_completion_queue_functor * cb,int ok)181*cc02d7e2SAndroid Build Coastguard Worker static void Run(grpc_completion_queue_functor* cb, int ok) {
182*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_lock(&shutdown_mu);
183*cc02d7e2SAndroid Build Coastguard Worker *static_cast<ShutdownCallback*>(cb)->done_ = static_cast<bool>(ok);
184*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_signal(&shutdown_cv);
185*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_unlock(&shutdown_mu);
186*cc02d7e2SAndroid Build Coastguard Worker }
187*cc02d7e2SAndroid Build Coastguard Worker
188*cc02d7e2SAndroid Build Coastguard Worker private:
189*cc02d7e2SAndroid Build Coastguard Worker bool* done_;
190*cc02d7e2SAndroid Build Coastguard Worker };
191*cc02d7e2SAndroid Build Coastguard Worker
BM_Callback_CQ_Pass1Core(benchmark::State & state)192*cc02d7e2SAndroid Build Coastguard Worker static void BM_Callback_CQ_Pass1Core(benchmark::State& state) {
193*cc02d7e2SAndroid Build Coastguard Worker int iteration = 0, current_iterations = 0;
194*cc02d7e2SAndroid Build Coastguard Worker TagCallback tag_cb(&iteration);
195*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_init(&mu);
196*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_init(&cv);
197*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_init(&shutdown_mu);
198*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_init(&shutdown_cv);
199*cc02d7e2SAndroid Build Coastguard Worker bool got_shutdown = false;
200*cc02d7e2SAndroid Build Coastguard Worker ShutdownCallback shutdown_cb(&got_shutdown);
201*cc02d7e2SAndroid Build Coastguard Worker // This test with stack-allocated completions only works for non-polling or
202*cc02d7e2SAndroid Build Coastguard Worker // EM-polling callback core CQs because otherwise the callback could execute
203*cc02d7e2SAndroid Build Coastguard Worker // on another thread after the stack objects here go out of scope. An
204*cc02d7e2SAndroid Build Coastguard Worker // alternative would be to synchronize between the benchmark loop and the
205*cc02d7e2SAndroid Build Coastguard Worker // callback, but then it would be measuring the overhead of synchronization
206*cc02d7e2SAndroid Build Coastguard Worker // rather than the overhead of the completion queue.
207*cc02d7e2SAndroid Build Coastguard Worker // For generality, test here with non-polling.
208*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue_attributes attr;
209*cc02d7e2SAndroid Build Coastguard Worker attr.version = 2;
210*cc02d7e2SAndroid Build Coastguard Worker attr.cq_completion_type = GRPC_CQ_CALLBACK;
211*cc02d7e2SAndroid Build Coastguard Worker attr.cq_polling_type = GRPC_CQ_NON_POLLING;
212*cc02d7e2SAndroid Build Coastguard Worker attr.cq_shutdown_cb = &shutdown_cb;
213*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue* cc = grpc_completion_queue_create(
214*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue_factory_lookup(&attr), &attr, nullptr);
215*cc02d7e2SAndroid Build Coastguard Worker for (auto _ : state) {
216*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
217*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx exec_ctx;
218*cc02d7e2SAndroid Build Coastguard Worker grpc_cq_completion completion;
219*cc02d7e2SAndroid Build Coastguard Worker GPR_ASSERT(grpc_cq_begin_op(cc, &tag_cb));
220*cc02d7e2SAndroid Build Coastguard Worker grpc_cq_end_op(cc, &tag_cb, absl::OkStatus(), DoneWithCompletionOnStack,
221*cc02d7e2SAndroid Build Coastguard Worker nullptr, &completion);
222*cc02d7e2SAndroid Build Coastguard Worker }
223*cc02d7e2SAndroid Build Coastguard Worker shutdown_and_destroy(cc);
224*cc02d7e2SAndroid Build Coastguard Worker
225*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_lock(&mu);
226*cc02d7e2SAndroid Build Coastguard Worker current_iterations = static_cast<int>(state.iterations());
227*cc02d7e2SAndroid Build Coastguard Worker while (current_iterations != iteration) {
228*cc02d7e2SAndroid Build Coastguard Worker // Wait for all the callbacks to complete.
229*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_wait(&cv, &mu, gpr_inf_future(GPR_CLOCK_REALTIME));
230*cc02d7e2SAndroid Build Coastguard Worker }
231*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_unlock(&mu);
232*cc02d7e2SAndroid Build Coastguard Worker
233*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_lock(&shutdown_mu);
234*cc02d7e2SAndroid Build Coastguard Worker while (!got_shutdown) {
235*cc02d7e2SAndroid Build Coastguard Worker // Wait for the shutdown callback to complete.
236*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_wait(&shutdown_cv, &shutdown_mu, gpr_inf_future(GPR_CLOCK_REALTIME));
237*cc02d7e2SAndroid Build Coastguard Worker }
238*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_unlock(&shutdown_mu);
239*cc02d7e2SAndroid Build Coastguard Worker
240*cc02d7e2SAndroid Build Coastguard Worker GPR_ASSERT(got_shutdown);
241*cc02d7e2SAndroid Build Coastguard Worker GPR_ASSERT(iteration == static_cast<int>(state.iterations()));
242*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_destroy(&cv);
243*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_destroy(&mu);
244*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_destroy(&shutdown_cv);
245*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_destroy(&shutdown_mu);
246*cc02d7e2SAndroid Build Coastguard Worker }
BM_Callback_CQ_Pass1CoreHeapCompletion(benchmark::State & state)247*cc02d7e2SAndroid Build Coastguard Worker static void BM_Callback_CQ_Pass1CoreHeapCompletion(benchmark::State& state) {
248*cc02d7e2SAndroid Build Coastguard Worker int iteration = 0, current_iterations = 0;
249*cc02d7e2SAndroid Build Coastguard Worker TagCallback tag_cb(&iteration);
250*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_init(&mu);
251*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_init(&cv);
252*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_init(&shutdown_mu);
253*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_init(&shutdown_cv);
254*cc02d7e2SAndroid Build Coastguard Worker bool got_shutdown = false;
255*cc02d7e2SAndroid Build Coastguard Worker ShutdownCallback shutdown_cb(&got_shutdown);
256*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue* cc =
257*cc02d7e2SAndroid Build Coastguard Worker grpc_completion_queue_create_for_callback(&shutdown_cb, nullptr);
258*cc02d7e2SAndroid Build Coastguard Worker for (auto _ : state) {
259*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
260*cc02d7e2SAndroid Build Coastguard Worker grpc_core::ExecCtx exec_ctx;
261*cc02d7e2SAndroid Build Coastguard Worker grpc_cq_completion* completion = new grpc_cq_completion;
262*cc02d7e2SAndroid Build Coastguard Worker GPR_ASSERT(grpc_cq_begin_op(cc, &tag_cb));
263*cc02d7e2SAndroid Build Coastguard Worker grpc_cq_end_op(cc, &tag_cb, absl::OkStatus(), DoneWithCompletionOnHeap,
264*cc02d7e2SAndroid Build Coastguard Worker nullptr, completion);
265*cc02d7e2SAndroid Build Coastguard Worker }
266*cc02d7e2SAndroid Build Coastguard Worker shutdown_and_destroy(cc);
267*cc02d7e2SAndroid Build Coastguard Worker
268*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_lock(&mu);
269*cc02d7e2SAndroid Build Coastguard Worker current_iterations = static_cast<int>(state.iterations());
270*cc02d7e2SAndroid Build Coastguard Worker while (current_iterations != iteration) {
271*cc02d7e2SAndroid Build Coastguard Worker // Wait for all the callbacks to complete.
272*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_wait(&cv, &mu, gpr_inf_future(GPR_CLOCK_REALTIME));
273*cc02d7e2SAndroid Build Coastguard Worker }
274*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_unlock(&mu);
275*cc02d7e2SAndroid Build Coastguard Worker
276*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_lock(&shutdown_mu);
277*cc02d7e2SAndroid Build Coastguard Worker while (!got_shutdown) {
278*cc02d7e2SAndroid Build Coastguard Worker // Wait for the shutdown callback to complete.
279*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_wait(&shutdown_cv, &shutdown_mu, gpr_inf_future(GPR_CLOCK_REALTIME));
280*cc02d7e2SAndroid Build Coastguard Worker }
281*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_unlock(&shutdown_mu);
282*cc02d7e2SAndroid Build Coastguard Worker
283*cc02d7e2SAndroid Build Coastguard Worker GPR_ASSERT(got_shutdown);
284*cc02d7e2SAndroid Build Coastguard Worker GPR_ASSERT(iteration == static_cast<int>(state.iterations()));
285*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_destroy(&cv);
286*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_destroy(&mu);
287*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_destroy(&shutdown_cv);
288*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_destroy(&shutdown_mu);
289*cc02d7e2SAndroid Build Coastguard Worker }
290*cc02d7e2SAndroid Build Coastguard Worker BENCHMARK(BM_Callback_CQ_Pass1Core);
291*cc02d7e2SAndroid Build Coastguard Worker BENCHMARK(BM_Callback_CQ_Pass1CoreHeapCompletion);
292*cc02d7e2SAndroid Build Coastguard Worker
293*cc02d7e2SAndroid Build Coastguard Worker } // namespace testing
294*cc02d7e2SAndroid Build Coastguard Worker } // namespace grpc
295*cc02d7e2SAndroid Build Coastguard Worker
296*cc02d7e2SAndroid Build Coastguard Worker // Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
297*cc02d7e2SAndroid Build Coastguard Worker // and others do not. This allows us to support both modes.
298*cc02d7e2SAndroid Build Coastguard Worker namespace benchmark {
RunTheBenchmarksNamespaced()299*cc02d7e2SAndroid Build Coastguard Worker void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
300*cc02d7e2SAndroid Build Coastguard Worker } // namespace benchmark
301*cc02d7e2SAndroid Build Coastguard Worker
main(int argc,char ** argv)302*cc02d7e2SAndroid Build Coastguard Worker int main(int argc, char** argv) {
303*cc02d7e2SAndroid Build Coastguard Worker grpc::testing::TestEnvironment env(&argc, argv);
304*cc02d7e2SAndroid Build Coastguard Worker LibraryInitializer libInit;
305*cc02d7e2SAndroid Build Coastguard Worker ::benchmark::Initialize(&argc, argv);
306*cc02d7e2SAndroid Build Coastguard Worker grpc::testing::InitTest(&argc, &argv, false);
307*cc02d7e2SAndroid Build Coastguard Worker benchmark::RunTheBenchmarksNamespaced();
308*cc02d7e2SAndroid Build Coastguard Worker return 0;
309*cc02d7e2SAndroid Build Coastguard Worker }
310