1#include <base/bind.h>
2#include <base/logging.h>
3#include <base/run_loop.h>
4#include <base/threading/thread.h>
5#include <gmock/gmock.h>
6#include <gtest/gtest.h>
7#include <unistd.h>
8#include <chrono>
9#include <iostream>
10
11#include "osi/include/fixed_queue.h"
12#include "osi/include/thread.h"
13
14#define NUM_MESSAGES_TO_SEND 1000000
15
16base::MessageLoop* message_loop;
17base::RunLoop* run_loop;
18thread_t* thread;
19
20volatile static int counter = 0;
21volatile bool loop_ready = false;
22
23void set_loop_ready() { loop_ready = true; }
24
25void callback(fixed_queue_t* queue, void* data) {
26  if (queue != nullptr) {
27    fixed_queue_dequeue(queue);
28  }
29
30  counter++;
31}
32
33void run_message_loop(void* UNUSED) {
34  message_loop = new base::MessageLoop();
35  run_loop = new base::RunLoop();
36
37  message_loop->task_runner()->PostTask(FROM_HERE, base::Bind(&set_loop_ready));
38
39  run_loop->Run();
40
41  delete message_loop;
42  message_loop = nullptr;
43
44  delete run_loop;
45  run_loop = nullptr;
46}
47
48class PerformanceTest : public testing::Test {
49 public:
50  fixed_queue_t* bt_msg_queue;
51
52  void SetUp() override {
53    counter = 0;
54
55    bt_msg_queue = fixed_queue_new(SIZE_MAX);
56    thread = thread_new("performance test thread");
57    thread_post(thread, run_message_loop, nullptr);
58  }
59
60  void TearDown() override {
61    fixed_queue_free(bt_msg_queue, NULL);
62    bt_msg_queue = nullptr;
63
64    thread_free(thread);
65    thread = nullptr;
66  }
67};
68
69TEST_F(PerformanceTest, message_loop_speed_test) {
70  loop_ready = false;
71  int test_data = 0;
72
73  std::chrono::steady_clock::time_point start_time =
74      std::chrono::steady_clock::now();
75  while (!loop_ready) {
76  }
77  for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
78    fixed_queue_enqueue(bt_msg_queue, (void*)&test_data);
79    message_loop->task_runner()->PostTask(
80        FROM_HERE, base::Bind(&callback, bt_msg_queue, nullptr));
81  }
82
83  message_loop->task_runner()->PostTask(FROM_HERE,
84                                        run_loop->QuitWhenIdleClosure());
85  while (counter < NUM_MESSAGES_TO_SEND) {
86  }
87
88  std::chrono::steady_clock::time_point end_time =
89      std::chrono::steady_clock::now();
90  std::chrono::milliseconds duration =
91      std::chrono::duration_cast<std::chrono::milliseconds>(end_time -
92                                                            start_time);
93
94  LOG(INFO) << "Message loop took " << duration.count() << "ms for "
95            << NUM_MESSAGES_TO_SEND << " messages";
96}
97
98TEST_F(PerformanceTest, reactor_thread_speed_test) {
99  counter = 0;
100  int test_data = 0;
101
102  thread = thread_new("queue performance test thread");
103  bt_msg_queue = fixed_queue_new(SIZE_MAX);
104  fixed_queue_register_dequeue(bt_msg_queue, thread_get_reactor(thread),
105                               callback, NULL);
106
107  std::chrono::steady_clock::time_point start_time =
108      std::chrono::steady_clock::now();
109  for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
110    fixed_queue_enqueue(bt_msg_queue, (void*)&test_data);
111  }
112
113  while (counter < NUM_MESSAGES_TO_SEND) {
114  };
115
116  std::chrono::steady_clock::time_point end_time =
117      std::chrono::steady_clock::now();
118  std::chrono::milliseconds duration =
119      std::chrono::duration_cast<std::chrono::milliseconds>(end_time -
120                                                            start_time);
121
122  LOG(INFO) << "Reactor thread took " << duration.count() << "ms for "
123            << NUM_MESSAGES_TO_SEND << " messages";
124
125  fixed_queue_free(bt_msg_queue, NULL);
126  bt_msg_queue = nullptr;
127
128  thread_free(thread);
129  thread = nullptr;
130}
131