Bug 1374333 - Ensure we get profiles for all content processes for tps by waiting until the profiles are gathered before closing the tabs. r=rwood
authorMike Conley <mconley@mozilla.com>
Thu, 13 Jul 2017 11:05:46 -0400
changeset 418186 835edc46b6c5bb2fe212a4ed9e466528daaac422
parent 418185 1b9006ceb4491652f89f8ba1097a13c400037f8f
child 418187 ba3597e894b0eefb4a58d5b64928b65ad3b94d86
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrwood
bugs1374333, 1380785
milestone56.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 1374333 - Ensure we get profiles for all content processes for tps by waiting until the profiles are gathered before closing the tabs. r=rwood There seems to be a race where the ProfilerParent::SendGatherProfile Promise can fail if the shutdown message has been sent by ContentParent. This means that exit profiles are on their way, but the gatherer is going to hear about the rejected Promises first and decrement the mPendingProfiles counter (with empty profiles) before the exit profiles can arrive. This is a workaround. Bug 1380785 has been filed for the ProfilerParent race. MozReview-Commit-ID: LacBwp4ttiP
testing/talos/talos/talos-powers/components/TalosPowersService.js
testing/talos/talos/talos-powers/content/TalosParentProfiler.js
testing/talos/talos/test.py
testing/talos/talos/tests/tabswitch/bootstrap.js
testing/talos/talos/tests/tabswitch/content/test.html
--- a/testing/talos/talos/talos-powers/components/TalosPowersService.js
+++ b/testing/talos/talos/talos-powers/components/TalosPowersService.js
@@ -117,16 +117,17 @@ TalosPowersService.prototype = {
         let encoder = new TextEncoder();
         let array = encoder.encode(JSON.stringify(profile));
 
         OS.File.writeAtomic(profileFile, array, {
           tmpPath: profileFile + ".tmp",
         }).then(() => {
           Services.profiler.StopProfiler();
           resolve();
+          Services.obs.notifyObservers(null, "talos-profile-gathered");
         });
       }, (error) => {
         Cu.reportError("Failed to gather profile: " + error);
         // FIXME: We should probably send a message down to the
         // child which causes it to reject the waiting Promise.
         reject();
       });
     });
--- a/testing/talos/talos/talos-powers/content/TalosParentProfiler.js
+++ b/testing/talos/talos/talos-powers/content/TalosParentProfiler.js
@@ -192,10 +192,23 @@ var TalosParentProfiler;
         // If marker is omitted, just use the test name
         if (!marker) {
           marker = currentTest;
         }
 
         TalosPowers.profilerMarker(marker);
       }
     },
+
+    afterProfileGathered() {
+      if (!initted) {
+        return Promise.resolve();
+      }
+
+      return new Promise(resolve => {
+        Services.obs.addObserver(function onGathered() {
+          Services.obs.removeObserver(onGathered, "talos-profile-gathered");
+          resolve();
+        }, "talos-profile-gathered");
+      });
+    }
   };
 })();
--- a/testing/talos/talos/test.py
+++ b/testing/talos/talos/test.py
@@ -301,17 +301,17 @@ class tabpaint(PageloaderTest):
 @register_test()
 class tps(PageloaderTest):
     """
     Tests the amount of time it takes to switch between tabs
     """
     extensions = '${talos}/tests/tabswitch/tabswitch-signed.xpi'
     tpmanifest = '${talos}/tests/tabswitch/tps.manifest'
     tppagecycles = 5
-    gecko_profile_entries = 1000000
+    gecko_profile_entries = 5000000
     tploadnocache = True
     preferences = {
         'addon.test.tabswitch.urlfile': os.path.join('${talos}',
                                                      'tests',
                                                      'tp5o.html'),
         'addon.test.tabswitch.webserver': '${webserver}',
         'addon.test.tabswitch.maxurls': -1,
     }
