Avoid lossy time stamp conversions when caching metadata.
[chromium-blink-merge.git] / cc / debug / rasterize_and_record_benchmark.cc
blob3a0c98b0fb32bf850f3979a70a84e8ba3a86f8e7
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[Picture::RECORDING_MODE_COUNT] = {
38 "",
39 "_sk_null_canvas",
40 "_painting_disabled"};
42 } // namespace
44 RasterizeAndRecordBenchmark::RasterizeAndRecordBenchmark(
45 scoped_ptr<base::Value> value,
46 const MicroBenchmark::DoneCallback& callback)
47 : MicroBenchmark(callback),
48 record_repeat_count_(kDefaultRecordRepeatCount),
49 settings_(value.Pass()),
50 main_thread_benchmark_done_(false),
51 host_(nullptr),
52 weak_ptr_factory_(this) {
53 base::DictionaryValue* settings = nullptr;
54 settings_->GetAsDictionary(&settings);
55 if (!settings)
56 return;
58 if (settings->HasKey("record_repeat_count"))
59 settings->GetInteger("record_repeat_count", &record_repeat_count_);
62 RasterizeAndRecordBenchmark::~RasterizeAndRecordBenchmark() {
63 weak_ptr_factory_.InvalidateWeakPtrs();
66 void RasterizeAndRecordBenchmark::DidUpdateLayers(LayerTreeHost* host) {
67 host_ = host;
68 LayerTreeHostCommon::CallFunctionForSubtree(
69 host->root_layer(),
70 base::Bind(&RasterizeAndRecordBenchmark::Run, base::Unretained(this)));
72 DCHECK(!results_.get());
73 results_ = make_scoped_ptr(new base::DictionaryValue);
74 results_->SetInteger("pixels_recorded", record_results_.pixels_recorded);
75 results_->SetInteger("picture_memory_usage", record_results_.bytes_used);
77 for (int i = 0; i < Picture::RECORDING_MODE_COUNT; i++) {
78 std::string name = base::StringPrintf("record_time%s_ms", kModeSuffixes[i]);
79 results_->SetDouble(name,
80 record_results_.total_best_time[i].InMillisecondsF());
82 main_thread_benchmark_done_ = true;
85 void RasterizeAndRecordBenchmark::RecordRasterResults(
86 scoped_ptr<base::Value> results_value) {
87 DCHECK(main_thread_benchmark_done_);
89 base::DictionaryValue* results = nullptr;
90 results_value->GetAsDictionary(&results);
91 DCHECK(results);
93 results_->MergeDictionary(results);
95 NotifyDone(results_.Pass());
98 scoped_ptr<MicroBenchmarkImpl> RasterizeAndRecordBenchmark::CreateBenchmarkImpl(
99 scoped_refptr<base::MessageLoopProxy> origin_loop) {
100 return make_scoped_ptr(new RasterizeAndRecordBenchmarkImpl(
101 origin_loop,
102 settings_.get(),
103 base::Bind(&RasterizeAndRecordBenchmark::RecordRasterResults,
104 weak_ptr_factory_.GetWeakPtr())));
107 void RasterizeAndRecordBenchmark::Run(Layer* layer) {
108 layer->RunMicroBenchmark(this);
111 void RasterizeAndRecordBenchmark::RunOnLayer(PictureLayer* layer) {
112 DCHECK(host_);
114 gfx::Rect visible_content_rect = gfx::ScaleToEnclosingRect(
115 layer->visible_content_rect(), 1.f / layer->contents_scale_x());
116 if (visible_content_rect.IsEmpty())
117 return;
119 if (host_->settings().use_display_lists) {
120 RunOnDisplayListLayer(layer, visible_content_rect);
121 } else {
122 RunOnPictureLayer(layer, visible_content_rect);
126 void RasterizeAndRecordBenchmark::RunOnPictureLayer(
127 PictureLayer* layer,
128 const gfx::Rect& visible_content_rect) {
129 ContentLayerClient* painter = layer->client();
131 DCHECK(host_ && !host_->settings().use_display_lists);
133 gfx::Size tile_grid_size = host_->settings().default_tile_size;
135 for (int mode_index = 0; mode_index < Picture::RECORDING_MODE_COUNT;
136 mode_index++) {
137 Picture::RecordingMode mode =
138 static_cast<Picture::RecordingMode>(mode_index);
139 base::TimeDelta min_time = base::TimeDelta::Max();
140 size_t memory_used = 0;
142 for (int i = 0; i < record_repeat_count_; ++i) {
143 // Run for a minimum amount of time to avoid problems with timer
144 // quantization when the layer is very small.
145 LapTimer timer(kWarmupRuns,
146 base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
147 kTimeCheckInterval);
148 scoped_refptr<Picture> picture;
149 do {
150 picture = Picture::Create(visible_content_rect, painter, tile_grid_size,
151 false, mode);
152 if (memory_used) {
153 // Verify we are recording the same thing each time.
154 DCHECK(memory_used == picture->ApproximateMemoryUsage());
155 } else {
156 memory_used = picture->ApproximateMemoryUsage();
159 timer.NextLap();
160 } while (!timer.HasTimeLimitExpired());
161 base::TimeDelta duration =
162 base::TimeDelta::FromMillisecondsD(timer.MsPerLap());
163 if (duration < min_time)
164 min_time = duration;
167 if (mode == Picture::RECORD_NORMALLY) {
168 record_results_.bytes_used += memory_used;
169 record_results_.pixels_recorded +=
170 visible_content_rect.width() * visible_content_rect.height();
172 record_results_.total_best_time[mode_index] += min_time;
176 void RasterizeAndRecordBenchmark::RunOnDisplayListLayer(
177 PictureLayer* layer,
178 const gfx::Rect& visible_content_rect) {
179 ContentLayerClient* painter = layer->client();
181 DCHECK(host_ && host_->settings().use_display_lists);
183 base::TimeDelta min_time = base::TimeDelta::Max();
184 size_t memory_used = 0;
186 // TODO(schenney): What are the corresponding Picture::RecordingMode modes
187 // for Slimming Paint. We could disable SkPicture creation in
188 // DrawingDisplayItems, or we could only generate the display list and not
189 // do any work on it in the compositor, or something else, or all of the
190 // above.
191 scoped_refptr<DisplayItemList> display_list;
192 for (int i = 0; i < record_repeat_count_; ++i) {
193 // Run for a minimum amount of time to avoid problems with timer
194 // quantization when the layer is very small.
195 LapTimer timer(kWarmupRuns,
196 base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
197 kTimeCheckInterval);
199 do {
200 // TODO(schenney): Cached content will not be regenerated, which skews
201 // the results significantly in favor of Slimming Paint (or should).
202 // Add a flag or API call to disable caching, and maybe run the test
203 // twice, without and with caching.
204 display_list = painter->PaintContentsToDisplayList(
205 visible_content_rect, ContentLayerClient::GRAPHICS_CONTEXT_ENABLED);
207 if (memory_used) {
208 // Verify we are recording the same thing each time.
209 DCHECK(memory_used == display_list->PictureMemoryUsage());
210 } else {
211 memory_used = display_list->PictureMemoryUsage();
214 timer.NextLap();
215 } while (!timer.HasTimeLimitExpired());
216 base::TimeDelta duration =
217 base::TimeDelta::FromMillisecondsD(timer.MsPerLap());
218 if (duration < min_time)
219 min_time = duration;
222 record_results_.bytes_used += memory_used;
223 record_results_.pixels_recorded +=
224 visible_content_rect.width() * visible_content_rect.height();
225 record_results_.total_best_time[Picture::RECORD_NORMALLY] += min_time;
228 RasterizeAndRecordBenchmark::RecordResults::RecordResults()
229 : pixels_recorded(0), bytes_used(0) {
232 RasterizeAndRecordBenchmark::RecordResults::~RecordResults() {}
234 } // namespace cc