Commit 2bde9143 authored by Sami Kyostila's avatar Sami Kyostila Committed by Commit Bot

sequence_manager: Speed up SequenceManagerPerfTests

In order to speed up performance waterfall iteration time, instead of
always running for 5 seconds in the SequenceManagerPerfTests, measure
the wall time cost of posting 100k tasks in various configurations. We
also only measure task queue scaling efficiency with specific types of
sequence manager configurations.

Bug: 897751
Change-Id: Iafd1d809bf5116912298b7cad10e00551939e601
Reviewed-on: https://chromium-review.googlesource.com/c/1315887Reviewed-by: default avatarAlex Clarke <alexclarke@chromium.org>
Commit-Queue: Sami Kyöstilä <skyostil@chromium.org>
Cr-Commit-Position: refs/heads/master@{#605923}
parent 2af43e66
...@@ -33,6 +33,9 @@ ...@@ -33,6 +33,9 @@
namespace base { namespace base {
namespace sequence_manager { namespace sequence_manager {
namespace {
const int kNumTasks = 1000000;
}
// To reduce noise related to the OS timer, we use a mock time domain to // To reduce noise related to the OS timer, we use a mock time domain to
// fast forward the timers. // fast forward the timers.
...@@ -356,6 +359,7 @@ class CrossThreadTaskSource : public TaskSource { ...@@ -356,6 +359,7 @@ class CrossThreadTaskSource : public TaskSource {
for (size_t i = 0; i < num_tasks_; i++) { for (size_t i = 0; i < num_tasks_; i++) {
while (num_tasks_in_flight_.load(std::memory_order_acquire) > while (num_tasks_in_flight_.load(std::memory_order_acquire) >
max_tasks_in_flight_) { max_tasks_in_flight_) {
PlatformThread::YieldCurrentThread();
} }
// Choose a queue weighted towards queue 0. // Choose a queue weighted towards queue 0.
unsigned int queue = i % (num_queues_ + 1); unsigned int queue = i % (num_queues_ + 1);
...@@ -394,13 +398,12 @@ class SingleThreadImmediateTestCase : public TestCase { ...@@ -394,13 +398,12 @@ class SingleThreadImmediateTestCase : public TestCase {
public: public:
SingleThreadImmediateTestCase( SingleThreadImmediateTestCase(
PerfTestDelegate* delegate, PerfTestDelegate* delegate,
std::vector<scoped_refptr<TaskRunner>> task_runners, std::vector<scoped_refptr<TaskRunner>> task_runners)
size_t num_tasks)
: TestCase(delegate), : TestCase(delegate),
task_source_(std::make_unique<SingleThreadImmediateTaskSource>( task_source_(std::make_unique<SingleThreadImmediateTaskSource>(
delegate, delegate,
std::move(task_runners), std::move(task_runners),
num_tasks)) {} kNumTasks)) {}
void Start() override { task_source_->Start(); } void Start() override { task_source_->Start(); }
...@@ -432,13 +435,12 @@ class SingleThreadDelayedTestCase : public TestCase { ...@@ -432,13 +435,12 @@ class SingleThreadDelayedTestCase : public TestCase {
public: public:
SingleThreadDelayedTestCase( SingleThreadDelayedTestCase(
PerfTestDelegate* delegate, PerfTestDelegate* delegate,
std::vector<scoped_refptr<TaskRunner>> task_runners, std::vector<scoped_refptr<TaskRunner>> task_runners)
size_t num_tasks)
: TestCase(delegate), : TestCase(delegate),
task_source_(std::make_unique<SingleThreadDelayedTaskSource>( task_source_(std::make_unique<SingleThreadDelayedTaskSource>(
delegate, delegate,
std::move(task_runners), std::move(task_runners),
num_tasks)) {} kNumTasks)) {}
void Start() override { task_source_->Start(); } void Start() override { task_source_->Start(); }
...@@ -472,11 +474,10 @@ class SingleThreadDelayedTestCase : public TestCase { ...@@ -472,11 +474,10 @@ class SingleThreadDelayedTestCase : public TestCase {
class TwoThreadTestCase : public TestCase { class TwoThreadTestCase : public TestCase {
public: public:
TwoThreadTestCase(PerfTestDelegate* delegate, TwoThreadTestCase(PerfTestDelegate* delegate,
std::vector<scoped_refptr<TaskRunner>> task_runners, std::vector<scoped_refptr<TaskRunner>> task_runners)
size_t num_tasks)
: TestCase(delegate), : TestCase(delegate),
task_runners_(std::move(task_runners)), task_runners_(std::move(task_runners)),
num_tasks_(num_tasks), num_tasks_(kNumTasks),
auxiliary_thread_("auxillary thread") { auxiliary_thread_("auxillary thread") {
auxiliary_thread_.Start(); auxiliary_thread_.Start();
} }
...@@ -558,9 +559,6 @@ class TwoThreadTestCase : public TestCase { ...@@ -558,9 +559,6 @@ class TwoThreadTestCase : public TestCase {
class SequenceManagerPerfTest : public testing::TestWithParam<PerfTestType> { class SequenceManagerPerfTest : public testing::TestWithParam<PerfTestType> {
public: public:
void SetUp() override { void SetUp() override {
if (ThreadTicks::IsSupported())
ThreadTicks::WaitUntilInitialized();
delegate_ = CreateDelegate(); delegate_ = CreateDelegate();
} }
...@@ -617,6 +615,13 @@ class SequenceManagerPerfTest : public testing::TestWithParam<PerfTestType> { ...@@ -617,6 +615,13 @@ class SequenceManagerPerfTest : public testing::TestWithParam<PerfTestType> {
} }
} }
bool ShouldMeasureQueueScaling() const {
// To limit test run time, we only measure multiple queues specific sequence
// manager configurations.
return delegate_->MultipleQueuesSupported() &&
GetParam() == PerfTestType::kUseSequenceManagerWithUIMessagePump;
}
std::vector<scoped_refptr<TaskRunner>> CreateTaskRunners(int num) { std::vector<scoped_refptr<TaskRunner>> CreateTaskRunners(int num) {
std::vector<scoped_refptr<TaskRunner>> task_runners; std::vector<scoped_refptr<TaskRunner>> task_runners;
for (int i = 0; i < num; i++) { for (int i = 0; i < num; i++) {
...@@ -628,23 +633,18 @@ class SequenceManagerPerfTest : public testing::TestWithParam<PerfTestType> { ...@@ -628,23 +633,18 @@ class SequenceManagerPerfTest : public testing::TestWithParam<PerfTestType> {
void Benchmark(const std::string& trace, TestCase* TestCase) { void Benchmark(const std::string& trace, TestCase* TestCase) {
TimeTicks start = TimeTicks::Now(); TimeTicks start = TimeTicks::Now();
TimeTicks now; TimeTicks now;
unsigned long long num_iterations = 0; TestCase->Start();
do { delegate_->WaitUntilDone();
TestCase->Start(); now = TimeTicks::Now();
delegate_->WaitUntilDone();
now = TimeTicks::Now();
num_iterations++;
} while (now - start < TimeDelta::FromSeconds(5));
perf_test::PrintResult( perf_test::PrintResult(
"task", "", trace + delegate_->GetName(), "task", "", trace + delegate_->GetName(),
(now - start).InMicroseconds() / static_cast<double>(num_iterations), (now - start).InMicroseconds() / static_cast<double>(kNumTasks),
"us/run", true); "us/task", true);
LOG(ERROR) << "task " << trace << delegate_->GetName() LOG(ERROR) << "task " << trace << delegate_->GetName()
<< ((now - start).InMicroseconds() / << ((now - start).InMicroseconds() /
static_cast<double>(num_iterations)) static_cast<double>(kNumTasks))
<< " us/run"; << " us/task";
} }
std::unique_ptr<PerfTestDelegate> delegate_; std::unique_ptr<PerfTestDelegate> delegate_;
...@@ -664,165 +664,123 @@ INSTANTIATE_TEST_CASE_P( ...@@ -664,165 +664,123 @@ INSTANTIATE_TEST_CASE_P(
PerfTestType::kUseIOMessageLoop, PerfTestType::kUseIOMessageLoop,
PerfTestType::kUseSingleThreadInWorkerPool)); PerfTestType::kUseSingleThreadInWorkerPool));
TEST_P(SequenceManagerPerfTest, RunTenThousandDelayedTasks_OneQueue) { TEST_P(SequenceManagerPerfTest, PostDelayedTasks_OneQueue) {
if (!ThreadTicks::IsSupported())
return;
if (!delegate_->VirtualTimeIsSupported()) { if (!delegate_->VirtualTimeIsSupported()) {
LOG(INFO) << "Unsupported"; LOG(INFO) << "Unsupported";
return; return;
} }
SingleThreadDelayedTestCase task_source(delegate_.get(), CreateTaskRunners(1), SingleThreadDelayedTestCase task_source(delegate_.get(),
10000u); CreateTaskRunners(1));
Benchmark("run 10000 delayed tasks with one queue", &task_source); Benchmark("post delayed tasks with one queue", &task_source);
} }
TEST_P(SequenceManagerPerfTest, RunTenThousandDelayedTasks_FourQueues) { TEST_P(SequenceManagerPerfTest, PostDelayedTasks_FourQueues) {
if (!ThreadTicks::IsSupported()) if (!delegate_->VirtualTimeIsSupported() || !ShouldMeasureQueueScaling()) {
return;
if (!delegate_->VirtualTimeIsSupported() ||
!delegate_->MultipleQueuesSupported()) {
LOG(INFO) << "Unsupported"; LOG(INFO) << "Unsupported";
return; return;
} }
SingleThreadDelayedTestCase task_source(delegate_.get(), CreateTaskRunners(4), SingleThreadDelayedTestCase task_source(delegate_.get(),
10000u); CreateTaskRunners(4));
Benchmark("run 10000 delayed tasks with four queues", &task_source); Benchmark("post delayed tasks with four queues", &task_source);
} }
TEST_P(SequenceManagerPerfTest, RunTenThousandDelayedTasks_EightQueues) { TEST_P(SequenceManagerPerfTest, PostDelayedTasks_EightQueues) {
if (!ThreadTicks::IsSupported()) if (!delegate_->VirtualTimeIsSupported() || !ShouldMeasureQueueScaling()) {
return;
if (!delegate_->VirtualTimeIsSupported() ||
!delegate_->MultipleQueuesSupported()) {
LOG(INFO) << "Unsupported"; LOG(INFO) << "Unsupported";
return; return;
} }
SingleThreadDelayedTestCase task_source(delegate_.get(), CreateTaskRunners(8), SingleThreadDelayedTestCase task_source(delegate_.get(),
10000u); CreateTaskRunners(8));
Benchmark("run 10000 delayed tasks with eight queues", &task_source); Benchmark("post delayed tasks with eight queues", &task_source);
} }
TEST_P(SequenceManagerPerfTest, RunTenThousandDelayedTasks_ThirtyTwoQueues) { TEST_P(SequenceManagerPerfTest, PostDelayedTasks_ThirtyTwoQueues) {
if (!ThreadTicks::IsSupported()) if (!delegate_->VirtualTimeIsSupported() || !ShouldMeasureQueueScaling()) {
return;
if (!delegate_->VirtualTimeIsSupported() ||
!delegate_->MultipleQueuesSupported()) {
LOG(INFO) << "Unsupported"; LOG(INFO) << "Unsupported";
return; return;
} }
SingleThreadDelayedTestCase task_source(delegate_.get(), SingleThreadDelayedTestCase task_source(delegate_.get(),
CreateTaskRunners(32), 10000u); CreateTaskRunners(32));
Benchmark("run 10000 delayed tasks with thirty two queues", &task_source); Benchmark("post delayed tasks with thirty two queues", &task_source);
} }
TEST_P(SequenceManagerPerfTest, RunTenThousandImmediateTasks_OneQueue) { TEST_P(SequenceManagerPerfTest, PostImmediateTasks_OneQueue) {
if (!ThreadTicks::IsSupported())
return;
SingleThreadImmediateTestCase task_source(delegate_.get(), SingleThreadImmediateTestCase task_source(delegate_.get(),
CreateTaskRunners(1), 10000u); CreateTaskRunners(1));
Benchmark("run 10000 immediate tasks with one queue", &task_source); Benchmark("post immediate tasks with one queue", &task_source);
} }
TEST_P(SequenceManagerPerfTest, RunTenThousandImmediateTasks_FourQueues) { TEST_P(SequenceManagerPerfTest, PostImmediateTasks_FourQueues) {
if (!ThreadTicks::IsSupported()) if (!ShouldMeasureQueueScaling()) {
return;
if (!delegate_->MultipleQueuesSupported()) {
LOG(INFO) << "Unsupported"; LOG(INFO) << "Unsupported";
return; return;
} }
SingleThreadImmediateTestCase task_source(delegate_.get(), SingleThreadImmediateTestCase task_source(delegate_.get(),
CreateTaskRunners(4), 10000u); CreateTaskRunners(4));
Benchmark("run 10000 immediate tasks with four queues", &task_source); Benchmark("post immediate tasks with four queues", &task_source);
} }
TEST_P(SequenceManagerPerfTest, RunTenThousandImmediateTasks_EightQueues) { TEST_P(SequenceManagerPerfTest, PostImmediateTasks_EightQueues) {
if (!ThreadTicks::IsSupported()) if (!ShouldMeasureQueueScaling()) {
return;
if (!delegate_->MultipleQueuesSupported()) {
LOG(INFO) << "Unsupported"; LOG(INFO) << "Unsupported";
return; return;
} }
SingleThreadImmediateTestCase task_source(delegate_.get(), SingleThreadImmediateTestCase task_source(delegate_.get(),
CreateTaskRunners(8), 10000u); CreateTaskRunners(8));
Benchmark("run 10000 immediate tasks with eight queues", &task_source); Benchmark("post immediate tasks with eight queues", &task_source);
} }
TEST_P(SequenceManagerPerfTest, RunTenThousandImmediateTasks_ThirtyTwoQueues) { TEST_P(SequenceManagerPerfTest, PostImmediateTasks_ThirtyTwoQueues) {
if (!ThreadTicks::IsSupported()) if (!ShouldMeasureQueueScaling()) {
return;
if (!delegate_->MultipleQueuesSupported()) {
LOG(INFO) << "Unsupported"; LOG(INFO) << "Unsupported";
return; return;
} }
SingleThreadImmediateTestCase task_source(delegate_.get(), SingleThreadImmediateTestCase task_source(delegate_.get(),
CreateTaskRunners(32), 10000u); CreateTaskRunners(32));
Benchmark("run 10000 immediate tasks with thirty two queues", &task_source); Benchmark("post immediate tasks with thirty two queues", &task_source);
} }
TEST_P(SequenceManagerPerfTest, TEST_P(SequenceManagerPerfTest, PostImmediateTasksFromTwoThreads_OneQueue) {
RunTenThousandImmediateTasksFromTwoThreads_OneQueue) { TwoThreadTestCase task_source(delegate_.get(), CreateTaskRunners(1));
if (!ThreadTicks::IsSupported()) Benchmark("post immediate tasks with one queue", &task_source);
return;
TwoThreadTestCase task_source(delegate_.get(), CreateTaskRunners(1), 10000u);
Benchmark("run 10000 immediate tasks with one queue", &task_source);
} }
TEST_P(SequenceManagerPerfTest, TEST_P(SequenceManagerPerfTest, PostImmediateTasksFromTwoThreads_FourQueues) {
RunTenThousandImmediateTasksFromTwoThreads_FourQueues) { if (!ShouldMeasureQueueScaling()) {
if (!ThreadTicks::IsSupported())
return;
if (!delegate_->MultipleQueuesSupported()) {
LOG(INFO) << "Unsupported"; LOG(INFO) << "Unsupported";
return; return;
} }
TwoThreadTestCase task_source(delegate_.get(), CreateTaskRunners(4), 10000u); TwoThreadTestCase task_source(delegate_.get(), CreateTaskRunners(4));
Benchmark("run 10000 immediate tasks with four queues", &task_source); Benchmark("post immediate tasks with four queues", &task_source);
} }
TEST_P(SequenceManagerPerfTest, TEST_P(SequenceManagerPerfTest, PostImmediateTasksFromTwoThreads_EightQueues) {
RunTenThousandImmediateTasksFromTwoThreads_EightQueues) { if (!ShouldMeasureQueueScaling()) {
if (!ThreadTicks::IsSupported())
return;
if (!delegate_->MultipleQueuesSupported()) {
LOG(INFO) << "Unsupported"; LOG(INFO) << "Unsupported";
return; return;
} }
TwoThreadTestCase task_source(delegate_.get(), CreateTaskRunners(8), 10000u); TwoThreadTestCase task_source(delegate_.get(), CreateTaskRunners(8));
Benchmark("run 10000 immediate tasks with eight queues", &task_source); Benchmark("post immediate tasks with eight queues", &task_source);
} }
TEST_P(SequenceManagerPerfTest, TEST_P(SequenceManagerPerfTest,
RunTenThousandImmediateTasksFromTwoThreads_ThirtyTwoQueues) { PostImmediateTasksFromTwoThreads_ThirtyTwoQueues) {
if (!ThreadTicks::IsSupported()) if (!ShouldMeasureQueueScaling()) {
return;
if (!delegate_->MultipleQueuesSupported()) {
LOG(INFO) << "Unsupported"; LOG(INFO) << "Unsupported";
return; return;
} }
TwoThreadTestCase task_source(delegate_.get(), CreateTaskRunners(32), 10000u); TwoThreadTestCase task_source(delegate_.get(), CreateTaskRunners(32));
Benchmark("run 10000 immediate tasks with thirty two queues", &task_source); Benchmark("post immediate tasks with thirty two queues", &task_source);
} }
// TODO(alexclarke): Add additional tests with different mixes of non-delayed vs // TODO(alexclarke): Add additional tests with different mixes of non-delayed vs
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment