Roll src/third_party/WebKit 2f4214f:d3a4736 (svn 202056:202057)
[chromium-blink-merge.git] / cc / debug / rasterize_and_record_benchmark.cc
blobb2534366a515f2a571ae3a8e11c4c3688e859908
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 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 (picture->ShouldBeAnalyzedForSolidColor()) {
156 gfx::Size layer_size = layer->paint_properties().bounds;
157 skia::AnalysisCanvas canvas(layer_size.width(), layer_size.height());
158 picture->Raster(&canvas, nullptr, gfx::Rect(), 1.f);
160 if (memory_used) {
161 // Verify we are recording the same thing each time.
162 DCHECK(memory_used == picture->ApproximateMemoryUsage());
163 } else {
164 memory_used = picture->ApproximateMemoryUsage();
167 timer.NextLap();
168 } while (!timer.HasTimeLimitExpired());
169 base::TimeDelta duration =
170 base::TimeDelta::FromMillisecondsD(timer.MsPerLap());
171 if (duration < min_time)
172 min_time = duration;
175 if (mode == RecordingSource::RECORD_NORMALLY) {
176 record_results_.bytes_used += memory_used;
177 record_results_.pixels_recorded +=
178 visible_layer_rect.width() * visible_layer_rect.height();
180 record_results_.total_best_time[mode_index] += min_time;
184 void RasterizeAndRecordBenchmark::RunOnDisplayListLayer(
185 PictureLayer* layer,
186 const gfx::Rect& visible_layer_rect) {
187 ContentLayerClient* painter = layer->client();
189 DCHECK(host_ && host_->settings().use_display_lists);
191 for (int mode_index = 0; mode_index < RecordingSource::RECORDING_MODE_COUNT;
192 mode_index++) {
193 ContentLayerClient::PaintingControlSetting painting_control =
194 ContentLayerClient::PAINTING_BEHAVIOR_NORMAL;
195 switch (static_cast<RecordingSource::RecordingMode>(mode_index)) {
196 case RecordingSource::RECORD_NORMALLY:
197 // Already setup for normal recording.
198 break;
199 case RecordingSource::RECORD_WITH_SK_NULL_CANVAS:
200 // Not supported for Display List recording.
201 continue;
202 case RecordingSource::RECORD_WITH_PAINTING_DISABLED:
203 painting_control = ContentLayerClient::DISPLAY_LIST_PAINTING_DISABLED;
204 break;
205 case RecordingSource::RECORD_WITH_CACHING_DISABLED:
206 painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED;
207 break;
208 case RecordingSource::RECORD_WITH_CONSTRUCTION_DISABLED:
209 painting_control =
210 ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED;
211 break;
212 default:
213 NOTREACHED();
215 base::TimeDelta min_time = base::TimeDelta::Max();
216 size_t memory_used = 0;
218 scoped_refptr<DisplayItemList> display_list;
219 for (int i = 0; i < record_repeat_count_; ++i) {
220 // Run for a minimum amount of time to avoid problems with timer
221 // quantization when the layer is very small.
222 LapTimer timer(kWarmupRuns,
223 base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
224 kTimeCheckInterval);
226 do {
227 display_list = painter->PaintContentsToDisplayList(visible_layer_rect,
228 painting_control);
229 if (display_list->ShouldBeAnalyzedForSolidColor()) {
230 gfx::Size layer_size = layer->paint_properties().bounds;
231 skia::AnalysisCanvas canvas(layer_size.width(), layer_size.height());
232 display_list->Raster(&canvas, nullptr, gfx::Rect(), 1.f);
235 if (memory_used) {
236 // Verify we are recording the same thing each time.
237 DCHECK_EQ(memory_used, display_list->ApproximateMemoryUsage());
238 } else {
239 memory_used = display_list->ApproximateMemoryUsage();
242 timer.NextLap();
243 } while (!timer.HasTimeLimitExpired());
244 base::TimeDelta duration =
245 base::TimeDelta::FromMillisecondsD(timer.MsPerLap());
246 if (duration < min_time)
247 min_time = duration;
250 if (mode_index == RecordingSource::RECORD_NORMALLY) {
251 record_results_.bytes_used +=
252 memory_used + painter->GetApproximateUnsharedMemoryUsage();
253 record_results_.pixels_recorded +=
254 visible_layer_rect.width() * visible_layer_rect.height();
256 record_results_.total_best_time[mode_index] += min_time;
260 RasterizeAndRecordBenchmark::RecordResults::RecordResults()
261 : pixels_recorded(0), bytes_used(0) {
264 RasterizeAndRecordBenchmark::RecordResults::~RecordResults() {}
266 } // namespace cc