14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file.
44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "cc/debug/micro_benchmark_controller.h"
64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <limits>
84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <string>
94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/callback.h"
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/values.h"
1346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "cc/debug/invalidation_benchmark.h"
144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "cc/debug/picture_record_benchmark.h"
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "cc/debug/rasterize_and_record_benchmark.h"
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "cc/debug/unittest_only_benchmark.h"
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "cc/trees/layer_tree_host.h"
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "cc/trees/layer_tree_host_impl.h"
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace cc {
214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int MicroBenchmarkController::next_id_ = 1;
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace {
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)scoped_ptr<MicroBenchmark> CreateBenchmark(
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const std::string& name,
288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    scoped_ptr<base::Value> value,
294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const MicroBenchmark::DoneCallback& callback) {
3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (name == "invalidation_benchmark") {
3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return scoped_ptr<MicroBenchmark>(
3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        new InvalidationBenchmark(value.Pass(), callback));
3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  } else if (name == "picture_record_benchmark") {
348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return scoped_ptr<MicroBenchmark>(
358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        new PictureRecordBenchmark(value.Pass(), callback));
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else if (name == "rasterize_and_record_benchmark") {
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return scoped_ptr<MicroBenchmark>(
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        new RasterizeAndRecordBenchmark(value.Pass(), callback));
398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  } else if (name == "unittest_only_benchmark") {
408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return scoped_ptr<MicroBenchmark>(
418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        new UnittestOnlyBenchmark(value.Pass(), callback));
428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return scoped_ptr<MicroBenchmark>();
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class IsDonePredicate {
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public:
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  typedef const MicroBenchmark* argument_type;
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  typedef bool result_type;
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  result_type operator()(argument_type benchmark) const {
524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return benchmark->IsDone();
534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace
574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)MicroBenchmarkController::MicroBenchmarkController(LayerTreeHost* host)
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : host_(host),
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      main_controller_message_loop_(base::MessageLoopProxy::current().get()) {
614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(host_);
624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)MicroBenchmarkController::~MicroBenchmarkController() {}
654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int MicroBenchmarkController::ScheduleRun(
674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const std::string& micro_benchmark_name,
688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    scoped_ptr<base::Value> value,
694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const MicroBenchmark::DoneCallback& callback) {
704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  scoped_ptr<MicroBenchmark> benchmark =
718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      CreateBenchmark(micro_benchmark_name, value.Pass(), callback);
724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (benchmark.get()) {
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int id = GetNextIdAndIncrement();
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    benchmark->set_id(id);
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    benchmarks_.push_back(benchmark.Pass());
764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    host_->SetNeedsCommit();
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return id;
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return 0;
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int MicroBenchmarkController::GetNextIdAndIncrement() {
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int id = next_id_++;
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Wrap around to 1 if we overflow (very unlikely).
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (next_id_ == std::numeric_limits<int>::max())
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    next_id_ = 1;
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return id;
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool MicroBenchmarkController::SendMessage(int id,
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                           scoped_ptr<base::Value> value) {
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (ScopedPtrVector<MicroBenchmark>::iterator it = benchmarks_.begin();
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       it != benchmarks_.end();
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       ++it) {
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if ((*it)->id() == id)
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return (*it)->ProcessMessage(value.Pass());
974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return false;
994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MicroBenchmarkController::ScheduleImplBenchmarks(
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    LayerTreeHostImpl* host_impl) {
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (ScopedPtrVector<MicroBenchmark>::iterator it = benchmarks_.begin();
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       it != benchmarks_.end();
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       ++it) {
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    scoped_ptr<MicroBenchmarkImpl> benchmark_impl;
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!(*it)->ProcessedForBenchmarkImpl()) {
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      benchmark_impl =
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          (*it)->GetBenchmarkImpl(main_controller_message_loop_);
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (benchmark_impl.get())
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      host_impl->ScheduleMicroBenchmark(benchmark_impl.Pass());
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void MicroBenchmarkController::DidUpdateLayers() {
1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (ScopedPtrVector<MicroBenchmark>::iterator it = benchmarks_.begin();
1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       it != benchmarks_.end();
1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       ++it) {
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!(*it)->IsDone())
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      (*it)->DidUpdateLayers(host_);
1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  CleanUpFinishedBenchmarks();
1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void MicroBenchmarkController::CleanUpFinishedBenchmarks() {
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  benchmarks_.erase(
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      benchmarks_.partition(std::not1(IsDonePredicate())),
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      benchmarks_.end());
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace cc
135