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 draft
authorMike Conley <mconley@mozilla.com>
Thu, 13 Jul 2017 11:05:46 -0400
changeset 610839 3cf6ddff9edc24388a0b92e1abcdd5c7418e1031
parent 610838 22821f1c5655c47747892e4daf277c9ccbfa8902
child 610840 e2676cb3ce735b81f3bd0157cd22cf1012b2aa4e
push id69002
push usermconley@mozilla.com
push dateTue, 18 Jul 2017 19:11:35 +0000
reviewersrwood
bugs1374333, 1380785
milestone56.0a1
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>