1 /* 2 * Copyright 2019 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 "benchmark/benchmark.h" 18 19 #include <future> 20 21 #include "os/handler.h" 22 #include "os/queue.h" 23 #include "os/thread.h" 24 25 using ::benchmark::State; 26 27 namespace bluetooth { 28 namespace os { 29 30 class BM_QueuePerformance : public ::benchmark::Fixture { 31 protected: 32 void SetUp(State& st) override { 33 ::benchmark::Fixture::SetUp(st); 34 enqueue_thread_ = new Thread("enqueue_thread", Thread::Priority::NORMAL); 35 enqueue_handler_ = new Handler(enqueue_thread_); 36 dequeue_thread_ = new Thread("dequeue_thread", Thread::Priority::NORMAL); 37 dequeue_handler_ = new Handler(dequeue_thread_); 38 } 39 40 void TearDown(State& st) override { 41 delete enqueue_handler_; 42 delete enqueue_thread_; 43 delete dequeue_handler_; 44 delete dequeue_thread_; 45 enqueue_handler_ = nullptr; 46 enqueue_thread_ = nullptr; 47 dequeue_handler_ = nullptr; 48 dequeue_thread_ = nullptr; 49 benchmark::Fixture::TearDown(st); 50 } 51 52 Thread* enqueue_thread_; 53 Handler* enqueue_handler_; 54 Thread* dequeue_thread_; 55 Handler* dequeue_handler_; 56 }; 57 58 class TestEnqueueEnd { 59 public: 60 explicit TestEnqueueEnd(int64_t count, Queue<std::string>* queue, Handler* handler, std::promise<void>* promise) 61 : count_(count), handler_(handler), queue_(queue), promise_(promise) {} 62 63 void RegisterEnqueue() { 64 handler_->Post(common::BindOnce(&TestEnqueueEnd::handle_register_enqueue, common::Unretained(this))); 65 } 66 67 void push(std::string data) { 68 { 69 std::lock_guard<std::mutex> lock(mutex_); 70 buffer_.push(std::move(data)); 71 } 72 if (buffer_.size() == 1) { 73 RegisterEnqueue(); 74 } 75 } 76 77 std::unique_ptr<std::string> EnqueueCallbackForTest() { 78 std::lock_guard<std::mutex> lock(mutex_); 79 std::unique_ptr<std::string> data = std::make_unique<std::string>(std::move(buffer_.front())); 80 buffer_.pop(); 81 82 if (buffer_.empty()) { 83 queue_->UnregisterEnqueue(); 84 } 85 86 count_--; 87 if (count_ == 0) { 88 promise_->set_value(); 89 } 90 91 return data; 92 } 93 94 std::queue<std::string> buffer_; 95 int64_t count_; 96 97 private: 98 Handler* handler_; 99 Queue<std::string>* queue_; 100 std::promise<void>* promise_; 101 std::mutex mutex_; 102 103 void handle_register_enqueue() { 104 queue_->RegisterEnqueue(handler_, common::Bind(&TestEnqueueEnd::EnqueueCallbackForTest, common::Unretained(this))); 105 } 106 }; 107 108 class TestDequeueEnd { 109 public: 110 explicit TestDequeueEnd(int64_t count, Queue<std::string>* queue, Handler* handler, std::promise<void>* promise) 111 : count_(count), handler_(handler), queue_(queue), promise_(promise) {} 112 113 void RegisterDequeue() { 114 handler_->Post(common::BindOnce(&TestDequeueEnd::handle_register_dequeue, common::Unretained(this))); 115 } 116 117 void DequeueCallbackForTest() { 118 std::string data = *(queue_->TryDequeue()); 119 buffer_.push(data); 120 121 count_--; 122 if (count_ == 0) { 123 queue_->UnregisterDequeue(); 124 promise_->set_value(); 125 } 126 } 127 128 std::queue<std::string> buffer_; 129 int64_t count_; 130 131 private: 132 Handler* handler_; 133 Queue<std::string>* queue_; 134 std::promise<void>* promise_; 135 136 void handle_register_dequeue() { 137 queue_->RegisterDequeue(handler_, common::Bind(&TestDequeueEnd::DequeueCallbackForTest, common::Unretained(this))); 138 } 139 }; 140 141 BENCHMARK_DEFINE_F(BM_QueuePerformance, send_packet_vary_by_packet_num)(State& state) { 142 for (auto _ : state) { 143 int64_t num_data_to_send_ = state.range(0); 144 Queue<std::string> queue(num_data_to_send_); 145 146 // register dequeue 147 std::promise<void> dequeue_promise; 148 auto dequeue_future = dequeue_promise.get_future(); 149 TestDequeueEnd test_dequeue_end(num_data_to_send_, &queue, enqueue_handler_, &dequeue_promise); 150 test_dequeue_end.RegisterDequeue(); 151 152 // Push data to enqueue end buffer and register enqueue 153 std::promise<void> enqueue_promise; 154 TestEnqueueEnd test_enqueue_end(num_data_to_send_, &queue, enqueue_handler_, &enqueue_promise); 155 for (int i = 0; i < num_data_to_send_; i++) { 156 std::string data = std::to_string(1); 157 test_enqueue_end.push(std::move(data)); 158 } 159 dequeue_future.wait(); 160 } 161 162 state.SetBytesProcessed(static_cast<int_fast64_t>(state.iterations()) * state.range(0)); 163 }; 164 165 BENCHMARK_REGISTER_F(BM_QueuePerformance, send_packet_vary_by_packet_num) 166 ->Arg(10) 167 ->Arg(100) 168 ->Arg(1000) 169 ->Arg(10000) 170 ->Arg(100000) 171 ->Iterations(100) 172 ->UseRealTime(); 173 174 BENCHMARK_DEFINE_F(BM_QueuePerformance, send_10000_packet_vary_by_packet_size)(State& state) { 175 for (auto _ : state) { 176 int64_t num_data_to_send_ = 10000; 177 int64_t packet_size = state.range(0); 178 Queue<std::string> queue(num_data_to_send_); 179 180 // register dequeue 181 std::promise<void> dequeue_promise; 182 auto dequeue_future = dequeue_promise.get_future(); 183 TestDequeueEnd test_dequeue_end(num_data_to_send_, &queue, enqueue_handler_, &dequeue_promise); 184 test_dequeue_end.RegisterDequeue(); 185 186 // Push data to enqueue end buffer and register enqueue 187 std::promise<void> enqueue_promise; 188 TestEnqueueEnd test_enqueue_end(num_data_to_send_, &queue, enqueue_handler_, &enqueue_promise); 189 for (int i = 0; i < num_data_to_send_; i++) { 190 std::string data = std::string(packet_size, 'x'); 191 test_enqueue_end.push(std::move(data)); 192 } 193 dequeue_future.wait(); 194 } 195 196 state.SetBytesProcessed(static_cast<int_fast64_t>(state.iterations()) * state.range(0) * 10000); 197 }; 198 199 BENCHMARK_REGISTER_F(BM_QueuePerformance, send_10000_packet_vary_by_packet_size) 200 ->Arg(10) 201 ->Arg(100) 202 ->Arg(1000) 203 ->Iterations(100) 204 ->UseRealTime(); 205 206 } // namespace os 207 } // namespace bluetooth 208