Setup a experiment to enable background tracing.
[chromium-blink-merge.git] / cc / debug / rasterize_and_record_benchmark.cc
blobe68f5de320d9fc2fccfc3cc44e52f85fdf95171b
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 "third_party/skia/include/utils/SkPictureUtils.h"
24 #include "ui/gfx/geometry/rect.h"
26 namespace cc {
28 namespace {
30 const int kDefaultRecordRepeatCount = 100;
32 // Parameters for LapTimer.
33 const int kTimeLimitMillis = 1;
34 const int kWarmupRuns = 0;
35 const int kTimeCheckInterval = 1;
37 const char* kModeSuffixes[RecordingSource::RECORDING_MODE_COUNT] = {
38 "",
39 "_sk_null_canvas",
40 "_painting_disabled",
41 "_caching_disabled",
42 "_construction_disabled"};
44 } // namespace
46 RasterizeAndRecordBenchmark::RasterizeAndRecordBenchmark(
47 scoped_ptr<base::Value> value,
48 const MicroBenchmark::DoneCallback& callback)
49 : MicroBenchmark(callback),
50 record_repeat_count_(kDefaultRecordRepeatCount),
51 settings_(value.Pass()),
52 main_thread_benchmark_done_(false),
53 host_(nullptr),
54 weak_ptr_factory_(this) {
55 base::DictionaryValue* settings = nullptr;
56 settings_->GetAsDictionary(&settings);
57 if (!settings)
58 return;
60 if (settings->HasKey("record_repeat_count"))
61 settings->GetInteger("record_repeat_count", &record_repeat_count_);
64 RasterizeAndRecordBenchmark::~RasterizeAndRecordBenchmark() {
65 weak_ptr_factory_.InvalidateWeakPtrs();
68 void RasterizeAndRecordBenchmark::DidUpdateLayers(LayerTreeHost* host) {
69 host_ = host;
70 LayerTreeHostCommon::CallFunctionForSubtree(
71 host->root_layer(),
72 [this](Layer* layer) { layer->RunMicroBenchmark(this); });
74 DCHECK(!results_.get());
75 results_ = make_scoped_ptr(new base::DictionaryValue);
76 results_->SetInteger("pixels_recorded", record_results_.pixels_recorded);
77 results_->SetInteger("picture_memory_usage",
78 static_cast<int>(record_results_.bytes_used));
80 for (int i = 0; i < RecordingSource::RECORDING_MODE_COUNT; i++) {
81 std::string name = base::StringPrintf("record_time%s_ms", kModeSuffixes[i]);
82 results_->SetDouble(name,
83 record_results_.total_best_time[i].InMillisecondsF());
85 main_thread_benchmark_done_ = true;
88 void RasterizeAndRecordBenchmark::RecordRasterResults(
89 scoped_ptr<base::Value> results_value) {
90 DCHECK(main_thread_benchmark_done_);
92 base::DictionaryValue* results = nullptr;
93 results_value->GetAsDictionary(&results);
94 DCHECK(results);
96 results_->MergeDictionary(results);
98 NotifyDone(results_.Pass());
101 scoped_ptr<MicroBenchmarkImpl> RasterizeAndRecordBenchmark::CreateBenchmarkImpl(
102 scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner) {
103 return make_scoped_ptr(new RasterizeAndRecordBenchmarkImpl(
104 origin_task_runner, settings_.get(),
105 base::Bind(&RasterizeAndRecordBenchmark::RecordRasterResults,
106 weak_ptr_factory_.GetWeakPtr())));
109 void RasterizeAndRecordBenchmark::RunOnLayer(PictureLayer* layer) {
110 DCHECK(host_);
112 gfx::Rect visible_layer_rect = gfx::ScaleToEnclosingRect(
113 layer->visible_content_rect(), 1.f / layer->contents_scale_x());
114 if (visible_layer_rect.IsEmpty())
115 return;
117 if (host_->settings().use_display_lists) {
118 RunOnDisplayListLayer(layer, visible_layer_rect);
119 } else {
120 RunOnPictureLayer(layer, visible_layer_rect);
124 void RasterizeAndRecordBenchmark::RunOnPictureLayer(
125 PictureLayer* layer,
126 const gfx::Rect& visible_layer_rect) {
127 ContentLayerClient* painter = layer->client();
129 DCHECK(host_ && !host_->settings().use_display_lists);
131 gfx::Size tile_grid_size = host_->settings().default_tile_size;
133 for (int mode_index = 0; mode_index < RecordingSource::RECORDING_MODE_COUNT;
134 mode_index++) {
135 RecordingSource::RecordingMode mode =
136 static_cast<RecordingSource::RecordingMode>(mode_index);
138 // Not supported for SkPicture recording.
139 if (mode == RecordingSource::RECORD_WITH_CONSTRUCTION_DISABLED)
140 continue;
142 base::TimeDelta min_time = base::TimeDelta::Max();
143 size_t memory_used = 0;
145 for (int i = 0; i < record_repeat_count_; ++i) {
146 // Run for a minimum amount of time to avoid problems with timer
147 // quantization when the layer is very small.
148 LapTimer timer(kWarmupRuns,
149 base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
150 kTimeCheckInterval);
151 scoped_refptr<Picture> picture;
152 do {
153 picture = Picture::Create(visible_layer_rect, painter, tile_grid_size,
154 false, mode);
155 if (memory_used) {
156 // Verify we are recording the same thing each time.
157 DCHECK(memory_used == picture->ApproximateMemoryUsage());
158 } else {
159 memory_used = picture->ApproximateMemoryUsage();
162 timer.NextLap();
163 } while (!timer.HasTimeLimitExpired());
164 base::TimeDelta duration =
165 base::TimeDelta::FromMillisecondsD(timer.MsPerLap());
166 if (duration < min_time)
167 min_time = duration;
170 if (mode == RecordingSource::RECORD_NORMALLY) {
171 record_results_.bytes_used += memory_used;
172 record_results_.pixels_recorded +=
173 visible_layer_rect.width() * visible_layer_rect.height();
175 record_results_.total_best_time[mode_index] += min_time;
179 void RasterizeAndRecordBenchmark::RunOnDisplayListLayer(
180 PictureLayer* layer,
181 const gfx::Rect& visible_layer_rect) {
182 ContentLayerClient* painter = layer->client();
184 DCHECK(host_ && host_->settings().use_display_lists);
186 for (int mode_index = 0; mode_index < RecordingSource::RECORDING_MODE_COUNT;
187 mode_index++) {
188 ContentLayerClient::PaintingControlSetting painting_control =
189 ContentLayerClient::PAINTING_BEHAVIOR_NORMAL;
190 switch (static_cast<RecordingSource::RecordingMode>(mode_index)) {
191 case RecordingSource::RECORD_NORMALLY:
192 // Already setup for normal recording.
193 break;
194 case RecordingSource::RECORD_WITH_SK_NULL_CANVAS:
195 // Not supported for Display List recording.
196 continue;
197 case RecordingSource::RECORD_WITH_PAINTING_DISABLED:
198 painting_control = ContentLayerClient::DISPLAY_LIST_PAINTING_DISABLED;
199 break;
200 case RecordingSource::RECORD_WITH_CACHING_DISABLED:
201 painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED;
202 break;
203 case RecordingSource::RECORD_WITH_CONSTRUCTION_DISABLED:
204 painting_control =
205 ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED;
206 break;
207 default:
208 NOTREACHED();
210 base::TimeDelta min_time = base::TimeDelta::Max();
211 size_t memory_used = 0;
213 scoped_refptr<DisplayItemList> display_list;
214 for (int i = 0; i < record_repeat_count_; ++i) {
215 // Run for a minimum amount of time to avoid problems with timer
216 // quantization when the layer is very small.
217 LapTimer timer(kWarmupRuns,
218 base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
219 kTimeCheckInterval);
221 do {
222 display_list = painter->PaintContentsToDisplayList(visible_layer_rect,
223 painting_control);
225 if (memory_used) {
226 // Verify we are recording the same thing each time.
227 DCHECK(memory_used == display_list->PictureMemoryUsage());
228 } else {
229 memory_used = display_list->PictureMemoryUsage();
232 timer.NextLap();
233 } while (!timer.HasTimeLimitExpired());
234 base::TimeDelta duration =
235 base::TimeDelta::FromMillisecondsD(timer.MsPerLap());
236 if (duration < min_time)
237 min_time = duration;
240 if (mode_index == RecordingSource::RECORD_NORMALLY) {
241 record_results_.bytes_used += memory_used;
242 record_results_.pixels_recorded +=
243 visible_layer_rect.width() * visible_layer_rect.height();
245 record_results_.total_best_time[mode_index] += min_time;
249 RasterizeAndRecordBenchmark::RecordResults::RecordResults()
250 : pixels_recorded(0), bytes_used(0) {
253 RasterizeAndRecordBenchmark::RecordResults::~RecordResults() {}
255 } // namespace cc