blob: a4a258b16d331c18619773e16fc99c69cd7729e6 [file] [log] [blame]
// Copyright 2013 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 "cc/resources/raster_worker_pool.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
namespace {
static const int kTimeLimitMillis = 2000;
static const int kWarmupRuns = 5;
static const int kTimeCheckInterval = 10;
class PerfWorkerPoolTaskImpl : public internal::WorkerPoolTask {
public:
// Overridden from internal::WorkerPoolTask:
virtual void RunOnWorkerThread(unsigned thread_index) OVERRIDE {}
virtual void CompleteOnOriginThread() OVERRIDE {}
private:
virtual ~PerfWorkerPoolTaskImpl() {}
};
class PerfRasterWorkerPool : public RasterWorkerPool {
public:
PerfRasterWorkerPool() : RasterWorkerPool(NULL, 1) {}
virtual ~PerfRasterWorkerPool() {}
static scoped_ptr<PerfRasterWorkerPool> Create() {
return make_scoped_ptr(new PerfRasterWorkerPool);
}
// Overridden from RasterWorkerPool:
virtual void ScheduleTasks(RasterTask::Queue* queue) OVERRIDE {
NOTREACHED();
}
virtual void OnRasterTasksFinished() OVERRIDE {
NOTREACHED();
}
virtual void OnRasterTasksRequiredForActivationFinished() OVERRIDE {
NOTREACHED();
}
void SetRasterTasks(RasterTask::Queue* queue) {
RasterWorkerPool::SetRasterTasks(queue);
TaskMap perf_tasks;
for (RasterTaskVector::const_iterator it = raster_tasks().begin();
it != raster_tasks().end(); ++it) {
internal::RasterWorkerPoolTask* task = it->get();
scoped_refptr<internal::WorkerPoolTask> new_perf_task(
new PerfWorkerPoolTaskImpl);
perf_tasks[task] = new_perf_task;
}
perf_tasks_.swap(perf_tasks);
}
void BuildTaskGraph() {
unsigned priority = 0;
TaskGraph graph;
scoped_refptr<internal::WorkerPoolTask>
raster_required_for_activation_finished_task(
CreateRasterRequiredForActivationFinishedTask());
internal::GraphNode* raster_required_for_activation_finished_node =
CreateGraphNodeForTask(
raster_required_for_activation_finished_task.get(),
priority++,
&graph);
scoped_refptr<internal::WorkerPoolTask> raster_finished_task(
CreateRasterFinishedTask());
internal::GraphNode* raster_finished_node =
CreateGraphNodeForTask(raster_finished_task.get(),
priority++,
&graph);
for (RasterTaskVector::const_iterator it = raster_tasks().begin();
it != raster_tasks().end(); ++it) {
internal::RasterWorkerPoolTask* task = it->get();
TaskMap::iterator perf_it = perf_tasks_.find(task);
DCHECK(perf_it != perf_tasks_.end());
if (perf_it != perf_tasks_.end()) {
internal::WorkerPoolTask* perf_task = perf_it->second.get();
internal::GraphNode* perf_node =
CreateGraphNodeForRasterTask(perf_task,
task->dependencies(),
priority++,
&graph);
if (IsRasterTaskRequiredForActivation(task)) {
raster_required_for_activation_finished_node->add_dependency();
perf_node->add_dependent(
raster_required_for_activation_finished_node);
}
raster_finished_node->add_dependency();
perf_node->add_dependent(raster_finished_node);
}
}
}
private:
TaskMap perf_tasks_;
DISALLOW_COPY_AND_ASSIGN(PerfRasterWorkerPool);
};
class RasterWorkerPoolPerfTest : public testing::Test {
public:
RasterWorkerPoolPerfTest() : num_runs_(0) {}
// Overridden from testing::Test:
virtual void SetUp() OVERRIDE {
raster_worker_pool_ = PerfRasterWorkerPool::Create();
}
virtual void TearDown() OVERRIDE {
raster_worker_pool_->Shutdown();
}
void EndTest() {
elapsed_ = base::TimeTicks::HighResNow() - start_time_;
}
void AfterTest(const std::string test_name) {
// Format matches chrome/test/perf/perf_test.h:PrintResult
printf("*RESULT %s: %.2f runs/s\n",
test_name.c_str(),
num_runs_ / elapsed_.InSecondsF());
}
bool DidRun() {
++num_runs_;
if (num_runs_ == kWarmupRuns)
start_time_ = base::TimeTicks::HighResNow();
if (!start_time_.is_null() && (num_runs_ % kTimeCheckInterval) == 0) {
base::TimeDelta elapsed = base::TimeTicks::HighResNow() - start_time_;
if (elapsed >= base::TimeDelta::FromMilliseconds(kTimeLimitMillis)) {
elapsed_ = elapsed;
return false;
}
}
return true;
}
void CreateTasks(RasterWorkerPool::RasterTask::Queue* tasks,
unsigned num_raster_tasks,
unsigned num_image_decode_tasks) {
typedef std::vector<RasterWorkerPool::Task> TaskVector;
TaskVector image_decode_tasks;
for (unsigned i = 0; i < num_image_decode_tasks; ++i) {
image_decode_tasks.push_back(
RasterWorkerPool::CreateImageDecodeTask(
NULL,
0,
NULL,
base::Bind(
&RasterWorkerPoolPerfTest::OnImageDecodeTaskCompleted)));
}
for (unsigned i = 0; i < num_raster_tasks; ++i) {
RasterWorkerPool::Task::Set decode_tasks;
for (TaskVector::iterator it = image_decode_tasks.begin();
it != image_decode_tasks.end(); ++it)
decode_tasks.Insert(*it);
tasks->Append(
RasterWorkerPool::CreateRasterTask(
NULL,
NULL,
gfx::Rect(),
1.0,
HIGH_QUALITY_RASTER_MODE,
false,
TileResolution(),
1,
NULL,
1,
NULL,
base::Bind(&RasterWorkerPoolPerfTest::OnRasterTaskCompleted),
&decode_tasks),
false);
}
}
void RunBuildTaskGraphTest(const std::string test_name,
unsigned num_raster_tasks,
unsigned num_image_decode_tasks) {
start_time_ = base::TimeTicks();
num_runs_ = 0;
RasterWorkerPool::RasterTask::Queue tasks;
CreateTasks(&tasks, num_raster_tasks, num_image_decode_tasks);
raster_worker_pool_->SetRasterTasks(&tasks);
do {
raster_worker_pool_->BuildTaskGraph();
} while (DidRun());
AfterTest(test_name);
}
protected:
static void OnRasterTaskCompleted(const PicturePileImpl::Analysis& analysis,
bool was_canceled) {}
static void OnImageDecodeTaskCompleted(bool was_canceled) {}
scoped_ptr<PerfRasterWorkerPool> raster_worker_pool_;
base::TimeTicks start_time_;
base::TimeDelta elapsed_;
int num_runs_;
};
TEST_F(RasterWorkerPoolPerfTest, BuildTaskGraph) {
RunBuildTaskGraphTest("build_task_graph_10_0", 10, 0);
RunBuildTaskGraphTest("build_task_graph_100_0", 100, 0);
RunBuildTaskGraphTest("build_task_graph_1000_0", 1000, 0);
RunBuildTaskGraphTest("build_task_graph_10_1", 10, 1);
RunBuildTaskGraphTest("build_task_graph_100_1", 100, 1);
RunBuildTaskGraphTest("build_task_graph_1000_1", 1000, 1);
RunBuildTaskGraphTest("build_task_graph_10_4", 10, 4);
RunBuildTaskGraphTest("build_task_graph_100_4", 100, 4);
RunBuildTaskGraphTest("build_task_graph_1000_4", 1000, 4);
RunBuildTaskGraphTest("build_task_graph_10_16", 10, 16);
RunBuildTaskGraphTest("build_task_graph_100_16", 100, 16);
RunBuildTaskGraphTest("build_task_graph_1000_16", 1000, 16);
}
} // namespace
} // namespace cc