Bug 1189901: part 2: scroll-tests: serialize asyncs with Promises. r=mconley
☠☠ backed out by 9dfac0d146bc ☠ ☠
authorAvi Halachmi <avihpit@yahoo.com>
Tue, 27 Sep 2016 16:43:37 +0300
changeset 315359 866c0244a7c1a80bc82d1163217241ea079ca552
parent 315358 081c6b4986a9c7c1c8994e095a0a834ba3a3149b
child 315360 610b70634239c1dc46d4f5052666a09ce712601d
push id82138
push userahalachmi@mozilla.com
push dateTue, 27 Sep 2016 13:43:58 +0000
treeherdermozilla-inbound@14660f4f2b23 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmconley
bugs1189901
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1189901: part 2: scroll-tests: serialize asyncs with Promises. r=mconley
testing/talos/talos/pageloader/chrome/tscroll.js
--- a/testing/talos/talos/pageloader/chrome/tscroll.js
+++ b/testing/talos/talos/pageloader/chrome/tscroll.js
@@ -7,20 +7,73 @@ function testScroll(target, stepSize, op
   var win;
   if (target == "content") {
     target = content.wrappedJSObject;
     win = content;
   } else {
     win = window;
   }
 
+  var report;
+  /**
+   * Sets up the value of 'report' as a function for reporting the test result[s].
+   * Chooses between the "usual" tpRecordTime which the pageloader addon injects
+   * to pages, or a custom function in case we're a framescript which pageloader
+   * added to the tested page, or a debug tpRecordTime from talos-debug.js if
+   * running in a plain browser.
+   *
+   * @returns Promise
+   */
+  function P_setupReportFn() {
+    return new Promise(function(resolve) {
+      report = opt_reportFunc || win.tpRecordTime;
+      if (report == 'PageLoader:RecordTime') {
+        report = function(duration, start, name) {
+          var msg = { time: duration, startTime: start, testName: name };
+          sendAsyncMessage('PageLoader:RecordTime', msg);
+        }
+        resolve();
+        return;
+      }
+
+      // Not part of the test and does nothing if we're within talos.
+      // Provides an alternative tpRecordTime (with some stats display) if running in a browser.
+      if (!report && document.head) {
+        var imported = document.createElement('script');
+        imported.addEventListener("load", function() {
+          report = tpRecordTime;
+          resolve();
+        });
+
+        imported.src = '../../scripts/talos-debug.js?dummy=' + Date.now(); // For some browsers to re-read
+        document.head.appendChild(imported);
+        return;
+      }
+
+      resolve();
+    });
+  }
+
+  function FP_wait(ms) {
+    return function() {
+      return new Promise(function(resolve) {
+        setTimeout(resolve, ms);
+      });
+    };
+  }
+
   function rAF(fn) {
     return content.requestAnimationFrame(fn);
   }
 
+  function P_rAF() {
+    return new Promise(function(resolve) {
+      rAF(resolve);
+    });
+  }
 
   function myNow() {
     return (win.performance && win.performance.now) ?
             win.performance.now() :
             Date.now();
   };
 
   var isWindow = target.self === target;
@@ -39,89 +92,78 @@ function testScroll(target, stepSize, op
       this.dummyEnsureScroll = 1;
     }
     this.dummyEnsureScroll += win.screenY + getPos();
   }
 
   // For reference, rAF should fire on vsync, but Gecko currently doesn't use vsync.
   // Instead, it uses 1000/layout.frame_rate
   // (with 60 as default value when layout.frame_rate == -1).
