| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "cc/debug/rasterize_and_record_benchmark.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <limits> | |
| 9 #include <string> | |
| 10 | |
| 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" | |
| 25 | |
| 26 namespace cc { | |
| 27 | |
| 28 namespace { | |
| 29 | |
| 30 const int kDefaultRecordRepeatCount = 100; | |
| 31 | |
| 32 // Parameters for LapTimer. | |
| 33 const int kTimeLimitMillis = 1; | |
| 34 const int kWarmupRuns = 0; | |
| 35 const int kTimeCheckInterval = 1; | |
| 36 | |
| 37 const char* kModeSuffixes[RecordingSource::RECORDING_MODE_COUNT] = | |
| 38 {"", "_sk_null_canvas", "_painting_disabled", "_caching_disabled"}; | |
| 39 | |
| 40 } // namespace | |
| 41 | |
| 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; | |
| 55 | |
| 56 if (settings->HasKey("record_repeat_count")) | |
| 57 settings->GetInteger("record_repeat_count", &record_repeat_count_); | |
| 58 } | |
| 59 | |
| 60 RasterizeAndRecordBenchmark::~RasterizeAndRecordBenchmark() { | |
| 61 weak_ptr_factory_.InvalidateWeakPtrs(); | |
| 62 } | |
| 63 | |
| 64 void RasterizeAndRecordBenchmark::DidUpdateLayers(LayerTreeHost* host) { | |
| 65 host_ = host; | |
| 66 LayerTreeHostCommon::CallFunctionForSubtree( | |
| 67 host->root_layer(), | |
| 68 [this](Layer* layer) { layer->RunMicroBenchmark(this); }); | |
| 69 | |
| 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); | |
| 74 | |
| 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()); | |
| 79 } | |
| 80 main_thread_benchmark_done_ = true; | |
| 81 } | |
| 82 | |
| 83 void RasterizeAndRecordBenchmark::RecordRasterResults( | |
| 84 scoped_ptr<base::Value> results_value) { | |
| 85 DCHECK(main_thread_benchmark_done_); | |
| 86 | |
| 87 base::DictionaryValue* results = nullptr; | |
| 88 results_value->GetAsDictionary(&results); | |
| 89 DCHECK(results); | |
| 90 | |
| 91 results_->MergeDictionary(results); | |
| 92 | |
| 93 NotifyDone(results_.Pass()); | |
| 94 } | |
| 95 | |
| 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()))); | |
| 103 } | |
| 104 | |
| 105 void RasterizeAndRecordBenchmark::RunOnLayer(PictureLayer* layer) { | |
| 106 DCHECK(host_); | |
| 107 | |
| 108 gfx::Rect visible_content_rect = gfx::ScaleToEnclosingRect( | |
| 109 layer->visible_content_rect(), 1.f / layer->contents_scale_x()); | |
| 110 if (visible_content_rect.IsEmpty()) | |
| 111 return; | |
| 112 | |
| 113 if (host_->settings().use_display_lists) { | |
| 114 RunOnDisplayListLayer(layer, visible_content_rect); | |
| 115 } else { | |
| 116 RunOnPictureLayer(layer, visible_content_rect); | |
| 117 } | |
| 118 } | |
| 119 | |
| 120 void RasterizeAndRecordBenchmark::RunOnPictureLayer( | |
| 121 PictureLayer* layer, | |
| 122 const gfx::Rect& visible_content_rect) { | |
| 123 ContentLayerClient* painter = layer->client(); | |
| 124 | |
| 125 DCHECK(host_ && !host_->settings().use_display_lists); | |
| 126 | |
| 127 gfx::Size tile_grid_size = host_->settings().default_tile_size; | |
| 128 | |
| 129 for (int mode_index = 0; mode_index < RecordingSource::RECORDING_MODE_COUNT; | |
| 130 mode_index++) { | |
| 131 RecordingSource::RecordingMode mode = | |
| 132 static_cast<RecordingSource::RecordingMode>(mode_index); | |
| 133 base::TimeDelta min_time = base::TimeDelta::Max(); | |
| 134 size_t memory_used = 0; | |
| 135 | |
| 136 for (int i = 0; i < record_repeat_count_; ++i) { | |
| 137 // Run for a minimum amount of time to avoid problems with timer | |
| 138 // quantization when the layer is very small. | |
| 139 LapTimer timer(kWarmupRuns, | |
| 140 base::TimeDelta::FromMilliseconds(kTimeLimitMillis), | |
| 141 kTimeCheckInterval); | |
| 142 scoped_refptr<Picture> picture; | |
| 143 do { | |
| 144 picture = Picture::Create(visible_content_rect, painter, tile_grid_size, | |
| 145 false, mode); | |
| 146 if (memory_used) { | |
| 147 // Verify we are recording the same thing each time. | |
| 148 DCHECK(memory_used == picture->ApproximateMemoryUsage()); | |
| 149 } else { | |
| 150 memory_used = picture->ApproximateMemoryUsage(); | |
| 151 } | |
| 152 | |
| 153 timer.NextLap(); | |
| 154 } while (!timer.HasTimeLimitExpired()); | |
| 155 base::TimeDelta duration = | |
| 156 base::TimeDelta::FromMillisecondsD(timer.MsPerLap()); | |
| 157 if (duration < min_time) | |
| 158 min_time = duration; | |
| 159 } | |
| 160 | |
| 161 if (mode == RecordingSource::RECORD_NORMALLY) { | |
| 162 record_results_.bytes_used += memory_used; | |
| 163 record_results_.pixels_recorded += | |
| 164 visible_content_rect.width() * visible_content_rect.height(); | |
| 165 } | |
| 166 record_results_.total_best_time[mode_index] += min_time; | |
| 167 } | |
| 168 } | |
| 169 | |
| 170 void RasterizeAndRecordBenchmark::RunOnDisplayListLayer( | |
| 171 PictureLayer* layer, | |
| 172 const gfx::Rect& visible_content_rect) { | |
| 173 ContentLayerClient* painter = layer->client(); | |
| 174 | |
| 175 DCHECK(host_ && host_->settings().use_display_lists); | |
| 176 | |
| 177 for (int mode_index = 0; mode_index < RecordingSource::RECORDING_MODE_COUNT; | |
| 178 mode_index++) { | |
| 179 ContentLayerClient::PaintingControlSetting painting_control = | |
| 180 ContentLayerClient::PAINTING_BEHAVIOR_NORMAL; | |
| 181 switch (static_cast<RecordingSource::RecordingMode>(mode_index)) { | |
| 182 case RecordingSource::RECORD_NORMALLY: | |
| 183 // Already setup for normal recording. | |
| 184 break; | |
| 185 case RecordingSource::RECORD_WITH_SK_NULL_CANVAS: | |
| 186 // TODO(schenney): Remove this when DisplayList recording is the only | |
| 187 // option. For now, fall through and disable construction. | |
| 188 case RecordingSource::RECORD_WITH_PAINTING_DISABLED: | |
| 189 painting_control = | |
| 190 ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED; | |
| 191 break; | |
| 192 case RecordingSource::RECORD_WITH_CACHING_DISABLED: | |
| 193 painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED; | |
| 194 break; | |
| 195 default: | |
| 196 NOTREACHED(); | |
| 197 } | |
| 198 base::TimeDelta min_time = base::TimeDelta::Max(); | |
| 199 size_t memory_used = 0; | |
| 200 | |
| 201 scoped_refptr<DisplayItemList> display_list; | |
| 202 for (int i = 0; i < record_repeat_count_; ++i) { | |
| 203 // Run for a minimum amount of time to avoid problems with timer | |
| 204 // quantization when the layer is very small. | |
| 205 LapTimer timer(kWarmupRuns, | |
| 206 base::TimeDelta::FromMilliseconds(kTimeLimitMillis), | |
| 207 kTimeCheckInterval); | |
| 208 | |
| 209 do { | |
| 210 display_list = painter->PaintContentsToDisplayList(visible_content_rect, | |
| 211 painting_control); | |
| 212 | |
| 213 if (memory_used) { | |
| 214 // Verify we are recording the same thing each time. | |
| 215 DCHECK(memory_used == display_list->PictureMemoryUsage()); | |
| 216 } else { | |
| 217 memory_used = display_list->PictureMemoryUsage(); | |
| 218 } | |
| 219 | |
| 220 timer.NextLap(); | |
| 221 } while (!timer.HasTimeLimitExpired()); | |
| 222 base::TimeDelta duration = | |
| 223 base::TimeDelta::FromMillisecondsD(timer.MsPerLap()); | |
| 224 if (duration < min_time) | |
| 225 min_time = duration; | |
| 226 } | |
| 227 | |
| 228 if (mode_index == RecordingSource::RECORD_NORMALLY) { | |
| 229 record_results_.bytes_used += memory_used; | |
| 230 record_results_.pixels_recorded += | |
| 231 visible_content_rect.width() * visible_content_rect.height(); | |
| 232 } | |
| 233 record_results_.total_best_time[mode_index] += min_time; | |
| 234 } | |
| 235 } | |
| 236 | |
| 237 RasterizeAndRecordBenchmark::RecordResults::RecordResults() | |
| 238 : pixels_recorded(0), bytes_used(0) { | |
| 239 } | |
| 240 | |
| 241 RasterizeAndRecordBenchmark::RecordResults::~RecordResults() {} | |
| 242 | |
| 243 } // namespace cc | |
| OLD | NEW |