Commit 586e21ec authored by Alexander Timin's avatar Alexander Timin Committed by Commit Bot

[scheduler] Add a perftest to measure basic scheduling costs.

Change-Id: Idda9f71ae005250848fd2a118e5c4344e36be452
Reviewed-on: https://chromium-review.googlesource.com/1085295Reviewed-by: default avatarAlex Clarke <alexclarke@chromium.org>
Commit-Queue: Alexander Timin <altimin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#566362}
parent 29d7535b
...@@ -241,6 +241,7 @@ source_set("perf_tests") { ...@@ -241,6 +241,7 @@ source_set("perf_tests") {
sources = [ sources = [
"base/task_queue_manager_perftest.cc", "base/task_queue_manager_perftest.cc",
"test/scheduler_perftest.cc",
] ]
deps = [ deps = [
......
...@@ -350,7 +350,7 @@ scoped_refptr<base::SingleThreadTaskRunner> FrameSchedulerImpl::GetTaskRunner( ...@@ -350,7 +350,7 @@ scoped_refptr<base::SingleThreadTaskRunner> FrameSchedulerImpl::GetTaskRunner(
return nullptr; return nullptr;
} }
scoped_refptr<TaskQueue> FrameSchedulerImpl::LoadingTaskQueue() { scoped_refptr<MainThreadTaskQueue> FrameSchedulerImpl::LoadingTaskQueue() {
DCHECK(parent_page_scheduler_); DCHECK(parent_page_scheduler_);
if (!loading_task_queue_) { if (!loading_task_queue_) {
// TODO(panicker): Avoid adding this queue in RS task_runners_. // TODO(panicker): Avoid adding this queue in RS task_runners_.
...@@ -364,7 +364,8 @@ scoped_refptr<TaskQueue> FrameSchedulerImpl::LoadingTaskQueue() { ...@@ -364,7 +364,8 @@ scoped_refptr<TaskQueue> FrameSchedulerImpl::LoadingTaskQueue() {
return loading_task_queue_; return loading_task_queue_;
} }
scoped_refptr<TaskQueue> FrameSchedulerImpl::LoadingControlTaskQueue() { scoped_refptr<MainThreadTaskQueue>
FrameSchedulerImpl::LoadingControlTaskQueue() {
DCHECK(parent_page_scheduler_); DCHECK(parent_page_scheduler_);
if (!loading_control_task_queue_) { if (!loading_control_task_queue_) {
loading_control_task_queue_ = main_thread_scheduler_->NewLoadingTaskQueue( loading_control_task_queue_ = main_thread_scheduler_->NewLoadingTaskQueue(
...@@ -377,7 +378,7 @@ scoped_refptr<TaskQueue> FrameSchedulerImpl::LoadingControlTaskQueue() { ...@@ -377,7 +378,7 @@ scoped_refptr<TaskQueue> FrameSchedulerImpl::LoadingControlTaskQueue() {
return loading_control_task_queue_; return loading_control_task_queue_;
} }
scoped_refptr<TaskQueue> FrameSchedulerImpl::ThrottleableTaskQueue() { scoped_refptr<MainThreadTaskQueue> FrameSchedulerImpl::ThrottleableTaskQueue() {
DCHECK(parent_page_scheduler_); DCHECK(parent_page_scheduler_);
if (!throttleable_task_queue_) { if (!throttleable_task_queue_) {
// TODO(panicker): Avoid adding this queue in RS task_runners_. // TODO(panicker): Avoid adding this queue in RS task_runners_.
...@@ -407,7 +408,7 @@ scoped_refptr<TaskQueue> FrameSchedulerImpl::ThrottleableTaskQueue() { ...@@ -407,7 +408,7 @@ scoped_refptr<TaskQueue> FrameSchedulerImpl::ThrottleableTaskQueue() {
return throttleable_task_queue_; return throttleable_task_queue_;
} }
scoped_refptr<TaskQueue> FrameSchedulerImpl::DeferrableTaskQueue() { scoped_refptr<MainThreadTaskQueue> FrameSchedulerImpl::DeferrableTaskQueue() {
DCHECK(parent_page_scheduler_); DCHECK(parent_page_scheduler_);
if (!deferrable_task_queue_) { if (!deferrable_task_queue_) {
deferrable_task_queue_ = main_thread_scheduler_->NewTaskQueue( deferrable_task_queue_ = main_thread_scheduler_->NewTaskQueue(
...@@ -426,7 +427,7 @@ scoped_refptr<TaskQueue> FrameSchedulerImpl::DeferrableTaskQueue() { ...@@ -426,7 +427,7 @@ scoped_refptr<TaskQueue> FrameSchedulerImpl::DeferrableTaskQueue() {
return deferrable_task_queue_; return deferrable_task_queue_;
} }
scoped_refptr<TaskQueue> FrameSchedulerImpl::PausableTaskQueue() { scoped_refptr<MainThreadTaskQueue> FrameSchedulerImpl::PausableTaskQueue() {
DCHECK(parent_page_scheduler_); DCHECK(parent_page_scheduler_);
if (!pausable_task_queue_) { if (!pausable_task_queue_) {
pausable_task_queue_ = main_thread_scheduler_->NewTaskQueue( pausable_task_queue_ = main_thread_scheduler_->NewTaskQueue(
...@@ -444,7 +445,7 @@ scoped_refptr<TaskQueue> FrameSchedulerImpl::PausableTaskQueue() { ...@@ -444,7 +445,7 @@ scoped_refptr<TaskQueue> FrameSchedulerImpl::PausableTaskQueue() {
return pausable_task_queue_; return pausable_task_queue_;
} }
scoped_refptr<TaskQueue> FrameSchedulerImpl::UnpausableTaskQueue() { scoped_refptr<MainThreadTaskQueue> FrameSchedulerImpl::UnpausableTaskQueue() {
DCHECK(parent_page_scheduler_); DCHECK(parent_page_scheduler_);
if (!unpausable_task_queue_) { if (!unpausable_task_queue_) {
unpausable_task_queue_ = main_thread_scheduler_->NewTaskQueue( unpausable_task_queue_ = main_thread_scheduler_->NewTaskQueue(
...@@ -776,5 +777,10 @@ void FrameSchedulerImpl::RemovePauseSubresourceLoadingHandle() { ...@@ -776,5 +777,10 @@ void FrameSchedulerImpl::RemovePauseSubresourceLoadingHandle() {
} }
} }
scoped_refptr<MainThreadTaskQueue>
FrameSchedulerImpl::GetTaskQueueForTesting() {
return UnpausableTaskQueue();
}
} // namespace scheduler } // namespace scheduler
} // namespace blink } // namespace blink
...@@ -110,6 +110,10 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler { ...@@ -110,6 +110,10 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler {
// page scheduler. Should be used only for testing purposes. // page scheduler. Should be used only for testing purposes.
FrameSchedulerImpl(); FrameSchedulerImpl();
// Retuns a valid per-frame task queue which should be used for testing.
// This task queue is expected to always run tasks.
scoped_refptr<MainThreadTaskQueue> GetTaskQueueForTesting();
private: private:
friend class PageSchedulerImpl; friend class PageSchedulerImpl;
friend class main_thread_scheduler_impl_unittest::MainThreadSchedulerImplTest; friend class main_thread_scheduler_impl_unittest::MainThreadSchedulerImplTest;
...@@ -165,12 +169,12 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler { ...@@ -165,12 +169,12 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler {
void AddPauseSubresourceLoadingHandle(); void AddPauseSubresourceLoadingHandle();
void RemovePauseSubresourceLoadingHandle(); void RemovePauseSubresourceLoadingHandle();
scoped_refptr<base::sequence_manager::TaskQueue> LoadingTaskQueue(); scoped_refptr<MainThreadTaskQueue> LoadingTaskQueue();
scoped_refptr<base::sequence_manager::TaskQueue> LoadingControlTaskQueue(); scoped_refptr<MainThreadTaskQueue> LoadingControlTaskQueue();
scoped_refptr<base::sequence_manager::TaskQueue> ThrottleableTaskQueue(); scoped_refptr<MainThreadTaskQueue> ThrottleableTaskQueue();
scoped_refptr<base::sequence_manager::TaskQueue> DeferrableTaskQueue(); scoped_refptr<MainThreadTaskQueue> DeferrableTaskQueue();
scoped_refptr<base::sequence_manager::TaskQueue> PausableTaskQueue(); scoped_refptr<MainThreadTaskQueue> PausableTaskQueue();
scoped_refptr<base::sequence_manager::TaskQueue> UnpausableTaskQueue(); scoped_refptr<MainThreadTaskQueue> UnpausableTaskQueue();
const FrameScheduler::FrameType frame_type_; const FrameScheduler::FrameType frame_type_;
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/test/test_mock_time_task_runner.h"
#include "base/time/default_tick_clock.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_test.h"
#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
namespace blink {
namespace scheduler {
class FrameSchedulerForTest : public FrameSchedulerImpl {
public:
FrameSchedulerForTest(MainThreadSchedulerImpl* main_thread_scheduler,
PageSchedulerImpl* page_scheduler)
: FrameSchedulerImpl(main_thread_scheduler,
page_scheduler,
nullptr,
FrameScheduler::FrameType::kMainFrame) {}
using FrameSchedulerImpl::GetTaskQueueForTesting;
};
class SchedulerPerfTest : public testing::Test {
protected:
void SetUp() override {
message_loop_ = std::make_unique<base::MessageLoop>();
main_thread_scheduler_ = std::make_unique<MainThreadSchedulerImpl>(
base::sequence_manager::TaskQueueManagerForTest::Create(
message_loop_.get(), message_loop_->task_runner(),
base::DefaultTickClock::GetInstance()),
base::nullopt);
metrics_helper_ = std::make_unique<MainThreadMetricsHelper>(
main_thread_scheduler_.get(), base::TimeTicks::Now(), false);
page_scheduler_ = std::make_unique<PageSchedulerImpl>(
nullptr, main_thread_scheduler_.get(), false);
frame_scheduler_ = std::make_unique<FrameSchedulerForTest>(
main_thread_scheduler_.get(), page_scheduler_.get());
}
std::unique_ptr<base::MessageLoop> message_loop_;
std::unique_ptr<MainThreadSchedulerImpl> main_thread_scheduler_;
std::unique_ptr<MainThreadMetricsHelper> metrics_helper_;
std::unique_ptr<PageSchedulerImpl> page_scheduler_;
std::unique_ptr<FrameSchedulerForTest> frame_scheduler_;
};
void Measure(base::OnceCallback<void(size_t)> task,
size_t num_iterations,
std::string name) {
base::TimeTicks start = base::TimeTicks::Now();
base::ThreadTicks start_thread = base::ThreadTicks::Now();
std::move(task).Run(num_iterations);
base::TimeTicks now = base::TimeTicks::Now();
base::ThreadTicks now_thread = base::ThreadTicks::Now();
perf_test::PrintResult(
"task", "", name + " (wall time)",
(now - start).InMicroseconds() / static_cast<double>(num_iterations),
"us/run", true);
perf_test::PrintResult("task", "", name + " (thread time)",
(now_thread - start_thread).InMicroseconds() /
static_cast<double>(num_iterations),
"us/run", true);
}
void RunChainedTask(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
size_t iterations) {
if (iterations <= 1)
return;
task_runner->PostTask(
FROM_HERE, base::BindOnce(&RunChainedTask, task_runner, iterations - 1));
}
TEST_F(SchedulerPerfTest, MeasureTimeCost) {
const size_t num_iterations = 1e5;
Measure(base::BindOnce([](size_t num_iterations) {
base::TimeTicks now;
for (size_t i = 0; i < num_iterations; ++i) {
now = base::TimeTicks::Now();
}
}),
num_iterations, "Measure wall time measurement cost");
Measure(base::BindOnce([](size_t num_iterations) {
base::ThreadTicks now;
for (size_t i = 0; i < num_iterations; ++i) {
now = base::ThreadTicks::Now();
}
}),
num_iterations, "Measure thread time measurement cost");
Measure(
base::BindOnce(
[](MainThreadMetricsHelper* metrics_helper,
FrameSchedulerForTest* frame_scheduler, size_t num_iterations) {
base::sequence_manager::TaskQueue::Task task(
base::sequence_manager::TaskQueue::PostedTask(
base::OnceClosure(), FROM_HERE),
base::TimeTicks());
base::TimeTicks now =
base::TimeTicks() + base::TimeDelta::FromSeconds(1);
base::TimeDelta delta = base::TimeDelta::FromMilliseconds(10);
scoped_refptr<MainThreadTaskQueue> queue =
frame_scheduler->GetTaskQueueForTesting();
for (size_t i = 0; i < num_iterations; ++i) {
metrics_helper->RecordTaskMetrics(queue.get(), task, now,
now + delta, base::nullopt);
now += delta;
}
},
base::Unretained(metrics_helper_.get()),
base::Unretained(frame_scheduler_.get())),
num_iterations, "Measure per-task metric cost");
Measure(
base::BindOnce(
[](scoped_refptr<MainThreadTaskQueue> queue, size_t num_iterations) {
queue->PostTask(FROM_HERE, base::BindOnce(&RunChainedTask, queue,
num_iterations));
base::RunLoop().RunUntilIdle();
},
frame_scheduler_->GetTaskQueueForTesting()),
num_iterations, "Measure a total cost of running a task");
DCHECK(false);
}
} // namespace scheduler
} // namespace blink
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