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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | chrome/test/functional/perf.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/test/data/scroll/scroll.js
diff --git a/chrome/test/data/scroll/scroll.js b/chrome/test/data/scroll/scroll.js
index 49d2d445b4d0a75016caf5b27528f8f49c464036..3815344f631c765341d4cc5dd8bb9b3c007cceb8 100644
--- a/chrome/test/data/scroll/scroll.js
+++ b/chrome/test/data/scroll/scroll.js
@@ -3,119 +3,178 @@
// found in the LICENSE file.
// Inject this script on any page to measure framerate as the page is scrolled
-// twice from top to bottom.
+// from top to bottom.
//
-// USAGE:
-// 1. To start the scrolling, invoke __scroll_test().
-// 2. Wait for __scrolling_complete to be true
-// 3. Read __frame_times array.
-
-
-// Function that sets a callback called when the next frame is rendered.
-var __set_frame_callback;
-
-// Function that scrolls the page.
-var __scroll_by;
+// Usage:
+// 1. Define a callback that takes the results array as a parameter.
+// 2. To start the test, call new __ScrollTest(callback).
+// 3a. When the test is complete, the callback will be called.
+// 3b. If no callback is specified, the results are sent to the console.
+
+(function() {
+ var getTimeMs = (function() {
+ if (window.performance)
+ return (performance.now ||
+ performance.mozNow ||
+ performance.msNow ||
+ performance.oNow ||
+ performance.webkitNow).bind(window.performance);
+ else
+ return function() { return new Date().getTime(); };
+ })();
+
+ var requestAnimationFrame = (function() {
+ return window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ window.msRequestAnimationFrame ||
+ function(callback) {
+ window.setTimeout(callback, 1000 / 60);
+ };
+ })().bind(window);
+
+ function GpuBenchmarkingScrollStats() {
+ this.initialStats_ = this.getRenderingStats_();
+ }
-// Element that can be scrolled. Must provide scrollTop property.
-var __scrollable_element;
+ GpuBenchmarkingScrollStats.prototype.getResult = function() {
+ var stats = this.getRenderingStats_();
+ for (var key in stats)
+ stats[key] -= this.initialStats_[key];
+ return stats;
+ };
+
+ GpuBenchmarkingScrollStats.prototype.getRenderingStats_ = function() {
+ var stats = chrome.gpuBenchmarking.renderingStats();
+ stats.totalTimeInSeconds = getTimeMs() / 1000;
+ return stats;
+ };
+
+ function RafScrollStats(timestamp) {
+ this.frameTimes_ = [timestamp];
+ this.recording_ = true;
+ requestAnimationFrame(this.processStep_.bind(this));
+ }
-// Amount of scrolling at each frame.
-var __scroll_delta = 100;
+ RafScrollStats.prototype.getResult = function() {
+ this.recording_ = false;
+
+ // Fill in the result object.
+ var result = {};
+ result.numAnimationFrames = this.frameTimes_.length - 1;
+ result.droppedFrameCount = this.getDroppedFrameCount_(this.frameTimes_);
+ result.totalTimeInSeconds = (this.frameTimes_[this.frameTimes_.length - 1] -
+ this.frameTimes_[0]) / 1000;
+ return result;
+ };
+
+ RafScrollStats.prototype.processStep_ = function(timestamp) {
+ if (!this.recording_)
+ return;
+
+ this.frameTimes_.push(timestamp);
+ requestAnimationFrame(this.processStep_.bind(this));
+ };
+
+ RafScrollStats.prototype.getDroppedFrameCount_ = function(frameTimes) {
+ var droppedFrameCount = 0;
+ for (var i = 1; i < frameTimes.length; i++) {
+ var frameTime = frameTimes[i] - frameTimes[i-1];
+ if (frameTime > 1000 / 55)
+ droppedFrameCount++;
+ }
+ return droppedFrameCount;
+ };
-// Number of scrolls to perform.
-var __num_scrolls = 2;
+ // In this class, a "step" is when the page is being scrolled.
+ // i.e. startScroll -> startStep -> scroll -> processStep ->
+ // -> startStep -> scroll -> processStep -> endScroll
+ function ScrollTest(callback, opt_isGmailTest) {
+ var self = this;
-// Current scroll position.
-var __ypos;
+ this.TOTAL_ITERATIONS_ = 2;
+ this.SCROLL_DELTA_ = 100;
-// Time of previous scroll callback execution.
-var __start_time = 0;
+ this.callback_ = callback;
+ this.isGmailTest_ = opt_isGmailTest;
+ this.iteration_ = 0;
-// True when all scrolling has completed.
-var __scrolling_complete = false;
+ this.results_ = []
-// Array of frame times for each scroll in __num_scrolls.
-var __frame_times = [[]];
+ if (this.isGmailTest_) {
+ gmonkey.load('2.0', function(api) {
+ self.start_(api.getScrollableElement());
+ });
+ } else {
+ if (document.readyState == 'complete')
+ this.start_();
+ else
+ window.addEventListener('load', function() { self.start_(); });
+ }
+ }
-// Set this to true when scrolling in Gmail.
-var __is_gmail_test = false;
+ ScrollTest.prototype.scroll_ = function(x, y) {
+ if (this.isGmailTest_)
+ this.element_.scrollByLines(1);
+ else
+ window.scrollBy(x, y);
+ };
+
+ ScrollTest.prototype.start_ = function(opt_element) {
+ // Assign this.element_ here instead of constructor, because the constructor
+ // ensures this method will be called after the document is loaded.
+ this.element_ = opt_element || document.body;
+ requestAnimationFrame(this.startScroll_.bind(this));
+ };
+
+ ScrollTest.prototype.startScroll_ = function(timestamp) {
+ this.element_.scrollTop = 0;
+ if (window.chrome && chrome.gpuBenchmarking)
+ this.scrollStats_ = new GpuBenchmarkingScrollStats();
+ else
+ this.scrollStats_ = new RafScrollStats(timestamp);
+ this.startStep_();
+ };
+
+ ScrollTest.prototype.startStep_ = function() {
+ this.scroll_(0, this.SCROLL_DELTA_);
+ requestAnimationFrame(this.processStep_.bind(this));
+ };
+
+ ScrollTest.prototype.endScroll_ = function() {
+ this.results_.push(this.scrollStats_.getResult());
+ this.iteration_++;
+ };
+
+ ScrollTest.prototype.processStep_ = function(timestamp) {
+ // clientHeight is "special" for the body element.
+ if (this.element_ == document.body)
+ var clientHeight = window.innerHeight;
+ else
+ var clientHeight = this.element_.clientHeight;
+ var isScrollComplete =
+ this.element_.scrollTop + clientHeight >= this.element_.scrollHeight;
+
+ if (!isScrollComplete) {
+ this.startStep_();
+ return;
+ }
+ this.endScroll_();
-// Initializes the platform-independent frame callback scheduler function.
-function __init_set_frame_callback() {
- __set_frame_callback = window.requestAnimationFrame ||
- window.mozRequestAnimationFrame ||
- window.msRequestAnimationFrame ||
- window.oRequestAnimationFrame ||
- window.webkitRequestAnimationFrame;
-}
+ var isTestComplete = this.iteration_ >= this.TOTAL_ITERATIONS_;
+ if (!isTestComplete) {
+ requestAnimationFrame(this.startScroll_.bind(this));
+ return;
+ }
+ // Send results.
+ if (this.callback_)
+ this.callback_(this.results_);
+ else
+ console.log(this.results_);
+ };
-// Initializes the most realistic scrolling method.
-function __init_scroll_by() {
- if (__is_gmail_test) {
- __scroll_by = function(x, y) {
- __scrollable_element.scrollByLines(1);
- };
- } else if (window.chrome && window.chrome.benchmarking &&
- window.chrome.benchmarking.smoothScrollBy) {
- __scroll_by = window.chrome.benchmarking.smoothScrollBy;
- } else {
- __scroll_by = window.scrollBy;
- }
-}
-
-
-// Scrolls page down and reschedules itself until it hits the bottom.
-// Collects stats along the way.
-function __do_scroll(now_time) {
- __scroll_by(0, __scroll_delta);
- __set_frame_callback(function(now_time) {
- if (__start_time) {
- if (__scrollable_element.scrollTop > __ypos) {
- // Scroll in progress, push a frame.
- __frame_times[__frame_times.length-1].push(now_time - __start_time);
- } else {
- // Scroll complete, either scroll again or finish.
- if (__frame_times.length < __num_scrolls) {
- __scrollable_element.scrollTop = 0;
- __frame_times.push([]);
- } else {
- console.log('frame_times', '' + __frame_times);
- __scrolling_complete = true;
- return;
- }
- }
- }
- __ypos = __scrollable_element.scrollTop;
- __start_time = now_time;
- __do_scroll();
- });
-}
-
-
-function __start_scroll(scrollable_element) {
- __scrollable_element = scrollable_element;
- __init_scroll_by();
- __set_frame_callback(__do_scroll);
-}
-
-
-// Performs the scroll test.
-function __scroll_test() {
- __init_set_frame_callback();
- if (__is_gmail_test) {
- gmonkey.load("2.0", function(api) {
- __start_scroll(api.getScrollableElement());
- });
- } else {
- if (window.performance.timing.loadEventStart) {
- __start_scroll(document.body); // Page already loaded.
- } else {
- window.addEventListener('load', function() {
- __start_scroll(document.body); // Page hasn't loaded yet, schedule.
- });
- }
- }
-}
+ window.__ScrollTest = ScrollTest;
+})();
« 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