Rewrite AndroidSyncSettings to be significantly simpler.
[chromium-blink-merge.git] / cc / debug / rasterize_and_record_benchmark.cc
blobe56a1e136d1c6cf5ffe6fc4a3f21e8617b29d01d
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/resources/display_item_list.h"
20 #include "cc/resources/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 {"", "_sk_null_canvas", "_painting_disabled", "_caching_disabled"};
40 } // namespace
42 RasterizeAndRecordBenchmark::RasterizeAndRecordBenchmark(
43 scoped_ptr<base::Value> value,
44 const MicroBenchmark::DoneCallback& callback)
45 : MicroBenchmark(callback),
46 record_repeat_count_(kDefaultRecordRepeatCount),
47 settings_(value.Pass()),
48 main_thread_benchmark_done_(false),
49 host_(nullptr),
50 weak_ptr_factory_(this) {
51 base::DictionaryValue* settings = nullptr;
52 settings_->GetAsDictionary(&settings);
53 if (!settings)
54 return;
56 if (settings->HasKey("record_repeat_count"))
57 settings->GetInteger("record_repeat_count", &record_repeat_count_);
60 RasterizeAndRecordBenchmark::~RasterizeAndRecordBenchmark() {
61 weak_ptr_factory_.InvalidateWeakPtrs();
64 void RasterizeAndRecordBenchmark::DidUpdateLayers(LayerTreeHost* host) {
65 host_ = host;
66 LayerTreeHostCommon::CallFunctionForSubtree(
67 host->root_layer(),
68 base::Bind(&RasterizeAndRecordBenchmark::Run, base::Unretained(this)));
70 DCHECK(!results_.get());
71 results_ = make_scoped_ptr(new base::DictionaryValue);
72 results_->SetInteger("pixels_recorded", record_results_.pixels_recorded);
73 results_->SetInteger("picture_memory_usage", record_results_.bytes_used);
75 for (int i = 0; i < RecordingSource::RECORDING_MODE_COUNT; i++) {
76 std::string name = base::StringPrintf("record_time%s_ms", kModeSuffixes[i]);
77 results_->SetDouble(name,
78 record_results_.total_best_time[i].InMillisecondsF());
80 main_thread_benchmark_done_ = true;
83 void RasterizeAndRecordBenchmark::RecordRasterResults(
84 scoped_ptr<base::Value> results_value) {
85 DCHECK(main_thread_benchmark_done_);
87 base::DictionaryValue* results = nullptr;
88 results_value->GetAsDictionary(&results);
89 DCHECK(results);
91 results_->MergeDictionary(results);
93 NotifyDone(results_.Pass());
96 scoped_ptr<MicroBenchmarkImpl> RasterizeAndRecordBenchmark::CreateBenchmarkImpl(
97 scoped_refptr<base::MessageLoopProxy> origin_loop) {
98 return make_scoped_ptr(new RasterizeAndRecordBenchmarkImpl(
99 origin_loop,
100 settings_.get(),
101 base::Bind(&RasterizeAndRecordBenchmark::RecordRasterResults,
102 weak_ptr_factory_.GetWeakPtr())));
105 void RasterizeAndRecordBenchmark::Run(Layer* layer) {
106 layer->RunMicroBenchmark(this);
109 void RasterizeAndRecordBenchmark::RunOnLayer(PictureLayer* layer) {
110 DCHECK(host_);
112 gfx::Rect visible_content_rect = gfx::ScaleToEnclosingRect(
113 layer->visible_content_rect(), 1.f / layer->contents_scale_x());
114 if (visible_content_rect.IsEmpty())
115 return;
117 if (host_->settings().use_display_lists) {
118 RunOnDisplayListLayer(layer, visible_content_rect);
119 } else {
120 RunOnPictureLayer(layer, visible_content_rect);
124 void RasterizeAndRecordBenchmark::RunOnPictureLayer(
125 PictureLayer* layer,
126 const gfx::Rect& visible_content_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);
137 base::TimeDelta min_time = base::TimeDelta::Max();
138 size_t memory_used = 0;
140 for (int i = 0; i < record_repeat_count_; ++i) {
141 // Run for a minimum amount of time to avoid problems with timer
142 // quantization when the layer is very small.
143 LapTimer timer(kWarmupRuns,
144 base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
145 kTimeCheckInterval);
146 scoped_refptr<Picture> picture;
147 do {
148 picture = Picture::Create(visible_content_rect, painter, tile_grid_size,
149 false, mode);
150 if (memory_used) {
151 // Verify we are recording the same thing each time.
152 DCHECK(memory_used == picture->ApproximateMemoryUsage());
153 } else {
154 memory_used = picture->ApproximateMemoryUsage();
157 timer.NextLap();
158 } while (!timer.HasTimeLimitExpired());
159 base::TimeDelta duration =
160 base::TimeDelta::FromMillisecondsD(timer.MsPerLap());
161 if (duration < min_time)
162 min_time = duration;
165 if (mode == RecordingSource::RECORD_NORMALLY) {
166 record_results_.bytes_used += memory_used;
167 record_results_.pixels_recorded +=
168 visible_content_rect.width() * visible_content_rect.height();
170 record_results_.total_best_time[mode_index] += min_time;
174 void RasterizeAndRecordBenchmark::RunOnDisplayListLayer(
175 PictureLayer* layer,
176 const gfx::Rect& visible_content_rect) {
177 ContentLayerClient* painter = layer->client();
179 DCHECK(host_ && host_->settings().use_display_lists);
181 for (int mode_index = 0; mode_index < RecordingSource::RECORDING_MODE_COUNT;
182 mode_index++) {
183 ContentLayerClient::PaintingControlSetting painting_control =
184 ContentLayerClient::PAINTING_BEHAVIOR_NORMAL;
185 switch (static_cast<RecordingSource::RecordingMode>(mode_index)) {
186 case RecordingSource::RECORD_NORMALLY:
187 // Already setup for normal recording.
188 break;
189 case RecordingSource::RECORD_WITH_SK_NULL_CANVAS:
190 // TODO(schenney): Remove this when DisplayList recording is the only
191 // option. For now, fall through and disable construction.
192 case RecordingSource::RECORD_WITH_PAINTING_DISABLED:
193 painting_control =
194 ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED;
195 break;
196 case RecordingSource::RECORD_WITH_CACHING_DISABLED:
197 painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED;
198 break;
199 default:
200 NOTREACHED();
202 base::TimeDelta min_time = base::TimeDelta::Max();
203 size_t memory_used = 0;
205 scoped_refptr<DisplayItemList> display_list;
206 for (int i = 0; i < record_repeat_count_; ++i) {
207 // Run for a minimum amount of time to avoid problems with timer
208 // quantization when the layer is very small.
209 LapTimer timer(kWarmupRuns,
210 base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
211 kTimeCheckInterval);
213 do {
214 display_list = painter->PaintContentsToDisplayList(visible_content_rect,
215 painting_control);
217 if (memory_used) {
218 // Verify we are recording the same thing each time.
219 DCHECK(memory_used == display_list->PictureMemoryUsage());
220 } else {
221 memory_used = display_list->PictureMemoryUsage();
224 timer.NextLap();
225 } while (!timer.HasTimeLimitExpired());
226 base::TimeDelta duration =
227 base::TimeDelta::FromMillisecondsD(timer.MsPerLap());
228 if (duration < min_time)
229 min_time = duration;
232 record_results_.bytes_used += memory_used;
233 record_results_.pixels_recorded +=
234 visible_content_rect.width() * visible_content_rect.height();
235 record_results_.total_best_time[mode_index] += min_time;
239 RasterizeAndRecordBenchmark::RecordResults::RecordResults()
240 : pixels_recorded(0), bytes_used(0) {
243 RasterizeAndRecordBenchmark::RecordResults::~RecordResults() {}
245 } // namespace cc