Skip to content

Commit

Permalink
cc: Plumbing for impl thread micro benchmarks
Browse files Browse the repository at this point in the history
This patch adds plumbing for running micro benchmarks on the impl
thread. The concept is as follows:

- Create a main thread benchmark via gpu benchmarking extension
- On commit complete, if the benchmark provides an impl thread
  benchmark, it is created and scheduled to be run on the impl thread
- Impl thread benchmarks are run after an appropriate callback
- Impl thread benchmarks post a done callback (with results) that is
  run on the main thread
- The main thread benchmark gets the callback and posts its own done
  callback (with aggregated results)
- This gets back to the gpu benchmarking extension which sends the
  response back to the caller

R=enne@chromium.org, nduca@chromium.org

Review URL: https://codereview.chromium.org/67563002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@235585 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
vmpstr@chromium.org committed Nov 18, 2013
1 parent 9b4b393 commit 5e5648a
Show file tree
Hide file tree
Showing 24 changed files with 448 additions and 23 deletions.
6 changes: 6 additions & 0 deletions cc/cc.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,12 @@
'debug/layer_tree_debug_state.h',
'debug/micro_benchmark.cc',
'debug/micro_benchmark.h',
'debug/micro_benchmark_impl.cc',
'debug/micro_benchmark_impl.h',
'debug/micro_benchmark_controller.cc',
'debug/micro_benchmark_controller.h',
'debug/micro_benchmark_controller_impl.cc',
'debug/micro_benchmark_controller_impl.h',
'debug/overdraw_metrics.cc',
'debug/overdraw_metrics.h',
'debug/paint_time_counter.cc',
Expand All @@ -101,6 +105,8 @@
'debug/traced_value.h',
'debug/unittest_only_benchmark.cc',
'debug/unittest_only_benchmark.h',
'debug/unittest_only_benchmark_impl.cc',
'debug/unittest_only_benchmark_impl.h',
'input/input_handler.h',
'input/page_scale_animation.cc',
'input/page_scale_animation.h',
Expand Down
23 changes: 22 additions & 1 deletion cc/debug/micro_benchmark.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@
#include "cc/debug/micro_benchmark.h"

#include "base/callback.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/values.h"
#include "cc/debug/micro_benchmark_impl.h"

namespace cc {

MicroBenchmark::MicroBenchmark(const DoneCallback& callback)
: callback_(callback), is_done_(false) {}
: callback_(callback),
is_done_(false),
processed_for_benchmark_impl_(false) {}

MicroBenchmark::~MicroBenchmark() {}

Expand All @@ -30,4 +35,20 @@ void MicroBenchmark::RunOnLayer(Layer* layer) {}

void MicroBenchmark::RunOnLayer(PictureLayer* layer) {}

bool MicroBenchmark::ProcessedForBenchmarkImpl() const {
return processed_for_benchmark_impl_;
}

scoped_ptr<MicroBenchmarkImpl> MicroBenchmark::GetBenchmarkImpl(
scoped_refptr<base::MessageLoopProxy> origin_loop) {
DCHECK(!processed_for_benchmark_impl_);
processed_for_benchmark_impl_ = true;
return CreateBenchmarkImpl(origin_loop);
}

scoped_ptr<MicroBenchmarkImpl> MicroBenchmark::CreateBenchmarkImpl(
scoped_refptr<base::MessageLoopProxy> origin_loop) {
return make_scoped_ptr<MicroBenchmarkImpl>(NULL);
}

} // namespace cc
13 changes: 12 additions & 1 deletion cc/debug/micro_benchmark.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,20 @@

#include "base/callback.h"
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"

namespace base {
class Value;
class MessageLoopProxy;
} // namespace base

