Bug 1384272 - Add a talos test that tracks the performance of opening about:preferences; r?jmaher draft
authorRob Wood <rwood@mozilla.com>
Fri, 09 Feb 2018 18:46:04 -0500
changeset 757475 7f327df05db3ad9773269e8323904be8d3ea7242
parent 757474 a7a34d672b95353eebcfa97f5434ec86a6791040
push id99764
push userrwood@mozilla.com
push dateTue, 20 Feb 2018 18:37:13 +0000
reviewersjmaher
bugs1384272
milestone60.0a1
Bug 1384272 - Add a talos test that tracks the performance of opening about:preferences; r?jmaher MozReview-Commit-ID: LuHosK5chMN
testing/talos/talos.json
testing/talos/talos/pageloader/chrome/lh_fnbpaint.js
testing/talos/talos/pageloader/chrome/pageloader.js
testing/talos/talos/pageloader/chrome/report.js
testing/talos/talos/run_tests.py
testing/talos/talos/test.py
testing/talos/talos/tests/about-preferences/about_preferences_basic.manifest
--- a/testing/talos/talos.json
+++ b/testing/talos/talos.json
@@ -1,16 +1,16 @@
 {
     "suites": {
         "chromez-e10s": {
-            "tests": ["tresize"]
+            "tests": ["about_preferences_basic", "tresize"]
         },
         "chromez-profiling-e10s": {
             "talos_options": ["--geckoProfile"],
-            "tests": ["tresize"]
+            "tests": [ "about_preferences_basic", "tresize"]
         },
         "dromaeojs-e10s": {
             "tests": ["dromaeo_css", "kraken"]
         },
         "dromaeojs-profiling-e10s": {
             "talos_options": ["--geckoProfile"],
             "tests": ["dromaeo_css", "kraken"]
         },
@@ -145,17 +145,17 @@
                 "--stylo-threads=1",
                 "--mitmproxy",
                 "mitmproxy-recording-google.mp mitmproxy-recording-youtube.mp mitmproxy-recording-amazon.mp mitmproxy-recording-facebook.mp",
                 "--firstNonBlankPaint"
             ]
         },
         "h1-e10s": {
             "tests": ["ts_paint_heavy"]
-            },
+        },
         "h2-e10s": {
             "tests": ["tp6_google_heavy", "tp6_youtube_heavy", "tp6_amazon_heavy", "tp6_facebook_heavy"],
             "mitmproxy_release_bin_osx": "mitmproxy-2.0.2-osx.tar.gz",
             "mitmproxy_release_bin_linux64": "mitmproxy-2.0.2-linux.tar.gz",
             "mitmproxy_recording_set": "mitmproxy-recording-set-win10.zip",
             "talos_options": [
                 "--mitmproxy",
                 "mitmproxy-recording-google.mp mitmproxy-recording-youtube.mp mitmproxy-recording-amazon.mp mitmproxy-recording-facebook.mp",
--- a/testing/talos/talos/pageloader/chrome/lh_fnbpaint.js
+++ b/testing/talos/talos/pageloader/chrome/lh_fnbpaint.js
@@ -1,28 +1,29 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+var gErr = "Abort: firstNonBlankPaint value is not available after loading the page";
 var gRetryCounter = 0;
-var gErr = "Abort: firstNonBlankPaint value is not available after loading the page";
-
 
 function _contentFNBPaintHandler() {
   var x = content.window.performance.timing.timeToNonBlankPaint;
   if (typeof x == "undefined") {
     sendAsyncMessage("PageLoader:Error", {"msg": gErr});
   }
   if (x > 0) {
+    dump("received fnbpaint value\n");
     sendAsyncMessage("PageLoader:LoadEvent", {"time": x,
                                               "name": "fnbpaint"});
+    gRetryCounter = 0;
   } else {
     gRetryCounter += 1;
     if (gRetryCounter <= 10) {
-      dump("fnbpaint is not yet available (0), retry number " + gRetryCounter + "...\n");
+      dump("\nfnbpaint is not yet available (0), retry number " + gRetryCounter + "...\n");
       content.setTimeout(_contentFNBPaintHandler, 100);
     } else {
-      dump("unable to get a value for fnbpaint after " + gRetryCounter + " retries\n");
+      dump("\nunable to get a value for fnbpaint after " + gRetryCounter + " retries\n");
       sendAsyncMessage("PageLoader:Error", {"msg": gErr});
     }
   }
 }
 
 addEventListener("load", contentLoadHandlerCallback(_contentFNBPaintHandler), true); // eslint-disable-line no-undef
--- a/testing/talos/talos/pageloader/chrome/pageloader.js
+++ b/testing/talos/talos/pageloader/chrome/pageloader.js
@@ -26,16 +26,17 @@ var pageCycle;
 var report;
 var timeout = -1;
 var delay = 250;
 var running = false;
 var forceCC = true;
 
 var useMozAfterPaint = false;
 var useFNBPaint = false;
+var isFNBPaintPending = false;
 var useHero = false;
 var gPaintWindow = window;
 var gPaintListener = false;
 var loadNoCache = false;
 var scrollTest = false;
 var profilingInfo = false;
 var baseVsRef = false;
 var useBrowserChrome = false;
@@ -306,16 +307,20 @@ function plLoadPage() {
     mm.removeMessageListener("PageLoader:IdleCallbackSet", ContentListener);
     mm.removeMessageListener("PageLoader:IdleCallbackReceived", ContentListener);
     mm.removeMessageListener("PageLoader:Error", ContentListener);
   };
   failTimeout.register(loadFail, timeout);
   // record which page we are about to open
   TalosParentProfiler.mark("Opening " + pages[pageIndex].url.pathQueryRef);
 
+  if (useFNBPaint) {
+    isFNBPaintPending = true;
+  }
+
   startAndLoadURI(pageName);
 }
 
 function startAndLoadURI(pageName) {
   if (!(plPageFlags() & TEST_DOES_OWN_TIMING)) {
     // Resume the profiler because we're really measuring page load time.
     // If the test is doing its own timing, it'll also need to do its own
     // profiler pausing / resuming.
@@ -387,16 +392,24 @@ var plNextPage = async function() {
   var doNextPage = false;
 
   // ensure we've receive idle-callback before proceeding
   if (isIdleCallbackPending) {
     dumpLine("Waiting for idle-callback");
     await waitForIdleCallback();
   }
 
+  if (useFNBPaint) {
+    // don't move to next page until we've received fnbpaint
+    if (isFNBPaintPending) {
+      dumpLine("Waiting for fnbpaint");
+      await waitForFNBPaint();
+    }
+  }
+
   if (profilingInfo) {
     await TalosParentProfiler.finishTest();
   }
 
   if (pageCycle < numPageCycles) {
     pageCycle++;
     doNextPage = true;
   } else if (pageIndex < pages.length - 1) {
@@ -443,16 +456,29 @@ function plIdleCallbackSet() {
     isIdleCallbackPending = true;
   }
 }
 
 function plIdleCallbackReceived() {
   isIdleCallbackPending = false;
 }
 
+function waitForFNBPaint() {
+  return new Promise(resolve => {
+    function checkForFNBPaint() {
+      if (!isFNBPaintPending) {
+        resolve();
+      } else {
+        setTimeout(checkForFNBPaint, 200);
+      }
+    }
+    checkForFNBPaint();
+  });
+}
+
 function forceContentGC() {
   return new Promise((resolve) => {
     let mm = browserWindow.getBrowser().selectedBrowser.messageManager;
     mm.addMessageListener("Talos:ForceGC:OK", function onTalosContentForceGC(msg) {
       mm.removeMessageListener("Talos:ForceGC:OK", onTalosContentForceGC);
       resolve();
     });
     mm.sendAsyncMessage("Talos:ForceGC");
@@ -613,16 +639,17 @@ function plPainted() {
 }
 
 function _loadHandler(paint_time = 0) {
   failTimeout.clear();
   var end_time = 0;
 
   if (paint_time !== 0) {
     // window.performance.timing.timeToNonBlankPaint is a timestamp
+    // this may have a value for hero element (also a timestamp)
     end_time = paint_time;
   } else {
     end_time = Date.now();
   }
 
   var duration = (end_time - start_time);
   TalosParentProfiler.pause("Bubbling load handler fired.");
 
@@ -640,17 +667,22 @@ function _loadHandler(paint_time = 0) {
 // the core handler
 function plLoadHandlerMessage(message) {
   let paint_time = 0;
   // XXX message.json.name contains the name
   // of the load handler, so in future versions
   // we can record several times per load.
   if (message.json.time !== undefined) {
       paint_time = message.json.time;
+      if (message.json.name == "fnbpaint") {
+        // we've received fnbpaint; no longer pending for this current pageload
+        isFNBPaintPending = false;
+      }
   }
+
   failTimeout.clear();
 
   if ((plPageFlags() & EXECUTE_SCROLL_TEST)) {
     // Let the page settle down after its load event, then execute the scroll test.
     setTimeout(sendScroll, 500);
   } else if ((plPageFlags() & TEST_DOES_OWN_TIMING)) {
     var time;
 
--- a/testing/talos/talos/pageloader/chrome/report.js
+++ b/testing/talos/talos/pageloader/chrome/report.js
@@ -62,16 +62,20 @@ Report.prototype.getReport = function() 
   var prefixLen = findCommonPrefixLength(pages);
 
   report = "__start_tp_report\n";
   report += "_x_x_mozilla_page_load\n";
   report += "_x_x_mozilla_page_load_details\n";
   report += "|i|pagename|runs|\n";
 
   for (var i = 0; i < pages.length; i++) {
+    // don't report any measurements that were reported for about:blank
+    // some tests (like about-preferences) use it as a dummy test page
+    if (pages[i] == "about:blank")
+      continue;
     report += "|" +
       i + ";" +
       pages[i].substr(prefixLen) + ";" +
       this.timeVals[pages[i]].join(";") +
       "\n";
   }
   report += "__end_tp_report\n";
 
--- a/testing/talos/talos/run_tests.py
+++ b/testing/talos/talos/run_tests.py
@@ -70,19 +70,16 @@ def set_tp_preferences(test, browser_con
         _pref_name = "talos.%s" % key
         if value:
             test['preferences'][_pref_name] = value
         else:
             # current test doesn't use this setting, remove it from our prefs
             if _pref_name in test['preferences']:
                 del test['preferences'][_pref_name]
 
-    LOG.info("* RW * preferences are now:")
-    LOG.info(test['preferences'])
-
 
 def setup_webserver(webserver):
     """use mozhttpd to setup a webserver"""
     LOG.info("starting webserver on %r" % webserver)
 
     host, port = webserver.split(':')
     return mozhttpd.MozHttpd(host=host, port=int(port), docroot=here)
 
--- a/testing/talos/talos/test.py
+++ b/testing/talos/talos/test.py
@@ -991,8 +991,27 @@ class rasterflood_gradient(PageloaderTes
     win_counters = w7_counters = linux_counters = mac_counters = None
     filters = filter.ignore_first.prepare(1) + filter.median.prepare()
     """ASAP mode"""
     preferences = {'layout.frame_rate': 0,
                    'docshell.event_starvation_delay_hint': 1,
                    'dom.send_after_paint_to_content': False}
     lower_is_better = False
     unit = 'score'
+
+
+@register_test()
+class about_preferences_basic(PageloaderTest):
+    """
+    Base class for about_preferences test
+    """
+    tpmanifest = '${talos}/tests/about-preferences/about_preferences_basic.manifest'
+    # this test uses 'about:blank' as a dummy page (see manifest) so that the pages
+    # that just change url categories (i.e. about:preferences#search) will get a load event
+    # also any of the url category pages cannot have more than one tppagecycle
+    tpcycles = 25
+    tppagecycles = 1
+    gecko_profile_interval = 1
+    gecko_profile_entries = 2000000
+    filters = filter.ignore_first.prepare(5) + filter.median.prepare()
+    unit = 'ms'
+    lower_is_better = True
+    fnbpaint = True
new file mode 100644
--- /dev/null
+++ b/testing/talos/talos/tests/about-preferences/about_preferences_basic.manifest
@@ -0,0 +1,7 @@
+about:preferences
+about:blank
+about:preferences#search
+about:blank
+about:preferences#privacy
+about:blank
+about:preferences#sync
\ No newline at end of file