Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / cc / debug / rasterize_and_record_benchmark.cc
blob0f47cd87842a255ca46e7d43acc6f5100415d6fc
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.
5 #include "cc/debug/rasterize_and_record_benchmark.h"
7 #include <algorithm>
8 #include <limits>
9 #include <string>
11 #include "base/basictypes.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/values.h"
14 #include "cc/debug/lap_timer.h"
15 #include "cc/debug/rasterize_and_record_benchmark_impl.h"
16 #include "cc/layers/content_layer_client.h"
17 #include "cc/layers/layer.h"
18 #include "cc/layers/picture_layer.h"
19 #include "cc/playback/display_item_list.h"
20 #include "cc/playback/picture_pile.h"
21 #include "cc/trees/layer_tree_host.h"
22 #include "cc/trees/layer_tree_host_common.h"
23 #include "skia/ext/analysis_canvas.h"
24 #include "third_party/skia/include/utils/SkPictureUtils.h"
25 #include "ui/gfx/geometry/rect.h"
27 namespace cc {
29 namespace {
31 const int kDefaultRecordRepeatCount = 100;
33 // Parameters for LapTimer.
34 const int kTimeLimitMillis = 1;
35 const int kWarmupRuns = 0;
36 const int kTimeCheckInterval = 1;
38 const char* kModeSuffixes[RecordingSource::RECORDING_MODE_COUNT] = {
39 "",
40 "_sk_null_canvas",
41 "_painting_disabled",
42 "_caching_disabled",
43 "_construction_disabled"};
45 } // namespace
47 RasterizeAndRecordBenchmark::RasterizeAndRecordBenchmark(
48 scoped_ptr<base::Value> value,
49 const MicroBenchmark::DoneCallback& callback)
50 : MicroBenchmark(callback),
51 record_repeat_count_(kDefaultRecordRepeatCount),
52 settings_(value.Pass()),
53 main_thread_benchmark_done_(false),
54 host_(nullptr),
55 weak_ptr_factory_(this) {
56 base::DictionaryValue* settings = nullptr;
57 settings_->GetAsDictionary(&settings);
58 if (!settings)
59 return;
61 if (settings->HasKey("record_repeat_count"))
62 settings->GetInteger("record_repeat_count", &record_repeat_count_);
65 RasterizeAndRecordBenchmark::~RasterizeAndRecordBenchmark() {
66 weak_ptr_factory_.InvalidateWeakPtrs();
69 void RasterizeAndRecordBenchmark::DidUpdateLayers(LayerTreeHost* host) {
70 host_ = host;
71 LayerTreeHostCommon::CallFunctionForSubtree(
72 host->root_layer(),
73 [this](Layer* layer) { layer->RunMicroBenchmark(this); });
75 DCHECK(!results_.get());
76 results_ = make_scoped_ptr(new base::DictionaryValue);
77 results_->SetInteger("pixels_recorded", record_results_.pixels_recorded);
78 results_->SetInteger("picture_memory_usage",
79 static_cast<int>(record_results_.bytes_used));
81 for (int i = 0; i < RecordingSource::RECORDING_MODE_COUNT; i++) {
82 std::string name = base::StringPrintf("record_time%s_ms", kModeSuffixes[i]);
83 results_->SetDouble(name,
84 record_results_.total_best_time[i].InMillisecondsF());
86 main_thread_benchmark_done_ = true;
89 void RasterizeAndRecordBenchmark::RecordRasterResults(
90 scoped_ptr<base::Value> results_value) {
91 DCHECK(main_thread_benchmark_done_);
93 base::DictionaryValue* results = nullptr;
94 results_value->GetAsDictionary(&results);
95 DCHECK(results);
97 results_->MergeDictionary(results);
99 NotifyDone(results_.Pass());
102 scoped_ptr<MicroBenchmarkImpl> RasterizeAndRecordBenchmark::CreateBenchmarkImpl(
103 scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner) {
104 return make_scoped_ptr(new RasterizeAndRecordBenchmarkImpl(
105 origin_task_runner, settings_.get(),
106 base::Bind(&RasterizeAndRecordBenchmark::RecordRasterResults,
107 weak_ptr_factory_.GetWeakPtr())));
110 void RasterizeAndRecordBenchmark::RunOnLayer(PictureLayer* layer) {
111 DCHECK(host_);
113 gfx::Rect visible_layer_rect = layer->visible_layer_rect();
114 if (visible_layer_rect.IsEmpty())
115 return;
117 RunOnDisplayListLayer(layer, visible_layer_rect);
120 void RasterizeAndRecordBenchmark::RunOnDisplayListLayer(
121 PictureLayer* layer,
122 const gfx::Rect& visible_layer_rect) {
123 ContentLayerClient* painter = layer->client();
125 for (int mode_index = 0; mode_index < RecordingSource::RECORDING_MODE_COUNT;
126 mode_index++) {
127 ContentLayerClient::PaintingControlSetting painting_control =
128 ContentLayerClient::PAINTING_BEHAVIOR_NORMAL;
129 switch (static_cast<RecordingSource::RecordingMode>(mode_index)) {
130 case RecordingSource::RECORD_NORMALLY:
131 // Already setup for normal recording.
132 break;
133 case RecordingSource::RECORD_WITH_SK_NULL_CANVAS:
134 // Not supported for Display List recording.
135 continue;
136 case RecordingSource::RECORD_WITH_PAINTING_DISABLED:
137 painting_control = ContentLayerClient::DISPLAY_LIST_PAINTING_DISABLED;
138 break;
139 case RecordingSource::RECORD_WITH_CACHING_DISABLED:
140 painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED;
141 break;
142 case RecordingSource::RECORD_WITH_CONSTRUCTION_DISABLED:
143 painting_control =
144 ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED;
145 break;
146 default:
147 NOTREACHED();
149 base::TimeDelta min_time = base::TimeDelta::Max();
150 size_t memory_used = 0;
152 scoped_refptr<DisplayItemList> display_list;
153 for (int i = 0; i < record_repeat_count_; ++i) {
154 // Run for a minimum amount of time to avoid problems with timer
155 // quantization when the layer is very small.
156 LapTimer timer(kWarmupRuns,
157 base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
158 kTimeCheckInterval);
160 do {
161 display_list = painter->PaintContentsToDisplayList(visible_layer_rect,
162 painting_control);
163 if (display_list->ShouldBeAnalyzedForSolidColor()) {
164 gfx::Size layer_size = layer->paint_properties().bounds;
165 skia::AnalysisCanvas canvas(layer_size.width(), layer_size.height());
166 display_list->Raster(&canvas, nullptr, gfx::Rect(), 1.f);
169 if (memory_used) {
170 // Verify we are recording the same thing each time.
171 DCHECK_EQ(memory_used, display_list->ApproximateMemoryUsage());
172 } else {
173 memory_used = display_list->ApproximateMemoryUsage();
176 timer.NextLap();
177 } while (!timer.HasTimeLimitExpired());
178 base::TimeDelta duration =
179 base::TimeDelta::FromMillisecondsD(timer.MsPerLap());
180 if (duration < min_time)
181 min_time = duration;
184 if (mode_index == RecordingSource::RECORD_NORMALLY) {
185 record_results_.bytes_used +=
186 memory_used + painter->GetApproximateUnsharedMemoryUsage();
187 record_results_.pixels_recorded +=
188 visible_layer_rect.width() * visible_layer_rect.height();
190 record_results_.total_best_time[mode_index] += min_time;
194 RasterizeAndRecordBenchmark::RecordResults::RecordResults()
195 : pixels_recorded(0), bytes_used(0) {
198 RasterizeAndRecordBenchmark::RecordResults::~RecordResults() {}
200 } // namespace cc