Loading system/gd/os/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -27,5 +27,6 @@ filegroup { srcs: [ "alarm_benchmark.cc", "thread_benchmark.cc", "queue_benchmark.cc", ] } system/gd/os/queue_benchmark.cc 0 → 100644 +199 −0 Original line number Diff line number Diff line /* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "benchmark/benchmark.h" #include <future> #include "os/handler.h" #include "os/queue.h" #include "os/thread.h" using ::benchmark::State; namespace bluetooth { namespace os { class BM_QueuePerformance : public ::benchmark::Fixture { protected: void SetUp(State& st) override { ::benchmark::Fixture::SetUp(st); enqueue_thread_ = new Thread("enqueue_thread", Thread::Priority::NORMAL); enqueue_handler_ = new Handler(enqueue_thread_); dequeue_thread_ = new Thread("dequeue_thread", Thread::Priority::NORMAL); dequeue_handler_ = new Handler(dequeue_thread_); } void TearDown(State& st) override { delete enqueue_handler_; delete enqueue_thread_; delete dequeue_handler_; delete dequeue_thread_; enqueue_handler_ = nullptr; enqueue_thread_ = nullptr; dequeue_handler_ = nullptr; dequeue_thread_ = nullptr; benchmark::Fixture::TearDown(st); } Thread* enqueue_thread_; Handler* enqueue_handler_; Thread* dequeue_thread_; Handler* dequeue_handler_; }; class TestEnqueueEnd { public: explicit TestEnqueueEnd(int64_t count, Queue<std::string>* queue, Handler* handler, std::promise<void>* promise) : count_(count), handler_(handler), queue_(queue), promise_(promise) {} void RegisterEnqueue() { handler_->Post([this] { queue_->RegisterEnqueue(handler_, [this] { return EnqueueCallbackForTest(); }); }); } void push(std::string data) { { std::lock_guard<std::mutex> lock(mutex_); buffer_.push(std::move(data)); } if (buffer_.size() == 1) { RegisterEnqueue(); } } std::unique_ptr<std::string> EnqueueCallbackForTest() { std::lock_guard<std::mutex> lock(mutex_); std::unique_ptr<std::string> data = std::make_unique<std::string>(std::move(buffer_.front())); buffer_.pop(); if (buffer_.empty()) { queue_->UnregisterEnqueue(); } count_--; if (count_ == 0) { promise_->set_value(); } return data; } std::queue<std::string> buffer_; int64_t count_; private: Handler* handler_; Queue<std::string>* queue_; std::promise<void>* promise_; std::mutex mutex_; }; class TestDequeueEnd { public: explicit TestDequeueEnd(int64_t count, Queue<std::string>* queue, Handler* handler, std::promise<void>* promise) : count_(count), handler_(handler), queue_(queue), promise_(promise) {} void RegisterDequeue() { handler_->Post([this] { queue_->RegisterDequeue(handler_, [this] { DequeueCallbackForTest(); }); }); } void DequeueCallbackForTest() { std::string data = *(queue_->TryDequeue()); buffer_.push(data); count_--; if (count_ == 0) { queue_->UnregisterDequeue(); promise_->set_value(); } } std::queue<std::string> buffer_; int64_t count_; private: Handler* handler_; Queue<std::string>* queue_; std::promise<void>* promise_; }; BENCHMARK_DEFINE_F(BM_QueuePerformance, send_packet_vary_by_packet_num)(State& state) { for (auto _ : state) { int64_t num_data_to_send_ = state.range(0); Queue<std::string> queue(num_data_to_send_); // register dequeue std::promise<void> dequeue_promise; auto dequeue_future = dequeue_promise.get_future(); TestDequeueEnd test_dequeue_end(num_data_to_send_, &queue, enqueue_handler_, &dequeue_promise); test_dequeue_end.RegisterDequeue(); // Push data to enqueue end buffer and register enqueue std::promise<void> enqueue_promise; TestEnqueueEnd test_enqueue_end(num_data_to_send_, &queue, enqueue_handler_, &enqueue_promise); for (int i = 0; i < num_data_to_send_; i++) { std::string data = std::to_string(1); test_enqueue_end.push(std::move(data)); } dequeue_future.wait(); } state.SetBytesProcessed(static_cast<int_fast64_t>(state.iterations()) * state.range(0)); }; BENCHMARK_REGISTER_F(BM_QueuePerformance, send_packet_vary_by_packet_num) ->Arg(10) ->Arg(100) ->Arg(1000) ->Arg(10000) ->Arg(100000) ->Iterations(100) ->UseRealTime(); BENCHMARK_DEFINE_F(BM_QueuePerformance, send_10000_packet_vary_by_packet_size)(State& state) { for (auto _ : state) { int64_t num_data_to_send_ = 10000; int64_t packet_size = state.range(0); Queue<std::string> queue(num_data_to_send_); // register dequeue std::promise<void> dequeue_promise; auto dequeue_future = dequeue_promise.get_future(); TestDequeueEnd test_dequeue_end(num_data_to_send_, &queue, enqueue_handler_, &dequeue_promise); test_dequeue_end.RegisterDequeue(); // Push data to enqueue end buffer and register enqueue std::promise<void> enqueue_promise; TestEnqueueEnd test_enqueue_end(num_data_to_send_, &queue, enqueue_handler_, &enqueue_promise); for (int i = 0; i < num_data_to_send_; i++) { std::string data = std::string(packet_size, 'x'); test_enqueue_end.push(std::move(data)); } dequeue_future.wait(); } state.SetBytesProcessed(static_cast<int_fast64_t>(state.iterations()) * state.range(0) * 10000); }; BENCHMARK_REGISTER_F(BM_QueuePerformance, send_10000_packet_vary_by_packet_size) ->Arg(10) ->Arg(100) ->Arg(1000) ->Iterations(100) ->UseRealTime(); } // namespace os } // namespace bluetooth No newline at end of file Loading
system/gd/os/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -27,5 +27,6 @@ filegroup { srcs: [ "alarm_benchmark.cc", "thread_benchmark.cc", "queue_benchmark.cc", ] }
system/gd/os/queue_benchmark.cc 0 → 100644 +199 −0 Original line number Diff line number Diff line /* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "benchmark/benchmark.h" #include <future> #include "os/handler.h" #include "os/queue.h" #include "os/thread.h" using ::benchmark::State; namespace bluetooth { namespace os { class BM_QueuePerformance : public ::benchmark::Fixture { protected: void SetUp(State& st) override { ::benchmark::Fixture::SetUp(st); enqueue_thread_ = new Thread("enqueue_thread", Thread::Priority::NORMAL); enqueue_handler_ = new Handler(enqueue_thread_); dequeue_thread_ = new Thread("dequeue_thread", Thread::Priority::NORMAL); dequeue_handler_ = new Handler(dequeue_thread_); } void TearDown(State& st) override { delete enqueue_handler_; delete enqueue_thread_; delete dequeue_handler_; delete dequeue_thread_; enqueue_handler_ = nullptr; enqueue_thread_ = nullptr; dequeue_handler_ = nullptr; dequeue_thread_ = nullptr; benchmark::Fixture::TearDown(st); } Thread* enqueue_thread_; Handler* enqueue_handler_; Thread* dequeue_thread_; Handler* dequeue_handler_; }; class TestEnqueueEnd { public: explicit TestEnqueueEnd(int64_t count, Queue<std::string>* queue, Handler* handler, std::promise<void>* promise) : count_(count), handler_(handler), queue_(queue), promise_(promise) {} void RegisterEnqueue() { handler_->Post([this] { queue_->RegisterEnqueue(handler_, [this] { return EnqueueCallbackForTest(); }); }); } void push(std::string data) { { std::lock_guard<std::mutex> lock(mutex_); buffer_.push(std::move(data)); } if (buffer_.size() == 1) { RegisterEnqueue(); } } std::unique_ptr<std::string> EnqueueCallbackForTest() { std::lock_guard<std::mutex> lock(mutex_); std::unique_ptr<std::string> data = std::make_unique<std::string>(std::move(buffer_.front())); buffer_.pop(); if (buffer_.empty()) { queue_->UnregisterEnqueue(); } count_--; if (count_ == 0) { promise_->set_value(); } return data; } std::queue<std::string> buffer_; int64_t count_; private: Handler* handler_; Queue<std::string>* queue_; std::promise<void>* promise_; std::mutex mutex_; }; class TestDequeueEnd { public: explicit TestDequeueEnd(int64_t count, Queue<std::string>* queue, Handler* handler, std::promise<void>* promise) : count_(count), handler_(handler), queue_(queue), promise_(promise) {} void RegisterDequeue() { handler_->Post([this] { queue_->RegisterDequeue(handler_, [this] { DequeueCallbackForTest(); }); }); } void DequeueCallbackForTest() { std::string data = *(queue_->TryDequeue()); buffer_.push(data); count_--; if (count_ == 0) { queue_->UnregisterDequeue(); promise_->set_value(); } } std::queue<std::string> buffer_; int64_t count_; private: Handler* handler_; Queue<std::string>* queue_; std::promise<void>* promise_; }; BENCHMARK_DEFINE_F(BM_QueuePerformance, send_packet_vary_by_packet_num)(State& state) { for (auto _ : state) { int64_t num_data_to_send_ = state.range(0); Queue<std::string> queue(num_data_to_send_); // register dequeue std::promise<void> dequeue_promise; auto dequeue_future = dequeue_promise.get_future(); TestDequeueEnd test_dequeue_end(num_data_to_send_, &queue, enqueue_handler_, &dequeue_promise); test_dequeue_end.RegisterDequeue(); // Push data to enqueue end buffer and register enqueue std::promise<void> enqueue_promise; TestEnqueueEnd test_enqueue_end(num_data_to_send_, &queue, enqueue_handler_, &enqueue_promise); for (int i = 0; i < num_data_to_send_; i++) { std::string data = std::to_string(1); test_enqueue_end.push(std::move(data)); } dequeue_future.wait(); } state.SetBytesProcessed(static_cast<int_fast64_t>(state.iterations()) * state.range(0)); }; BENCHMARK_REGISTER_F(BM_QueuePerformance, send_packet_vary_by_packet_num) ->Arg(10) ->Arg(100) ->Arg(1000) ->Arg(10000) ->Arg(100000) ->Iterations(100) ->UseRealTime(); BENCHMARK_DEFINE_F(BM_QueuePerformance, send_10000_packet_vary_by_packet_size)(State& state) { for (auto _ : state) { int64_t num_data_to_send_ = 10000; int64_t packet_size = state.range(0); Queue<std::string> queue(num_data_to_send_); // register dequeue std::promise<void> dequeue_promise; auto dequeue_future = dequeue_promise.get_future(); TestDequeueEnd test_dequeue_end(num_data_to_send_, &queue, enqueue_handler_, &dequeue_promise); test_dequeue_end.RegisterDequeue(); // Push data to enqueue end buffer and register enqueue std::promise<void> enqueue_promise; TestEnqueueEnd test_enqueue_end(num_data_to_send_, &queue, enqueue_handler_, &enqueue_promise); for (int i = 0; i < num_data_to_send_; i++) { std::string data = std::string(packet_size, 'x'); test_enqueue_end.push(std::move(data)); } dequeue_future.wait(); } state.SetBytesProcessed(static_cast<int_fast64_t>(state.iterations()) * state.range(0) * 10000); }; BENCHMARK_REGISTER_F(BM_QueuePerformance, send_10000_packet_vary_by_packet_size) ->Arg(10) ->Arg(100) ->Arg(1000) ->Iterations(100) ->UseRealTime(); } // namespace os } // namespace bluetooth No newline at end of file