--- a/testing/talos/talos/tests/tabswitch/bootstrap.js
+++ b/testing/talos/talos/tests/tabswitch/bootstrap.js
@@ -201,41 +201,38 @@ function switchToTab(tab) {
 
   if (browser.isRemoteBrowser) {
     return Task.spawn(function*() {
       // The multi-process case requires that we load our utility script
       // inside the content, since it's the content that will hear a MozAfterPaint
       // once the content is presented to the user.
       yield loadTPSContentScript(browser);
       let start = Math.floor(window.performance.timing.navigationStart + window.performance.now());
-      TalosParentProfiler.resume("start (" + start + "): " + browser.currentURI.spec);
 
       // We need to wait for the TabSwitchDone event to make sure
       // that the async tab switcher has shut itself down.
       let switchDone = waitForTabSwitchDone(browser);
       // Set up our promise that will wait for the content to be
       // presented.
       let finishPromise = waitForContentPresented(browser);
       // Finally, do the tab switch.
       gBrowser.selectedTab = tab;
 
       yield switchDone;
       let finish = yield finishPromise;
-      TalosParentProfiler.mark("end (" + finish + ")");
       return finish - start;
     });
   }
 
   return Task.spawn(function*() {
     let win = browser.ownerGlobal;
     let winUtils = win.QueryInterface(Ci.nsIInterfaceRequestor)
                       .getInterface(Ci.nsIDOMWindowUtils);
 
     let start = Math.floor(window.performance.timing.navigationStart + window.performance.now());
-    TalosParentProfiler.resume("start (" + start + "): " + browser.currentURI.spec);
 
     // There is no async tab switcher for the single-process case,
     // but tabbrowser.xml will still fire this once the updateCurrentBrowser
     // method runs.
     let switchDone = waitForTabSwitchDone(browser);
     // Do our tab switch
     gBrowser.selectedTab = tab;
     // Because the above tab switch is synchronous, we know that the
@@ -245,17 +242,16 @@ function switchToTab(tab) {
 
     yield switchDone;
 
     // Now we'll wait for content to be presented. Because
     // this is the single-process case, we pass the last transaction
     // id that we got so that we don't get any intermediate MozAfterPaint's
     // that might fire before web content is shown.
     let finish = yield waitForContentPresented(browser, lastTransactionId);
-    TalosParentProfiler.mark("end (" + finish + ")");
     return finish - start;
   });
 }
 
 /**
  * For some <xul:browser>, find the <xul:tabbrowser> associated with it,
  * and wait until that tabbrowser has finished a tab switch. This function
  * assumes a tab switch has started, or is about to start.
@@ -415,17 +411,19 @@ function test(window) {
       // content processes, so we cannot do this at the manifest level.
       yield switchToTab(tab);
       yield switchToTab(initialTab);
     }
 
     for (let tab of tabs) {
       gBrowser.moveTabTo(tab, 1);
       yield forceGC(win, tab.linkedBrowser);
+      TalosParentProfiler.resume("start: " + tab.linkedBrowser.currentURI.spec);
       let time = yield switchToTab(tab);
+      TalosParentProfiler.pause("finish: " + tab.linkedBrowser.currentURI.spec);
       dump(`${tab.linkedBrowser.currentURI.spec}: ${time}ms\n`);
       times.push(time);
       yield switchToTab(initialTab);
     }
 
     let output = "<!DOCTYPE html>" +
                  '<html lang="en">' +
                  "<head><title>Tab Switch Results</title></head>" +
@@ -438,29 +436,27 @@ function test(window) {
     }
     output += "</table></body></html>";
     dump("total tab switch time:" + time + "\n");
 
     let resultsTab = win.gBrowser.loadOneTab(
       "data:text/html;charset=utf-8," + encodeURIComponent(output), {
       triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
     });
-    let pref = Services.prefs.getBoolPref("browser.tabs.warnOnCloseOtherTabs");
-    if (pref)
-      Services.prefs.setBoolPref("browser.tabs.warnOnCloseOtherTabs", false);
-    win.gBrowser.removeAllTabsBut(resultsTab);
-    if (pref)
-      Services.prefs.setBoolPref("browser.tabs.warnOnCloseOtherTabs", pref);
+
+    win.gBrowser.selectedTab = resultsTab;
 
     remotePage.sendAsyncMessage("tabswitch-test-results", {
       times,
       urls: testURLs,
     });
 
-    win.close();
+    TalosParentProfiler.afterProfileGathered().then(() => {
+      win.close();
+    });
   });
 }
 
 function unloadFromWindow(window) {
   if (!window)
     return;
   let toolsMenu = window.document.getElementById("menu_ToolsPopup");
   if (!toolsMenu)
--- a/testing/talos/talos/tests/tabswitch/content/test.html
+++ b/testing/talos/talos/tests/tabswitch/content/test.html
@@ -2,16 +2,17 @@
   <head>
     <script>
       function do_test(override) {
         if (override || document.location.hash.indexOf("#auto") == 0) {
           sendAsyncMessage("tabswitch-do-test");
           addMessageListener("tabswitch-test-results", function onMessage(msg) {
             let data = msg.data;
             content.tpRecordTime(data.times.join(","), 0, data.urls.join(","));
+            sendAsyncMessage("tabswitch-test-results-reported");
           });
         }
       }
     </script>
   </head>
   <body onload="do_test(false)">
     Hello Talos!
   </body>