Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(432)

Side by Side Diff: tools/perf/perf_tools/scroll.js

Issue 11316017: Refactoring scrolling_benchmark code into scrolling_interaction.py (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/perf/page_sets/top_25.json ('k') | tools/perf/perf_tools/scrolling_benchmark.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 // Inject this script on any page to measure framerate as the page is scrolled
6 // from top to bottom.
7 //
8 // Usage:
9 // 1. Define a callback that takes a RenderingStats object as a parameter.
10 // 2. To start the test, call new __ScrollTest(callback).
11 // 3a. When the test is complete, the callback will be called.
12 // 3b. If no callback is specified, the results is sent to the console.
13
14 (function() {
15 var getTimeMs = (function() {
16 if (window.performance)
17 return (performance.now ||
18 performance.mozNow ||
19 performance.msNow ||
20 performance.oNow ||
21 performance.webkitNow).bind(window.performance);
22 else
23 return function() { return new Date().getTime(); };
24 })();
25
26 var requestAnimationFrame = (function() {
27 return window.requestAnimationFrame ||
28 window.webkitRequestAnimationFrame ||
29 window.mozRequestAnimationFrame ||
30 window.oRequestAnimationFrame ||
31 window.msRequestAnimationFrame ||
32 function(callback) {
33 window.setTimeout(callback, 1000 / 60);
34 };
35 })().bind(window);
36
37 /**
38 * Scrolls a given element down a certain amount to emulate user scrolling.
39 * Uses smooth scrolling capabilities provided by the platform, if available.
40 * @constructor
41 */
42 function SmoothScrollDownGesture(opt_element) {
43 this.element_ = opt_element || document.body;
44 };
45
46 function min(a, b) {
47 if (a > b) {
48 return b;
49 }
50 return a;
51 };
52
53 function getBoundingVisibleRect(el) {
54 var bound = el.getBoundingClientRect();
55 var rect = { top: bound.top,
56 left: bound.left,
57 width: bound.width,
58 height: bound.height };
59 var outsideHeight = (rect.top + rect.height) - window.innerHeight;
60 var outsideWidth = (rect.left + rect.width) - window.innerWidth;
61
62 if (outsideHeight > 0) {
63 rect.height -= outsideHeight;
64 }
65 if (outsideWidth > 0) {
66 rect.width -= outsideWidth;
67 }
68 return rect;
69 };
70
71 SmoothScrollDownGesture.prototype.start = function(callback) {
72 this.callback_ = callback;
73 if (chrome &&
74 chrome.gpuBenchmarking &&
75 chrome.gpuBenchmarking.smoothScrollBy) {
76 var rect = getBoundingVisibleRect(this.element_);
77 chrome.gpuBenchmarking.smoothScrollBy(
78 this.element_.scrollHeight, function() {
79 callback();
80 }, rect.left + rect.width / 2, rect.top + rect.height / 2);
81 return;
82 }
83
84 var SCROLL_DELTA = 100;
85 this.element_.scrollTop += SCROLL_DELTA;
86 requestAnimationFrame(callback);
87 };
88
89 /**
90 * Tracks rendering performance using the gpuBenchmarking.renderingStats API.
91 * @constructor
92 */
93 function GpuBenchmarkingRenderingStats() {
94 }
95
96 GpuBenchmarkingRenderingStats.prototype.start = function() {
97 this.initialStats_ = this.getRenderingStats_();
98 }
99 GpuBenchmarkingRenderingStats.prototype.stop = function() {
100 this.finalStats_ = this.getRenderingStats_();
101 }
102
103 GpuBenchmarkingRenderingStats.prototype.getDeltas = function() {
104 if (!this.initialStats_)
105 throw new Error('Start not called.');
106
107 if (!this.finalStats_)
108 throw new Error('Stop was not called.');
109
110 var stats = this.finalStats_;
111 for (var key in stats)
112 stats[key] -= this.initialStats_[key];
113 return stats;
114 };
115
116 GpuBenchmarkingRenderingStats.prototype.getRenderingStats_ = function() {
117 var stats = chrome.gpuBenchmarking.renderingStats();
118 stats.totalTimeInSeconds = getTimeMs() / 1000;
119 return stats;
120 };
121
122 /**
123 * Tracks rendering performance using requestAnimationFrame.
124 * @constructor
125 */
126 function RafRenderingStats() {
127 this.recording_ = false;
128 this.frameTimes_ = [];
129 }
130
131 RafRenderingStats.prototype.start = function() {
132 if (this.recording_)
133 throw new Error('Already started.');
134 this.recording_ = true;
135 requestAnimationFrame(this.recordFrameTime_.bind(this));
136 }
137
138 RafRenderingStats.prototype.stop = function() {
139 this.recording_ = false;
140 }
141
142 RafRenderingStats.prototype.getDeltas = function() {
143 var results = {};
144 results.numAnimationFrames = this.frameTimes_.length - 1;
145 results.numFramesSentToScreen = results.numAnimationFrames;
146 results.droppedFrameCount = this.getDroppedFrameCount_(this.frameTimes_);
147 results.totalTimeInSeconds = (
148 this.frameTimes_[this.frameTimes_.length - 1] -
149 this.frameTimes_[0]) / 1000;
150 return results;
151 };
152
153 RafRenderingStats.prototype.recordFrameTime_ = function(timestamp) {
154 if (!this.recording_)
155 return;
156
157 this.frameTimes_.push(timestamp);
158 requestAnimationFrame(this.recordFrameTime_.bind(this));
159 };
160
161 RafRenderingStats.prototype.getDroppedFrameCount_ = function(frameTimes) {
162 var droppedFrameCount = 0;
163 for (var i = 1; i < frameTimes.length; i++) {
164 var frameTime = frameTimes[i] - frameTimes[i-1];
165 if (frameTime > 1000 / 55)
166 droppedFrameCount++;
167 }
168 return droppedFrameCount;
169 };
170
171 // This class scrolls a page from the top to the bottom once.
172 //
173 // The page is scrolled down by a set of scroll gestures. These gestures
174 // correspond to a reading gesture on that platform.
175 //
176 // start -> startPass_ -> ...scrolling... -> onGestureComplete_ ->
177 // -> startPass_ -> .. scrolling... -> onGestureComplete_ -> callback_
178 function ScrollTest(opt_callback) {
179 var self = this;
180
181 this.callback_ = opt_callback;
182 }
183
184 ScrollTest.prototype.start = function(opt_element) {
185 // Assign this.element_ here instead of constructor, because the constructor
186 // ensures this method will be called after the document is loaded.
187 this.element_ = opt_element || document.body;
188 // Some pages load more content when you scroll to the bottom. Record
189 // the original element height here and only scroll to that point.
190 this.scrollHeight_ = this.element_.scrollHeight
191 requestAnimationFrame(this.startPass_.bind(this));
192 };
193
194 ScrollTest.prototype.startPass_ = function() {
195 this.element_.scrollTop = 0;
196 if (window.chrome && chrome.gpuBenchmarking &&
197 chrome.gpuBenchmarking.renderingStats)
198 this.renderingStats_ = new GpuBenchmarkingRenderingStats();
199 else
200 this.renderingStats_ = new RafRenderingStats();
201 this.renderingStats_.start();
202
203 this.gesture_ = new SmoothScrollDownGesture(this.element_);
204 this.gesture_.start(this.onGestureComplete_.bind(this));
205 };
206
207 ScrollTest.prototype.onGestureComplete_ = function(timestamp) {
208 // clientHeight is "special" for the body element.
209 var clientHeight;
210 if (this.element_ == document.body)
211 clientHeight = window.innerHeight;
212 else
213 clientHeight = this.element_.clientHeight;
214
215 // If the scrollHeight went down, only scroll to the new scrollHeight.
216 this.scrollHeight_ = Math.min(this.scrollHeight_,
217 this.element_.scrollHeight);
218
219 // -1 to allow for rounding errors on scaled viewports (like mobile).
220 var isPassComplete =
221 this.element_.scrollTop + clientHeight >= this.scrollHeight_ - 1;
222
223 if (!isPassComplete) {
224 this.gesture_.start(this.onGestureComplete_.bind(this));
225 return;
226 }
227
228 this.endPass_();
229
230 // We're done.
231 if (this.callback_)
232 this.callback_(this.renderingStats_.getDeltas());
233 else
234 console.log(this.renderingStats_.getDeltas());
235 };
236
237 ScrollTest.prototype.endPass_ = function() {
238 this.renderingStats_.stop();
239 };
240
241 window.__ScrollTest = ScrollTest;
242 window.__ScrollTest_GetBoundingVisibleRect = getBoundingVisibleRect;
243 })();
OLDNEW
« no previous file with comments | « tools/perf/page_sets/top_25.json ('k') | tools/perf/perf_tools/scrolling_benchmark.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698