Bug 1189901: part 5: add CSSOM scroll test - uses APZ when available. r=kats
authorAvi Halachmi <avihpit@yahoo.com>
Thu, 29 Sep 2016 21:00:22 +0300
changeset 315865 1a294b6d4847c3e9ccd427fc05e4a707c06ec93e
parent 315864 2b747bcd819e4379a7f4036d271a398b9236802e
child 315866 f1c1f217e1947f8948cf9963e5a97004011da16c
push id20634
push usercbook@mozilla.com
push dateFri, 30 Sep 2016 10:10:13 +0000
treeherderfx-team@afe79b010d13 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1189901
milestone52.0a1
Bug 1189901: part 5: add CSSOM scroll test - uses APZ when available. r=kats
testing/talos/talos/pageloader/chrome/tscroll.js
testing/talos/talos/talos-powers/components/TalosPowersService.js
testing/talos/talos/test.py
--- a/testing/talos/talos/pageloader/chrome/tscroll.js
+++ b/testing/talos/talos/pageloader/chrome/tscroll.js
@@ -21,16 +21,47 @@ function testScroll(target, stepSize, op
   // the path if non-empty (e.g. with tscrollx), or the last dir otherwise (e.g.
   // 'mydir' for 'http://my.domain/dir1/mydir/').
   var href = win.location.href;
   var testBaseName = href.split("/tp5n/")[1]
                   || href.split("/").pop()
                   || href.split("/").splice(-2, 1)[0]
                   || "REALLY_WEIRD_URI";
 
+  // Verbatim copy from talos-powers/content/TalosPowersContent.js
+  // If the origin changes, this copy should be updated.
+  TalosPowersParent = {
+    replyId: 1,
+
+    // dispatch an event to the framescript and register the result/callback event
+    exec: function(commandName, arg, callback, opt_custom_window) {
+      let win = opt_custom_window || window;
+      let replyEvent = "TalosPowers:ParentExec:ReplyEvent:" + this.replyId++;
+      if (callback) {
+        win.addEventListener(replyEvent, function rvhandler(e) {
+          win.removeEventListener(replyEvent, rvhandler);
+          callback(e.detail);
+        });
+      }
+      win.dispatchEvent(
+        new win.CustomEvent("TalosPowers:ParentExec:QueryEvent", {
+          bubbles: true,
+          detail: {
+            command: {
+              name: commandName,
+              data: arg,
+            },
+            listeningTo: replyEvent,
+          }
+        })
+      );
+    },
+  };
+  // End of code from talos-powers
+
   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.
    *
@@ -96,16 +127,22 @@ function testScroll(target, stepSize, op
                               : function() { return target.scrollTop; };
 
   var gotoTop =      isWindow ? function() { target.scroll(0, 0);  ensureScroll(); }
                               : function() { target.scrollTop = 0; ensureScroll(); };
 
   var doScrollTick = isWindow ? function() { target.scrollBy(0, stepSize); ensureScroll(); }
                               : function() { target.scrollTop += stepSize; ensureScroll(); };
 
+  var setSmooth =    isWindow ? function() { target.document.scrollingElement.style.scrollBehavior = "smooth"; }
+                              : function() { target.style.scrollBehavior = "smooth"; };
+
+  var gotoBottom =   isWindow ? function() { target.scrollTo(0, target.scrollMaxY); }
+                              : function() { target.scrollTop = target.scrollHeight; };
+
   function ensureScroll() { // Ensure scroll by reading computed values. screenY is for X11.
     if (!this.dummyEnsureScroll) {
       this.dummyEnsureScroll = 1;
     }
     this.dummyEnsureScroll += win.screenY + getPos();
   }
 
   // For reference, rAF should fire on vsync, but Gecko currently doesn't use vsync.
@@ -162,21 +199,68 @@ function testScroll(target, stepSize, op
 
       if (typeof(Profiler) !== "undefined") {
         Profiler.resume();
       }
       rAF(tick);
     });
   }
 