-  function startTest()
-  {
-    // We should be at the top of the page now.
-    var start = myNow();
-    var lastScrollPos = getPos();
-    var lastScrollTime = start;
-    var durations = [];
-    var report = opt_reportFunc || tpRecordTime;
-    if (report == 'PageLoader:RecordTime') {
-      report = function(duration) {
-        var msg = { time: duration, startTime: '', testName: '' };
-        sendAsyncMessage('PageLoader:RecordTime', msg);
-      }
-    }
+  function P_syncScrollTest() {
+    return new Promise(function(resolve) {
+      // We should be at the top of the page now.
+      var start = myNow();
+      var lastScrollPos = getPos();
+      var lastScrollTime = start;
+      var durations = [];
+
+      function tick() {
+        var now = myNow();
+        var duration = now - lastScrollTime;
+        lastScrollTime = now;
+
+        durations.push(duration);
+        doScrollTick();
 
-    function tick() {
-      var now = myNow();
-      var duration = now - lastScrollTime;
-      lastScrollTime = now;
+        /* stop scrolling if we can't scroll more, or if we've reached requested number of steps */
+        if ((getPos() == lastScrollPos) || (opt_numSteps && (durations.length >= (opt_numSteps + 2)))) {
+          if (typeof(Profiler) !== "undefined") {
+            Profiler.pause();
+          }
+
+          // Note: The first (1-5) intervals WILL be longer than the rest.
+          // First interval might include initial rendering and be extra slow.
+          // Also requestAnimationFrame needs to sync (optimally in 1 frame) after long frames.
+          // Suggested: Ignore the first 5 intervals.
 
-      durations.push(duration);
-      doScrollTick();
+          durations.pop(); // Last step was 0.
+          durations.pop(); // and the prev one was shorter and with end-of-page logic, ignore both.
+
+          if (win.talosDebug)
+            win.talosDebug.displayData = true; // In a browser: also display all data points.
 
-      /* stop scrolling if we can't scroll more, or if we've reached requested number of steps */
-      if ((getPos() == lastScrollPos) || (opt_numSteps && (durations.length >= (opt_numSteps + 2)))) {
-        if (typeof(Profiler) !== "undefined") {
-          Profiler.pause();
+          // For analysis (otherwise, it's too many data points for talos):
+          var sum = 0;
+          for (var i = 0; i < durations.length; i++)
+            sum += Number(durations[i]);
+
+          // Report average interval or (failsafe) 0 if no intervls were recorded
+          resolve(durations.length ? sum / durations.length : 0);
+          return;
         }
 
-        // Note: The first (1-5) intervals WILL be longer than the rest.
-        // First interval might include initial rendering and be extra slow.
-        // Also requestAnimationFrame needs to sync (optimally in 1 frame) after long frames.
-        // Suggested: Ignore the first 5 intervals.
-
-        durations.pop(); // Last step was 0.
-        durations.pop(); // and the prev one was shorter and with end-of-page logic, ignore both.
-
-        if (win.talosDebug)
-          win.talosDebug.displayData = true; // In a browser: also display all data points.
-
-        // For analysis (otherwise, it's too many data points for talos):
-        var sum = 0;
-        for (var i = 0; i < durations.length; i++)
-          sum += Number(durations[i]);
-
-        // Report average interval or (failsafe) 0 if no intervls were recorded
-        report(durations.length ? sum / durations.length : 0);
-        return;
+        lastScrollPos = getPos();
+        rAF(tick);
       }
 
-      lastScrollPos = getPos();
+      if (typeof(Profiler) !== "undefined") {
+        Profiler.resume();
+      }
       rAF(tick);
-    }
-
-    if (typeof(Profiler) !== "undefined") {
-      Profiler.resume();
-    }
-    rAF(tick);
+    });
   }
 
-  // Not part of the test and does nothing if we're within talos,
-  // But provides an alternative tpRecordTime (with some stats display) if running in a browser
-  // If a callback is provided, then we don't need this debug reporting.
-  if(!opt_reportFunc && document.head) {
-    var imported = document.createElement('script');
-    imported.src = '../../scripts/talos-debug.js?dummy=' + Date.now(); // For some browsers to re-read
-    document.head.appendChild(imported);
-  }
-
-  setTimeout(function(){
-    gotoTop();
-    rAF(startTest);
-  }, 260);
+  P_setupReportFn()
+  .then(FP_wait(260))
+  .then(gotoTop)
+  .then(P_rAF)
+  .then(P_syncScrollTest)
+  .then(function(result) { // function since 'report' might not be ready when invoking 'then'
+    report(result);
+  });
 }
 
 // This code below here is unique to tscroll.js inside of pageloader
 try {
   function handleMessageFromChrome(message) {
     var payload = message.data.details;
     testScroll(payload.target, payload.stepSize, 'PageLoader:RecordTime', payload.opt_numSteps);
   }