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

Side by Side Diff: chrome/test/data/scroll/scroll.js

Issue 10836202: Refactor/rewrite scroll.js, reporting results as renderingStats objects. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: More changes. Created 8 years, 4 months 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 | « no previous file | chrome/test/functional/perf.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Inject this script on any page to measure framerate as the page is scrolled 5 // Inject this script on any page to measure framerate as the page is scrolled
6 // twice from top to bottom. 6 // from top to bottom.
7 // 7 //
8 // USAGE: 8 // Usage:
9 // 1. To start the scrolling, invoke __scroll_test(). 9 // 1. Define a callback that takes the results array as a parameter.
10 // 2. Wait for __scrolling_complete to be true 10 // 2. To start the test, call new __ScrollTest(callback).
11 // 3. Read __frame_times array. 11 // 3a. When the test is complete, the callback will be called.
12 // 3b. If no callback is specified, the results are sent to the console.
12 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 })();
13 25
14 // Function that sets a callback called when the next frame is rendered. 26 var requestAnimationFrame = (function() {
15 var __set_frame_callback; 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);
16 36
17 // Function that scrolls the page. 37 function GpuBenchmarkingScrollStats() {
18 var __scroll_by; 38 this.initialStats_ = this.getRenderingStats_();
39 }
19 40
20 // Element that can be scrolled. Must provide scrollTop property. 41 GpuBenchmarkingScrollStats.prototype.getResult = function() {
21 var __scrollable_element; 42 var stats = this.getRenderingStats_();
43 for (var key in stats)
44 stats[key] -= this.initialStats_[key];
45 return stats;
46 };
22 47
23 // Amount of scrolling at each frame. 48 GpuBenchmarkingScrollStats.prototype.getRenderingStats_ = function() {
24 var __scroll_delta = 100; 49 var stats = chrome.gpuBenchmarking.renderingStats();
50 stats.totalTimeInSeconds = getTimeMs() / 1000;
51 return stats;
52 };
25 53
26 // Number of scrolls to perform. 54 function RafScrollStats(timestamp) {
27 var __num_scrolls = 2; 55 this.frameTimes_ = [timestamp];
56 this.recording_ = true;
57 requestAnimationFrame(this.processStep_.bind(this));
58 }
28 59
29 // Current scroll position. 60 RafScrollStats.prototype.getResult = function() {
30 var __ypos; 61 this.recording_ = false;
31 62
32 // Time of previous scroll callback execution. 63 // Fill in the result object.
33 var __start_time = 0; 64 var result = {};
65 result.numAnimationFrames = this.frameTimes_.length - 1;
66 result.droppedFrameCount = this.getDroppedFrameCount_(this.frameTimes_);
67 result.totalTimeInSeconds = (this.frameTimes_[this.frameTimes_.length - 1] -
68 this.frameTimes_[0]) / 1000;
69 return result;
70 };
34 71
35 // True when all scrolling has completed. 72 RafScrollStats.prototype.processStep_ = function(timestamp) {
36 var __scrolling_complete = false; 73 if (!this.recording_)
74 return;
37 75
38 // Array of frame times for each scroll in __num_scrolls. 76 this.frameTimes_.push(timestamp);
39 var __frame_times = [[]]; 77 requestAnimationFrame(this.processStep_.bind(this));
78 };
40 79
41 // Set this to true when scrolling in Gmail. 80 RafScrollStats.prototype.getDroppedFrameCount_ = function(frameTimes) {
42 var __is_gmail_test = false; 81 var droppedFrameCount = 0;
82 for (var i = 1; i < frameTimes.length; i++) {
83 var frameTime = frameTimes[i] - frameTimes[i-1];
84 if (frameTime > 1000 / 55)
85 droppedFrameCount++;
86 }
87 return droppedFrameCount;
88 };
43 89
90 // In this class, a "step" is when the page is being scrolled.
91 // i.e. startScroll -> startStep -> scroll -> processStep ->
92 // -> startStep -> scroll -> processStep -> endScroll
93 function ScrollTest(callback, opt_isGmailTest) {
94 var self = this;
44 95
45 // Initializes the platform-independent frame callback scheduler function. 96 this.TOTAL_ITERATIONS_ = 2;
46 function __init_set_frame_callback() { 97 this.SCROLL_DELTA_ = 100;
47 __set_frame_callback = window.requestAnimationFrame ||
48 window.mozRequestAnimationFrame ||
49 window.msRequestAnimationFrame ||
50 window.oRequestAnimationFrame ||
51 window.webkitRequestAnimationFrame;
52 }
53 98
99 this.callback_ = callback;
100 this.isGmailTest_ = opt_isGmailTest;
101 this.iteration_ = 0;
54 102
55 // Initializes the most realistic scrolling method. 103 this.results_ = []
56 function __init_scroll_by() {
57 if (__is_gmail_test) {
58 __scroll_by = function(x, y) {
59 __scrollable_element.scrollByLines(1);
60 };
61 } else if (window.chrome && window.chrome.benchmarking &&
62 window.chrome.benchmarking.smoothScrollBy) {
63 __scroll_by = window.chrome.benchmarking.smoothScrollBy;
64 } else {
65 __scroll_by = window.scrollBy;
66 }
67 }
68 104
69 105 if (this.isGmailTest_) {
70 // Scrolls page down and reschedules itself until it hits the bottom. 106 gmonkey.load('2.0', function(api) {
71 // Collects stats along the way. 107 self.start_(api.getScrollableElement());
72 function __do_scroll(now_time) { 108 });
73 __scroll_by(0, __scroll_delta);
74 __set_frame_callback(function(now_time) {
75 if (__start_time) {
76 if (__scrollable_element.scrollTop > __ypos) {
77 // Scroll in progress, push a frame.
78 __frame_times[__frame_times.length-1].push(now_time - __start_time);
79 } else {
80 // Scroll complete, either scroll again or finish.
81 if (__frame_times.length < __num_scrolls) {
82 __scrollable_element.scrollTop = 0;
83 __frame_times.push([]);
84 } else {
85 console.log('frame_times', '' + __frame_times);
86 __scrolling_complete = true;
87 return;
88 }
89 }
90 }
91 __ypos = __scrollable_element.scrollTop;
92 __start_time = now_time;
93 __do_scroll();
94 });
95 }
96
97
98 function __start_scroll(scrollable_element) {
99 __scrollable_element = scrollable_element;
100 __init_scroll_by();
101 __set_frame_callback(__do_scroll);
102 }
103
104
105 // Performs the scroll test.
106 function __scroll_test() {
107 __init_set_frame_callback();
108 if (__is_gmail_test) {
109 gmonkey.load("2.0", function(api) {
110 __start_scroll(api.getScrollableElement());
111 });
112 } else {
113 if (window.performance.timing.loadEventStart) {
114 __start_scroll(document.body); // Page already loaded.
115 } else { 109 } else {
116 window.addEventListener('load', function() { 110 if (document.readyState == 'complete')
117 __start_scroll(document.body); // Page hasn't loaded yet, schedule. 111 this.start_();
118 }); 112 else
113 window.addEventListener('load', function() { self.start_(); });
119 } 114 }
120 } 115 }
121 } 116
117 ScrollTest.prototype.scroll_ = function(x, y) {
118 if (this.isGmailTest_)
119 this.element_.scrollByLines(1);
120 else
121 window.scrollBy(x, y);
122 };
123
124 ScrollTest.prototype.start_ = function(opt_element) {
125 // Assign this.element_ here instead of constructor, because the constructor
126 // ensures this method will be called after the document is loaded.
127 this.element_ = opt_element || document.body;
128 requestAnimationFrame(this.startScroll_.bind(this));
129 };
130
131 ScrollTest.prototype.startScroll_ = function(timestamp) {
132 this.element_.scrollTop = 0;
133 if (window.chrome && chrome.gpuBenchmarking)
134 this.scrollStats_ = new GpuBenchmarkingScrollStats();
135 else
136 this.scrollStats_ = new RafScrollStats(timestamp);
137 this.startStep_();
138 };
139
140 ScrollTest.prototype.startStep_ = function() {
141 this.scroll_(0, this.SCROLL_DELTA_);
142 requestAnimationFrame(this.processStep_.bind(this));
143 };
144
145 ScrollTest.prototype.endScroll_ = function() {
146 this.results_.push(this.scrollStats_.getResult());
147 this.iteration_++;
148 };
149
150 ScrollTest.prototype.processStep_ = function(timestamp) {
151 // clientHeight is "special" for the body element.
152 if (this.element_ == document.body)
153 var clientHeight = window.innerHeight;
154 else
155 var clientHeight = this.element_.clientHeight;
156 var isScrollComplete =
157 this.element_.scrollTop + clientHeight >= this.element_.scrollHeight;
158
159 if (!isScrollComplete) {
160 this.startStep_();
161 return;
162 }
163
164 this.endScroll_();
165
166 var isTestComplete = this.iteration_ >= this.TOTAL_ITERATIONS_;
167 if (!isTestComplete) {
168 requestAnimationFrame(this.startScroll_.bind(this));
169 return;
170 }
171
172 // Send results.
173 if (this.callback_)
174 this.callback_(this.results_);
175 else
176 console.log(this.results_);
177 };
178
179 window.__ScrollTest = ScrollTest;
180 })();
OLDNEW
« no previous file with comments | « no previous file | chrome/test/functional/perf.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698