+  function P_testAPZScroll() {
+    var APZ_MEASURE_MS = 1000;
+
+    function startFrameTimeRecording(cb) {
+      TalosPowersParent.exec("startFrameTimeRecording", null, cb, win);
+    }
+
+    function stopFrameTimeRecording(handle, cb) {
+      TalosPowersParent.exec("stopFrameTimeRecording", handle, cb, win);
+    }
+
+    return new Promise(function(resolve, reject) {
+      setSmooth();
+      var startts = Date.now();
+
+      var handle = -1;
+      startFrameTimeRecording(function(rv) {
+        handle = rv;
+      });
+
+      // Get the measurements after APZ_MEASURE_MS of scrolling
+      setTimeout(function() {
+        var endts = Date.now();
+
+        stopFrameTimeRecording(handle, function(intervals) {
+          function average(arr) {
+              var sum = 0;
+              for(var i = 0; i < arr.length; i++)
+                sum += arr[i];
+              return arr.length ? sum / arr.length : 0;
+          }
+
+          // remove two frames on each side of the recording to get a cleaner result
+          result.values.push(average(intervals.slice(2, intervals.length - 2)));
+          result.names.push("CSSOM." + testBaseName);
+
+          resolve();
+        });
+      }, APZ_MEASURE_MS);
+
+      gotoBottom(); // trigger the APZ scroll
+    });
+  }
+
   P_setupReportFn()
   .then(FP_wait(260))
   .then(gotoTop)
   .then(P_rAF)
   .then(P_syncScrollTest)
+  .then(gotoTop)
+  .then(FP_wait(260))
+  .then(P_testAPZScroll)
   .then(function() {
     report(result.values.join(","), 0, result.names.join(","));
   });
 }
 
 // This code below here is unique to tscroll.js inside of pageloader
 try {
   function handleMessageFromChrome(message) {
--- a/testing/talos/talos/talos-powers/components/TalosPowersService.js
+++ b/testing/talos/talos/talos-powers/components/TalosPowersService.js
@@ -273,19 +273,34 @@ TalosPowersService.prototype = {
   // Sample service:
   /*
     // arg: anything. return: sample reply
     sampleParentService: function(arg, callback, win) {
       win.setTimeout(function() {
         callback("sample reply for: " + arg);
       }, 500);
     },
-
   */
   ParentExecServices: {
+
+    // arg: ignored. return: handle (number) for use with stopFrameTimeRecording
+    startFrameTimeRecording: function(arg, callback, win) {
+      var rv = win.QueryInterface(Ci.nsIInterfaceRequestor)
+                  .getInterface(Ci.nsIDOMWindowUtils)
+                  .startFrameTimeRecording();
+      callback(rv);
+    },
+
+    // arg: handle from startFrameTimeRecording. return: array with composition intervals
+    stopFrameTimeRecording: function(arg, callback, win) {
+      var rv = win.QueryInterface(Ci.nsIInterfaceRequestor)
+                  .getInterface(Ci.nsIDOMWindowUtils)
+                  .stopFrameTimeRecording(arg);
+      callback(rv);
+    },
   },
 
   RecieveParentExecCommand(msg) {
     function sendResult(result) {
       let mm = msg.target.messageManager;
       mm.sendAsyncMessage("TalosPowers:ParentExec:ReplyMsg", {
         id: msg.data.id,
         result: result
--- a/testing/talos/talos/test.py
+++ b/testing/talos/talos/test.py
@@ -493,17 +493,19 @@ class tp5o_scroll(PageloaderTest):
     sps_profile_interval = 2
     sps_profile_entries = 2000000
 
     tpscrolltest = True
     """ASAP mode"""
     tpmozafterpaint = False
     preferences = {'layout.frame_rate': 0,
                    'docshell.event_starvation_delay_hint': 1,
-                   'dom.send_after_paint_to_content': False}
+                   'dom.send_after_paint_to_content': False,
+                   'layout.css.scroll-behavior.spring-constant': "'10'",
+                   'toolkit.framesRecording.bufferSize': 10000}
     filters = filter.ignore_first.prepare(1) + filter.median.prepare()
     unit = '1/FPS'
 
 
 @register_test()
 class v8_7(PageloaderTest):
     """
     This is the V8 (version 7) javascript benchmark taken verbatim and
@@ -683,17 +685,19 @@ class tscrollx(PageloaderTest):
     tpcycles = 1
     tppagecycles = 25
     tpmozafterpaint = False
     sps_profile_interval = 1
     sps_profile_entries = 1000000
     """ ASAP mode """
     preferences = {'layout.frame_rate': 0,
                    'docshell.event_starvation_delay_hint': 1,
-                   'dom.send_after_paint_to_content': False}
+                   'dom.send_after_paint_to_content': False,
+                   'layout.css.scroll-behavior.spring-constant': "'10'",
+                   'toolkit.framesRecording.bufferSize': 10000}
     filters = filter.ignore_first.prepare(5) + filter.median.prepare()
     unit = 'ms'
 
 
 @register_test()
 class a11yr(PageloaderTest):
     """
     This test ensures basic a11y tables and permutations do not cause