1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "cc/debug/micro_benchmark_controller.h" 6 7#include <limits> 8#include <string> 9 10#include "base/callback.h" 11#include "base/message_loop/message_loop_proxy.h" 12#include "base/values.h" 13#include "cc/debug/invalidation_benchmark.h" 14#include "cc/debug/picture_record_benchmark.h" 15#include "cc/debug/rasterize_and_record_benchmark.h" 16#include "cc/debug/unittest_only_benchmark.h" 17#include "cc/trees/layer_tree_host.h" 18#include "cc/trees/layer_tree_host_impl.h" 19 20namespace cc { 21 22int MicroBenchmarkController::next_id_ = 1; 23 24namespace { 25 26scoped_ptr<MicroBenchmark> CreateBenchmark( 27 const std::string& name, 28 scoped_ptr<base::Value> value, 29 const MicroBenchmark::DoneCallback& callback) { 30 if (name == "invalidation_benchmark") { 31 return scoped_ptr<MicroBenchmark>( 32 new InvalidationBenchmark(value.Pass(), callback)); 33 } else if (name == "picture_record_benchmark") { 34 return scoped_ptr<MicroBenchmark>( 35 new PictureRecordBenchmark(value.Pass(), callback)); 36 } else if (name == "rasterize_and_record_benchmark") { 37 return scoped_ptr<MicroBenchmark>( 38 new RasterizeAndRecordBenchmark(value.Pass(), callback)); 39 } else if (name == "unittest_only_benchmark") { 40 return scoped_ptr<MicroBenchmark>( 41 new UnittestOnlyBenchmark(value.Pass(), callback)); 42 } 43 return scoped_ptr<MicroBenchmark>(); 44} 45 46class IsDonePredicate { 47 public: 48 typedef const MicroBenchmark* argument_type; 49 typedef bool result_type; 50 51 result_type operator()(argument_type benchmark) const { 52 return benchmark->IsDone(); 53 } 54}; 55 56} // namespace 57 58MicroBenchmarkController::MicroBenchmarkController(LayerTreeHost* host) 59 : host_(host), 60 main_controller_message_loop_(base::MessageLoopProxy::current().get()) { 61 DCHECK(host_); 62} 63 64MicroBenchmarkController::~MicroBenchmarkController() {} 65 66int MicroBenchmarkController::ScheduleRun( 67 const std::string& micro_benchmark_name, 68 scoped_ptr<base::Value> value, 69 const MicroBenchmark::DoneCallback& callback) { 70 scoped_ptr<MicroBenchmark> benchmark = 71 CreateBenchmark(micro_benchmark_name, value.Pass(), callback); 72 if (benchmark.get()) { 73 int id = GetNextIdAndIncrement(); 74 benchmark->set_id(id); 75 benchmarks_.push_back(benchmark.Pass()); 76 host_->SetNeedsCommit(); 77 return id; 78 } 79 return 0; 80} 81 82int MicroBenchmarkController::GetNextIdAndIncrement() { 83 int id = next_id_++; 84 // Wrap around to 1 if we overflow (very unlikely). 85 if (next_id_ == std::numeric_limits<int>::max()) 86 next_id_ = 1; 87 return id; 88} 89 90bool MicroBenchmarkController::SendMessage(int id, 91 scoped_ptr<base::Value> value) { 92 for (ScopedPtrVector<MicroBenchmark>::iterator it = benchmarks_.begin(); 93 it != benchmarks_.end(); 94 ++it) { 95 if ((*it)->id() == id) 96 return (*it)->ProcessMessage(value.Pass()); 97 } 98 return false; 99} 100 101void MicroBenchmarkController::ScheduleImplBenchmarks( 102 LayerTreeHostImpl* host_impl) { 103 for (ScopedPtrVector<MicroBenchmark>::iterator it = benchmarks_.begin(); 104 it != benchmarks_.end(); 105 ++it) { 106 scoped_ptr<MicroBenchmarkImpl> benchmark_impl; 107 if (!(*it)->ProcessedForBenchmarkImpl()) { 108 benchmark_impl = 109 (*it)->GetBenchmarkImpl(main_controller_message_loop_); 110 } 111 112 if (benchmark_impl.get()) 113 host_impl->ScheduleMicroBenchmark(benchmark_impl.Pass()); 114 } 115} 116 117void MicroBenchmarkController::DidUpdateLayers() { 118 for (ScopedPtrVector<MicroBenchmark>::iterator it = benchmarks_.begin(); 119 it != benchmarks_.end(); 120 ++it) { 121 if (!(*it)->IsDone()) 122 (*it)->DidUpdateLayers(host_); 123 } 124 125 CleanUpFinishedBenchmarks(); 126} 127 128void MicroBenchmarkController::CleanUpFinishedBenchmarks() { 129 benchmarks_.erase( 130 benchmarks_.partition(std::not1(IsDonePredicate())), 131 benchmarks_.end()); 132} 133 134} // namespace cc 135