• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <base/bind.h>
18 #include <base/logging.h>
19 #include <base/run_loop.h>
20 #include <base/threading/thread.h>
21 #include <benchmark/benchmark.h>
22 #include <future>
23 #include <memory>
24 #include <thread>
25 
26 #include "abstract_message_loop.h"
27 #include "common/message_loop_thread.h"
28 #include "osi/include/fixed_queue.h"
29 #include "osi/include/thread.h"
30 
31 using ::benchmark::State;
32 using bluetooth::common::MessageLoopThread;
33 
34 #define NUM_MESSAGES_TO_SEND 100000
35 
36 volatile static int g_counter = 0;
37 static std::unique_ptr<std::promise<void>> g_counter_promise = nullptr;
38 
pthread_callback_batch(void * context)39 void pthread_callback_batch(void* context) {
40   auto queue = static_cast<fixed_queue_t*>(context);
41   CHECK_NE(queue, nullptr);
42   fixed_queue_dequeue(queue);
43   g_counter++;
44   if (g_counter >= NUM_MESSAGES_TO_SEND) {
45     g_counter_promise->set_value();
46   }
47 }
48 
callback_sequential(void * context)49 void callback_sequential(void* context) { g_counter_promise->set_value(); }
50 
callback_sequential_queue(fixed_queue_t * queue,void * context)51 void callback_sequential_queue(fixed_queue_t* queue, void* context) {
52   CHECK_NE(queue, nullptr);
53   fixed_queue_dequeue(queue);
54   g_counter_promise->set_value();
55 }
56 
callback_batch(fixed_queue_t * queue,void * data)57 void callback_batch(fixed_queue_t* queue, void* data) {
58   CHECK_NE(queue, nullptr);
59   fixed_queue_dequeue(queue);
60   g_counter++;
61   if (g_counter >= NUM_MESSAGES_TO_SEND) {
62     g_counter_promise->set_value();
63   }
64 }
65 
66 class BM_ThreadPerformance : public ::benchmark::Fixture {
67  protected:
SetUp(State & st)68   void SetUp(State& st) override {
69     benchmark::Fixture::SetUp(st);
70     set_up_promise_ = std::make_unique<std::promise<void>>();
71     g_counter = 0;
72     bt_msg_queue_ = fixed_queue_new(SIZE_MAX);
73   }
TearDown(State & st)74   void TearDown(State& st) override {
75     fixed_queue_free(bt_msg_queue_, nullptr);
76     bt_msg_queue_ = nullptr;
77     set_up_promise_.reset(nullptr);
78     g_counter_promise.reset(nullptr);
79     benchmark::Fixture::TearDown(st);
80   }
81   fixed_queue_t* bt_msg_queue_ = nullptr;
82   std::unique_ptr<std::promise<void>> set_up_promise_;
83 };
84 
85 class BM_MessageLoop : public BM_ThreadPerformance {
86  public:
RunThread(void * context)87   static void RunThread(void* context) {
88     auto test = static_cast<BM_MessageLoop*>(context);
89     test->RunMessageLoop();
90   }
RunPThread(void * context)91   static void* RunPThread(void* context) {
92     auto test = static_cast<BM_MessageLoop*>(context);
93     test->RunMessageLoop();
94     return nullptr;
95   }
RunMessageLoop()96   void RunMessageLoop() {
97     message_loop_ = new btbase::AbstractMessageLoop();
98     run_loop_ = new base::RunLoop();
99     message_loop_->task_runner()->PostTask(
100         FROM_HERE, base::BindOnce(&std::promise<void>::set_value,
101                                   base::Unretained(set_up_promise_.get())));
102     run_loop_->Run();
103     delete message_loop_;
104     message_loop_ = nullptr;
105     delete run_loop_;
106     run_loop_ = nullptr;
107   }
108 
109  protected:
110   btbase::AbstractMessageLoop* message_loop_ = nullptr;
111   base::RunLoop* run_loop_ = nullptr;
112 };
113 
114 class BM_MessageLoopOsiThread : public BM_MessageLoop {
115  protected:
SetUp(State & st)116   void SetUp(State& st) override {
117     BM_MessageLoop::SetUp(st);
118     std::future<void> set_up_future = set_up_promise_->get_future();
119     thread_ = thread_new("BM_MessageLoopOnOsiThread thread");
120     thread_post(thread_, &BM_MessageLoop::RunThread, this);
121     set_up_future.wait();
122   }
123 
TearDown(State & st)124   void TearDown(State& st) override {
125     message_loop_->task_runner()->PostTask(FROM_HERE,
126                                            run_loop_->QuitWhenIdleClosure());
127     thread_free(thread_);
128     thread_ = nullptr;
129     BM_MessageLoop::TearDown(st);
130   }
131 
132   thread_t* thread_ = nullptr;
133 };
134 
BENCHMARK_F(BM_MessageLoopOsiThread,batch_enque_dequeue)135 BENCHMARK_F(BM_MessageLoopOsiThread, batch_enque_dequeue)(State& state) {
136   for (auto _ : state) {
137     g_counter = 0;
138     g_counter_promise = std::make_unique<std::promise<void>>();
139     std::future<void> counter_future = g_counter_promise->get_future();
140     for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
141       fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
142       message_loop_->task_runner()->PostTask(
143           FROM_HERE, base::BindOnce(&callback_batch, bt_msg_queue_, nullptr));
144     }
145     counter_future.wait();
146   }
147 };
148 
BENCHMARK_F(BM_MessageLoopOsiThread,sequential_execution)149 BENCHMARK_F(BM_MessageLoopOsiThread, sequential_execution)(State& state) {
150   for (auto _ : state) {
151     for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
152       g_counter_promise = std::make_unique<std::promise<void>>();
153       std::future<void> counter_future = g_counter_promise->get_future();
154       message_loop_->task_runner()->PostTask(
155           FROM_HERE, base::BindOnce(&callback_sequential, nullptr));
156       counter_future.wait();
157     }
158   }
159 };
160 
161 class BM_MessageLoopStlThread : public BM_MessageLoop {
162  protected:
SetUp(State & st)163   void SetUp(State& st) override {
164     BM_MessageLoop::SetUp(st);
165     std::future<void> set_up_future = set_up_promise_->get_future();
166     thread_ = new std::thread(&BM_MessageLoop::RunThread, this);
167     set_up_future.wait();
168   }
169 
TearDown(State & st)170   void TearDown(State& st) override {
171     message_loop_->task_runner()->PostTask(FROM_HERE,
172                                            run_loop_->QuitWhenIdleClosure());
173     thread_->join();
174     delete thread_;
175     thread_ = nullptr;
176     BM_MessageLoop::TearDown(st);
177   }
178 
179   std::thread* thread_ = nullptr;
180 };
181 
BENCHMARK_F(BM_MessageLoopStlThread,batch_enque_dequeue)182 BENCHMARK_F(BM_MessageLoopStlThread, batch_enque_dequeue)(State& state) {
183   for (auto _ : state) {
184     g_counter = 0;
185     g_counter_promise = std::make_unique<std::promise<void>>();
186     std::future<void> counter_future = g_counter_promise->get_future();
187     for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
188       fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
189       message_loop_->task_runner()->PostTask(
190           FROM_HERE, base::BindOnce(&callback_batch, bt_msg_queue_, nullptr));
191     }
192     counter_future.wait();
193   }
194 };
195 
BENCHMARK_F(BM_MessageLoopStlThread,sequential_execution)196 BENCHMARK_F(BM_MessageLoopStlThread, sequential_execution)(State& state) {
197   for (auto _ : state) {
198     for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
199       g_counter_promise = std::make_unique<std::promise<void>>();
200       std::future<void> counter_future = g_counter_promise->get_future();
201       message_loop_->task_runner()->PostTask(
202           FROM_HERE, base::BindOnce(&callback_sequential, nullptr));
203       counter_future.wait();
204     }
205   }
206 };
207 
208 class BM_MessageLoopPosixThread : public BM_MessageLoop {
209  protected:
SetUp(State & st)210   void SetUp(State& st) override {
211     BM_MessageLoop::SetUp(st);
212     std::future<void> set_up_future = set_up_promise_->get_future();
213     pthread_create(&thread_, nullptr, &BM_MessageLoop::RunPThread, (void*)this);
214     set_up_future.wait();
215   }
216 
TearDown(State & st)217   void TearDown(State& st) override {
218     message_loop_->task_runner()->PostTask(FROM_HERE,
219                                            run_loop_->QuitWhenIdleClosure());
220     pthread_join(thread_, nullptr);
221     BM_MessageLoop::TearDown(st);
222   }
223 
224   pthread_t thread_ = -1;
225 };
226 
BENCHMARK_F(BM_MessageLoopPosixThread,batch_enque_dequeue)227 BENCHMARK_F(BM_MessageLoopPosixThread, batch_enque_dequeue)(State& state) {
228   for (auto _ : state) {
229     g_counter = 0;
230     g_counter_promise = std::make_unique<std::promise<void>>();
231     std::future<void> counter_future = g_counter_promise->get_future();
232     for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
233       fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
234       message_loop_->task_runner()->PostTask(
235           FROM_HERE, base::BindOnce(&callback_batch, bt_msg_queue_, nullptr));
236     }
237     counter_future.wait();
238   }
239 };
240 
BENCHMARK_F(BM_MessageLoopPosixThread,sequential_execution)241 BENCHMARK_F(BM_MessageLoopPosixThread, sequential_execution)(State& state) {
242   for (auto _ : state) {
243     for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
244       g_counter_promise = std::make_unique<std::promise<void>>();
245       std::future<void> counter_future = g_counter_promise->get_future();
246       message_loop_->task_runner()->PostTask(
247           FROM_HERE, base::BindOnce(&callback_sequential, nullptr));
248       counter_future.wait();
249     }
250   }
251 };
252 
253 class BM_OsiReactorThread : public BM_ThreadPerformance {
254  protected:
SetUp(State & st)255   void SetUp(State& st) override {
256     BM_ThreadPerformance::SetUp(st);
257     thread_ = thread_new("BM_OsiReactorThread thread");
258   }
259 
TearDown(State & st)260   void TearDown(State& st) override {
261     thread_free(thread_);
262     thread_ = nullptr;
263     BM_ThreadPerformance::TearDown(st);
264   }
265 
266   thread_t* thread_ = nullptr;
267 };
268 
BENCHMARK_F(BM_OsiReactorThread,batch_enque_dequeue_using_thread_post)269 BENCHMARK_F(BM_OsiReactorThread, batch_enque_dequeue_using_thread_post)
270 (State& state) {
271   for (auto _ : state) {
272     g_counter = 0;
273     g_counter_promise = std::make_unique<std::promise<void>>();
274     std::future<void> counter_future = g_counter_promise->get_future();
275     for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
276       fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
277       thread_post(thread_, pthread_callback_batch, bt_msg_queue_);
278     }
279     counter_future.wait();
280   }
281 };
282 
BENCHMARK_F(BM_OsiReactorThread,sequential_execution_using_thread_post)283 BENCHMARK_F(BM_OsiReactorThread, sequential_execution_using_thread_post)
284 (State& state) {
285   for (auto _ : state) {
286     for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
287       g_counter_promise = std::make_unique<std::promise<void>>();
288       std::future<void> counter_future = g_counter_promise->get_future();
289       thread_post(thread_, callback_sequential, nullptr);
290       counter_future.wait();
291     }
292   }
293 };
294 
BENCHMARK_F(BM_OsiReactorThread,batch_enque_dequeue_using_reactor)295 BENCHMARK_F(BM_OsiReactorThread, batch_enque_dequeue_using_reactor)
296 (State& state) {
297   fixed_queue_register_dequeue(bt_msg_queue_, thread_get_reactor(thread_),
298                                callback_batch, nullptr);
299   for (auto _ : state) {
300     g_counter = 0;
301     g_counter_promise = std::make_unique<std::promise<void>>();
302     std::future<void> counter_future = g_counter_promise->get_future();
303     for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
304       fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
305     }
306     counter_future.wait();
307   }
308 };
309 
BENCHMARK_F(BM_OsiReactorThread,sequential_execution_using_reactor)310 BENCHMARK_F(BM_OsiReactorThread, sequential_execution_using_reactor)
311 (State& state) {
312   fixed_queue_register_dequeue(bt_msg_queue_, thread_get_reactor(thread_),
313                                callback_sequential_queue, nullptr);
314   for (auto _ : state) {
315     for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
316       g_counter_promise = std::make_unique<std::promise<void>>();
317       std::future<void> counter_future = g_counter_promise->get_future();
318       fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
319       counter_future.wait();
320     }
321   }
322 };
323 
324 class BM_MessageLooopThread : public BM_ThreadPerformance {
325  protected:
SetUp(State & st)326   void SetUp(State& st) override {
327     BM_ThreadPerformance::SetUp(st);
328     std::future<void> set_up_future = set_up_promise_->get_future();
329     message_loop_thread_ =
330         new MessageLoopThread("BM_MessageLooopThread thread");
331     message_loop_thread_->StartUp();
332     message_loop_thread_->DoInThread(
333         FROM_HERE, base::BindOnce(&std::promise<void>::set_value,
334                                   base::Unretained(set_up_promise_.get())));
335     set_up_future.wait();
336   }
337 
TearDown(State & st)338   void TearDown(State& st) override {
339     message_loop_thread_->ShutDown();
340     delete message_loop_thread_;
341     message_loop_thread_ = nullptr;
342     BM_ThreadPerformance::TearDown(st);
343   }
344 
345   MessageLoopThread* message_loop_thread_ = nullptr;
346 };
347 
BENCHMARK_F(BM_MessageLooopThread,batch_enque_dequeue)348 BENCHMARK_F(BM_MessageLooopThread, batch_enque_dequeue)(State& state) {
349   for (auto _ : state) {
350     g_counter = 0;
351     g_counter_promise = std::make_unique<std::promise<void>>();
352     std::future<void> counter_future = g_counter_promise->get_future();
353     for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
354       fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
355       message_loop_thread_->DoInThread(
356           FROM_HERE, base::BindOnce(&callback_batch, bt_msg_queue_, nullptr));
357     }
358     counter_future.wait();
359   }
360 };
361 
BENCHMARK_F(BM_MessageLooopThread,sequential_execution)362 BENCHMARK_F(BM_MessageLooopThread, sequential_execution)(State& state) {
363   for (auto _ : state) {
364     for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
365       g_counter_promise = std::make_unique<std::promise<void>>();
366       std::future<void> counter_future = g_counter_promise->get_future();
367       message_loop_thread_->DoInThread(
368           FROM_HERE, base::BindOnce(&callback_sequential, nullptr));
369       counter_future.wait();
370     }
371   }
372 };
373 
374 class BM_LibChromeThread : public BM_ThreadPerformance {
375  protected:
SetUp(State & st)376   void SetUp(State& st) override {
377     BM_ThreadPerformance::SetUp(st);
378     std::future<void> set_up_future = set_up_promise_->get_future();
379     thread_ = new base::Thread("BM_LibChromeThread thread");
380     thread_->Start();
381     thread_->task_runner()->PostTask(
382         FROM_HERE, base::BindOnce(&std::promise<void>::set_value,
383                                   base::Unretained(set_up_promise_.get())));
384     set_up_future.wait();
385   }
386 
TearDown(State & st)387   void TearDown(State& st) override {
388     thread_->Stop();
389     delete thread_;
390     thread_ = nullptr;
391     BM_ThreadPerformance::TearDown(st);
392   }
393 
394   base::Thread* thread_ = nullptr;
395 };
396 
BENCHMARK_F(BM_LibChromeThread,batch_enque_dequeue)397 BENCHMARK_F(BM_LibChromeThread, batch_enque_dequeue)(State& state) {
398   for (auto _ : state) {
399     g_counter = 0;
400     g_counter_promise = std::make_unique<std::promise<void>>();
401     std::future<void> counter_future = g_counter_promise->get_future();
402     for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
403       fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
404       thread_->task_runner()->PostTask(
405           FROM_HERE, base::BindOnce(&callback_batch, bt_msg_queue_, nullptr));
406     }
407     counter_future.wait();
408   }
409 };
410 
BENCHMARK_F(BM_LibChromeThread,sequential_execution)411 BENCHMARK_F(BM_LibChromeThread, sequential_execution)(State& state) {
412   for (auto _ : state) {
413     for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
414       g_counter_promise = std::make_unique<std::promise<void>>();
415       std::future<void> counter_future = g_counter_promise->get_future();
416       thread_->task_runner()->PostTask(
417           FROM_HERE, base::BindOnce(&callback_sequential, nullptr));
418       counter_future.wait();
419     }
420   }
421 };
422 
main(int argc,char ** argv)423 int main(int argc, char** argv) {
424   // Disable LOG() output from libchrome
425   logging::LoggingSettings log_settings;
426   log_settings.logging_dest = logging::LoggingDestination::LOG_NONE;
427   CHECK(logging::InitLogging(log_settings)) << "Failed to set up logging";
428   ::benchmark::Initialize(&argc, argv);
429   if (::benchmark::ReportUnrecognizedArguments(argc, argv)) {
430     return 1;
431   }
432   ::benchmark::RunSpecifiedBenchmarks();
433 }
434