You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
6.0 KiB
207 lines
6.0 KiB
/*
|
|
* 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 <future>
|
|
|
|
#include "benchmark/benchmark.h"
|
|
#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(common::BindOnce(&TestEnqueueEnd::handle_register_enqueue, common::Unretained(this)));
|
|
}
|
|
|
|
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_;
|
|
|
|
void handle_register_enqueue() {
|
|
queue_->RegisterEnqueue(handler_, common::Bind(&TestEnqueueEnd::EnqueueCallbackForTest, common::Unretained(this)));
|
|
}
|
|
};
|
|
|
|
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(common::BindOnce(&TestDequeueEnd::handle_register_dequeue, common::Unretained(this)));
|
|
}
|
|
|
|
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_;
|
|
|
|
void handle_register_dequeue() {
|
|
queue_->RegisterDequeue(handler_, common::Bind(&TestDequeueEnd::DequeueCallbackForTest, common::Unretained(this)));
|
|
}
|
|
};
|
|
|
|
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
|