namespace cc {

class LayerTreeHost;
class Layer;
class PictureLayer;
class MicroBenchmark {
class MicroBenchmarkImpl;
class CC_EXPORT MicroBenchmark {
public:
typedef base::Callback<void(scoped_ptr<base::Value>)> DoneCallback;

Expand All @@ -30,12 +33,20 @@ class MicroBenchmark {
virtual void RunOnLayer(Layer* layer);
virtual void RunOnLayer(PictureLayer* layer);

bool ProcessedForBenchmarkImpl() const;
scoped_ptr<MicroBenchmarkImpl> GetBenchmarkImpl(
scoped_refptr<base::MessageLoopProxy> origin_loop);

protected:
void NotifyDone(scoped_ptr<base::Value> result);

virtual scoped_ptr<MicroBenchmarkImpl> CreateBenchmarkImpl(
scoped_refptr<base::MessageLoopProxy> origin_loop);

private:
DoneCallback callback_;
bool is_done_;
bool processed_for_benchmark_impl_;
};

} // namespace cc
Expand Down
25 changes: 22 additions & 3 deletions cc/debug/micro_benchmark_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
#include <string>

#include "base/callback.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/values.h"
#include "cc/debug/picture_record_benchmark.h"
#include "cc/debug/unittest_only_benchmark.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_host_impl.h"

namespace cc {

Expand Down Expand Up @@ -43,7 +45,8 @@ class IsDonePredicate {
} // namespace

MicroBenchmarkController::MicroBenchmarkController(LayerTreeHost* host)
: host_(host) {
: host_(host),
main_controller_message_loop_(base::MessageLoopProxy::current().get()) {
DCHECK(host_);
}

Expand All @@ -63,12 +66,28 @@ bool MicroBenchmarkController::ScheduleRun(
return false;
}

void MicroBenchmarkController::ScheduleImplBenchmarks(
LayerTreeHostImpl* host_impl) {
for (ScopedPtrVector<MicroBenchmark>::iterator it = benchmarks_.begin();
it != benchmarks_.end();
++it) {
scoped_ptr<MicroBenchmarkImpl> benchmark_impl;
if (!(*it)->ProcessedForBenchmarkImpl()) {
benchmark_impl =
(*it)->GetBenchmarkImpl(main_controller_message_loop_);
}

if (benchmark_impl.get())
host_impl->ScheduleMicroBenchmark(benchmark_impl.Pass());
}
}

void MicroBenchmarkController::DidUpdateLayers() {
for (ScopedPtrVector<MicroBenchmark>::iterator it = benchmarks_.begin();
it != benchmarks_.end();
++it) {
DCHECK(!(*it)->IsDone());
(*it)->DidUpdateLayers(host_);
if (!(*it)->IsDone())
(*it)->DidUpdateLayers(host_);
}

CleanUpFinishedBenchmarks();
Expand Down
9 changes: 6 additions & 3 deletions cc/debug/micro_benchmark_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@

namespace base {
class Value;
class MessageLoopProxy;
} // namespace base

namespace cc {

class LayerTreeHost;
class Layer;
class PictureLayer;
class MicroBenchmarkController {
class LayerTreeHostImpl;
class CC_EXPORT MicroBenchmarkController {
public:
explicit MicroBenchmarkController(LayerTreeHost* host);
~MicroBenchmarkController();
Expand All @@ -32,11 +32,14 @@ class MicroBenchmarkController {
scoped_ptr<base::Value> value,
const MicroBenchmark::DoneCallback& callback);

void ScheduleImplBenchmarks(LayerTreeHostImpl* host_impl);

private:
void CleanUpFinishedBenchmarks();

LayerTreeHost* host_;
ScopedPtrVector<MicroBenchmark> benchmarks_;
scoped_refptr<base::MessageLoopProxy> main_controller_message_loop_;

DISALLOW_COPY_AND_ASSIGN(MicroBenchmarkController);
};
Expand Down
59 changes: 59 additions & 0 deletions cc/debug/micro_benchmark_controller_impl.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// 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/debug/micro_benchmark_controller_impl.h"

#include <string>

#include "base/callback.h"
#include "base/values.h"
#include "cc/trees/layer_tree_host_impl.h"

namespace cc {

namespace {

class IsDonePredicate {
public:
typedef const MicroBenchmarkImpl* argument_type;
typedef bool result_type;

result_type operator()(argument_type benchmark) const {
return benchmark->IsDone();
}
};

} // namespace

MicroBenchmarkControllerImpl::MicroBenchmarkControllerImpl(
LayerTreeHostImpl* host)
: host_(host) {
DCHECK(host_);
}

MicroBenchmarkControllerImpl::~MicroBenchmarkControllerImpl() {}

void MicroBenchmarkControllerImpl::ScheduleRun(
scoped_ptr<MicroBenchmarkImpl> benchmark) {
benchmarks_.push_back(benchmark.Pass());
}

void MicroBenchmarkControllerImpl::DidCompleteCommit() {
for (ScopedPtrVector<MicroBenchmarkImpl>::iterator it = benchmarks_.begin();
it != benchmarks_.end();
++it) {
DCHECK(!(*it)->IsDone());
(*it)->DidCompleteCommit(host_);
}

CleanUpFinishedBenchmarks();
}

void MicroBenchmarkControllerImpl::CleanUpFinishedBenchmarks() {
benchmarks_.erase(
benchmarks_.partition(std::not1(IsDonePredicate())),
benchmarks_.end());
}

} // namespace cc
37 changes: 37 additions & 0 deletions cc/debug/micro_benchmark_controller_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// 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.

#ifndef CC_DEBUG_MICRO_BENCHMARK_CONTROLLER_IMPL_H_
#define CC_DEBUG_MICRO_BENCHMARK_CONTROLLER_IMPL_H_

#include <string>

#include "base/basictypes.h"
#include "cc/base/scoped_ptr_vector.h"
#include "cc/debug/micro_benchmark_impl.h"

namespace cc {

class LayerTreeHostImpl;
class CC_EXPORT MicroBenchmarkControllerImpl {
public:
explicit MicroBenchmarkControllerImpl(LayerTreeHostImpl* host);
~MicroBenchmarkControllerImpl();

void DidCompleteCommit();

void ScheduleRun(scoped_ptr<MicroBenchmarkImpl> benchmark);

private:
void CleanUpFinishedBenchmarks();

LayerTreeHostImpl* host_;
ScopedPtrVector<MicroBenchmarkImpl> benchmarks_;

DISALLOW_COPY_AND_ASSIGN(MicroBenchmarkControllerImpl);
};

} // namespace cc

#endif // CC_DEBUG_MICRO_BENCHMARK_CONTROLLER_IMPL_H_
43 changes: 40 additions & 3 deletions cc/debug/micro_benchmark_controller_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "cc/layers/layer.h"
#include "cc/resources/resource_update_queue.h"
#include "cc/test/fake_layer_tree_host.h"
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/fake_proxy.h"
#include "testing/gtest/include/gtest/gtest.h"

Expand All @@ -17,14 +18,25 @@ namespace {

class MicroBenchmarkControllerTest : public testing::Test {
public:
virtual void SetUp() {
virtual void SetUp() OVERRIDE {
impl_proxy_ = make_scoped_ptr(new FakeImplProxy);
layer_tree_host_impl_ =
make_scoped_ptr(new FakeLayerTreeHostImpl(impl_proxy_.get()));

layer_tree_host_ = FakeLayerTreeHost::Create();
layer_tree_host_->SetRootLayer(Layer::Create());
layer_tree_host_->InitializeForTesting(
scoped_ptr<Proxy>(new FakeProxy));
layer_tree_host_->InitializeForTesting(scoped_ptr<Proxy>(new FakeProxy));
}

virtual void TearDown() OVERRIDE {
layer_tree_host_impl_.reset();
layer_tree_host_.reset();
impl_proxy_.reset();
}

scoped_ptr<FakeLayerTreeHost> layer_tree_host_;
scoped_ptr<FakeLayerTreeHostImpl> layer_tree_host_impl_;
scoped_ptr<FakeImplProxy> impl_proxy_;
};

void Noop(scoped_ptr<base::Value> value) {
Expand Down Expand Up @@ -100,5 +112,30 @@ TEST_F(MicroBenchmarkControllerTest, MultipleBenchmarkRan) {
EXPECT_EQ(4, run_count);
}

TEST_F(MicroBenchmarkControllerTest, BenchmarkImplRan) {
int run_count = 0;
scoped_ptr<base::DictionaryValue> settings(new base::DictionaryValue);
settings->SetBoolean("run_benchmark_impl", true);

// Schedule a main thread benchmark.
bool result = layer_tree_host_->ScheduleMicroBenchmark(
"unittest_only_benchmark",
settings.PassAs<base::Value>(),
base::Bind(&IncrementCallCount, base::Unretained(&run_count)));
EXPECT_TRUE(result);

// Schedule impl benchmarks. In production code, this is run in commit.
layer_tree_host_->GetMicroBenchmarkController()->ScheduleImplBenchmarks(
layer_tree_host_impl_.get());

// Now complete the commit (as if on the impl thread).
layer_tree_host_impl_->CommitComplete();

// Make sure all posted messages run.
base::MessageLoop::current()->RunUntilIdle();

EXPECT_EQ(1, run_count);
}

} // namespace
} // namespace cc
Loading

0 comments on commit 5e5648a

Please sign in to comment.