Bug 1156264 - Activate/deactivate jank and CPOW monitoring separately (high-level). r=mossop
authorDavid Rajchenbach-Teller <dteller@mozilla.com>
Thu, 04 Jun 2015 13:12:27 +0200
changeset 280768 01cc604a77f135e9eb6268f9b8cf0ee1bf131293
parent 280767 494ad53ffb83b8a5038963c988ef04118c28dd03
child 280769 7f3efd2fe68e3e4d9c956aaf159f9c5e36b142a1
push id897
push userjlund@mozilla.com
push dateMon, 14 Sep 2015 18:56:12 +0000
treeherdermozilla-release@9411e2d2b214 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmossop
bugs1156264
milestone41.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 1156264 - Activate/deactivate jank and CPOW monitoring separately (high-level). r=mossop
toolkit/components/perfmonitoring/PerformanceStats.jsm
toolkit/components/perfmonitoring/nsIPerformanceStats.idl
toolkit/components/perfmonitoring/nsPerformanceStats.cpp
toolkit/components/perfmonitoring/tests/browser/browser_compartments.js
toolkit/components/perfmonitoring/tests/xpcshell/test_compartments.js
--- a/toolkit/components/perfmonitoring/PerformanceStats.jsm
+++ b/toolkit/components/perfmonitoring/PerformanceStats.jsm
@@ -169,18 +169,22 @@ let Probes = {
    * kernel for this performance group, in µs.
    * @field {Array<number>} durations An array containing at each position `i`
    * the number of times execution of this component has lasted at least `2^i`
    * milliseconds.
    * @field {number} longestDuration The index of the highest non-0 value in
    * `durations`.
    */
   jank: new Probe("jank", {
-    set isActive(x) { /* always active in the current implementation */ },
-    get isActive() { return true; },
+    set isActive(x) {
+      performanceStatsService.isMonitoringJank = x;
+    },
+    get isActive() {
+      return performanceStatsService.isMonitoringJank;
+    },
     extract: function(xpcom) {
       let durations = xpcom.getDurations();
       return {
         totalUserTime: xpcom.totalUserTime,
         totalSystemTime: xpcom.totalSystemTime,
         durations: durations,
         longestDuration: lastNonZero(durations)
       }
@@ -220,18 +224,22 @@ let Probes = {
    * A probe measuring CPOW activity.
    *
    * Data provided by this probe uses the following format:
    *
    * @field {number} totalCPOWTime The amount of wallclock time
    * spent executing blocking cross-process calls, in µs.
    */
   cpow: new Probe("cpow", {
-    set isActive(x) { /* always active in the current implementation */ },
-    get isActive() { return true; },
+    set isActive(x) {
+      performanceStatsService.isMonitoringCPOW = x;
+    },
+    get isActive() {
+      return performanceStatsService.isMonitoringCPOW;
+    },
     extract: function(xpcom) {
       return {
         totalCPOWTime: xpcom.totalCPOWTime
       };
     },
     isEqual: function(a, b) {
       return a.totalCPOWTime == b.totalCPOWTime;
     },
@@ -523,12 +531,8 @@ function Snapshot({xpcom, probes}) {
   this.componentsData = [];
   let enumeration = xpcom.getComponentsData().enumerate();
   while (enumeration.hasMoreElements()) {
     let stat = enumeration.getNext().QueryInterface(Ci.nsIPerformanceStats);
     this.componentsData.push(new PerformanceData({xpcom: stat, probes}));
   }
   this.processData = new PerformanceData({xpcom: xpcom.getProcessData(), probes});
 }
-
-
-// In the current implementation, all probes are always active.
-performanceStatsService.isStopwatchActive = true;
--- a/toolkit/components/perfmonitoring/nsIPerformanceStats.idl
+++ b/toolkit/components/perfmonitoring/nsIPerformanceStats.idl
@@ -99,22 +99,27 @@ interface nsIPerformanceSnapshot: nsISup
    * This contains the total amount of time spent executing JS code,
    * the total amount of time spent waiting for system calls while
    * executing JS code, the total amount of time performing blocking
    * inter-process calls, etc.
    */
   nsIPerformanceStats getProcessData();
 };
 
-[scriptable, builtinclass, uuid(3a20d41d-9f24-44b3-bd65-0910f92d33d2)]
+[scriptable, builtinclass, uuid(0469e6af-95c3-4961-a385-4bc009128939)]
 interface nsIPerformanceStatsService : nsISupports {
   /**
-   * `true` if we should monitor performance, `false` otherwise.
+   * `true` if we should monitor CPOW, `false` otherwise.
    */
-  [implicit_jscontext] attribute bool isStopwatchActive;
+  [implicit_jscontext] attribute bool isMonitoringCPOW;
+
+  /**
+   * `true` if we should monitor jank, `false` otherwise.
+   */
+  [implicit_jscontext] attribute bool isMonitoringJank;
 
   /**
    * Capture a snapshot of the performance data.
    */
   [implicit_jscontext] nsIPerformanceSnapshot getSnapshot();
 };
 
 %{C++
--- a/toolkit/components/perfmonitoring/nsPerformanceStats.cpp
+++ b/toolkit/components/perfmonitoring/nsPerformanceStats.cpp
@@ -328,27 +328,41 @@ NS_IMPL_ISUPPORTS(nsPerformanceStatsServ
 nsPerformanceStatsService::nsPerformanceStatsService()
 {
 }
 
 nsPerformanceStatsService::~nsPerformanceStatsService()
 {
 }
 
-/* [implicit_jscontext] attribute bool isStopwatchActive; */
-NS_IMETHODIMP nsPerformanceStatsService::GetIsStopwatchActive(JSContext* cx, bool *aIsStopwatchActive)
+//[implicit_jscontext] attribute bool isMonitoringCPOW;
+NS_IMETHODIMP nsPerformanceStatsService::GetIsMonitoringCPOW(JSContext* cx, bool *aIsStopwatchActive)
+{
+  JSRuntime *runtime = JS_GetRuntime(cx);
+  *aIsStopwatchActive = js::GetStopwatchIsMonitoringCPOW(runtime);
+  return NS_OK;
+}
+NS_IMETHODIMP nsPerformanceStatsService::SetIsMonitoringCPOW(JSContext* cx, bool aIsStopwatchActive)
 {
   JSRuntime *runtime = JS_GetRuntime(cx);
-  *aIsStopwatchActive = js::IsStopwatchActive(runtime);
+  if (!js::SetStopwatchIsMonitoringCPOW(runtime, aIsStopwatchActive)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
   return NS_OK;
 }
-NS_IMETHODIMP nsPerformanceStatsService::SetIsStopwatchActive(JSContext* cx, bool aIsStopwatchActive)
+NS_IMETHODIMP nsPerformanceStatsService::GetIsMonitoringJank(JSContext* cx, bool *aIsStopwatchActive)
 {
   JSRuntime *runtime = JS_GetRuntime(cx);
-  if (!js::SetStopwatchActive(runtime, aIsStopwatchActive)) {
+  *aIsStopwatchActive = js::GetStopwatchIsMonitoringJank(runtime);
+  return NS_OK;
+}
+NS_IMETHODIMP nsPerformanceStatsService::SetIsMonitoringJank(JSContext* cx, bool aIsStopwatchActive)
+{
+  JSRuntime *runtime = JS_GetRuntime(cx);
+  if (!js::SetStopwatchIsMonitoringJank(runtime, aIsStopwatchActive)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
   return NS_OK;
 }
 
 /* readonly attribute nsIPerformanceSnapshot snapshot; */
 NS_IMETHODIMP nsPerformanceStatsService::GetSnapshot(JSContext* cx, nsIPerformanceSnapshot * *aSnapshot)
 {
--- a/toolkit/components/perfmonitoring/tests/browser/browser_compartments.js
+++ b/toolkit/components/perfmonitoring/tests/browser/browser_compartments.js
@@ -12,54 +12,57 @@ Cu.import("resource://gre/modules/Perfor
 Cu.import("resource://testing-common/ContentTask.jsm", this);
 
 const URL = "http://example.com/browser/toolkit/components/perfmonitoring/tests/browser/browser_compartments.html?test=" + Math.random();
 const PARENT_TITLE = `Main frame for test browser_compartments.js ${Math.random()}`;
 const FRAME_TITLE = `Subframe for test browser_compartments.js ${Math.random()}`;
 
 // This function is injected as source as a frameScript
 function frameScript() {
-  "use strict";
+  try {
+    "use strict";
 
-  const { utils: Cu, classes: Cc, interfaces: Ci } = Components;
-  Cu.import("resource://gre/modules/PerformanceStats.jsm");
+    const { utils: Cu, classes: Cc, interfaces: Ci } = Components;
+    Cu.import("resource://gre/modules/PerformanceStats.jsm");
 
-  let performanceStatsService =
-    Cc["@mozilla.org/toolkit/performance-stats-service;1"].
-    getService(Ci.nsIPerformanceStatsService);
+    let performanceStatsService =
+      Cc["@mozilla.org/toolkit/performance-stats-service;1"].
+      getService(Ci.nsIPerformanceStatsService);
 
-  // Make sure that the stopwatch is now active.
-  performanceStatsService.isStopwatchActive = true;
-
-  let monitor = PerformanceStats.getMonitor(["jank", "cpow", "ticks"]);
+    // Make sure that the stopwatch is now active.
+    let monitor = PerformanceStats.getMonitor(["jank", "cpow", "ticks"]);
 
-  addMessageListener("compartments-test:getStatistics", () => {
-    try {
-      monitor.promiseSnapshot().then(snapshot => {
-        sendAsyncMessage("compartments-test:getStatistics", snapshot);
-      });
-    } catch (ex) {
-      Cu.reportError("Error in content: " + ex);
-      Cu.reportError(ex.stack);
-    }
-  });
+    addMessageListener("compartments-test:getStatistics", () => {
+      try {
+        monitor.promiseSnapshot().then(snapshot => {
+          sendAsyncMessage("compartments-test:getStatistics", snapshot);
+        });
+      } catch (ex) {
+        Cu.reportError("Error in content (getStatistics): " + ex);
+        Cu.reportError(ex.stack);
+      }
+    });
 
-  addMessageListener("compartments-test:setTitles", titles => {
-    try {
-      content.document.title = titles.data.parent;
-      for (let i = 0; i < content.frames.length; ++i) {
-        content.frames[i].postMessage({title: titles.data.frames}, "*");
+    addMessageListener("compartments-test:setTitles", titles => {
+      try {
+        content.document.title = titles.data.parent;
+        for (let i = 0; i < content.frames.length; ++i) {
+          content.frames[i].postMessage({title: titles.data.frames}, "*");
+        }
+        console.log("content", "Done setting titles", content.document.title);
+        sendAsyncMessage("compartments-test:setTitles");
+      } catch (ex) {
+        Cu.reportError("Error in content (setTitles): " + ex);
+        Cu.reportError(ex.stack);
       }
-      console.log("content", "Done setting titles", content.document.title);
-      sendAsyncMessage("compartments-test:setTitles");
-    } catch (ex) {
-      Cu.reportError("Error in content: " + ex);
-      Cu.reportError(ex.stack);
-    }
-  });
+    });
+  } catch (ex) {
+    Cu.reportError("Error in content (setup): " + ex);
+    Cu.reportError(ex.stack);    
+  }
 }
 
 // A variant of `Assert` that doesn't spam the logs
 // in case of success.
 let SilentAssert = {
   equal: function(a, b, msg) {
     if (a == b) {
       return;
--- a/toolkit/components/perfmonitoring/tests/xpcshell/test_compartments.js
+++ b/toolkit/components/perfmonitoring/tests/xpcshell/test_compartments.js
@@ -5,35 +5,46 @@ const {utils: Cu, interfaces: Ci, classe
 Cu.import("resource://gre/modules/Task.jsm", this);
 Cu.import("resource://gre/modules/Services.jsm", this);
 Cu.import("resource://gre/modules/PerformanceStats.jsm", this);
 
 function run_test() {
   run_next_test();
 }
 
-let monitor = PerformanceStats.getMonitor(["ticks", "jank", "cpow"]);
-
 let promiseStatistics = Task.async(function*(name) {
   yield Promise.resolve(); // Make sure that we wait until
   // statistics have been updated.
-  return monitor.promiseSnapshot();
+  let service = Cc["@mozilla.org/toolkit/performance-stats-service;1"].
+    getService(Ci.nsIPerformanceStatsService);
+  let snapshot = service.getSnapshot();
+  let componentsData = [];
+  let componentsEnum = snapshot.getComponentsData().enumerate();
+  while (componentsEnum.hasMoreElements()) {
+    componentsData.push(componentsEnum.getNext().QueryInterface(Ci.nsIPerformanceStats));
+  }
+  return {
+    processData: snapshot.getProcessData(),
+    componentsData
+  };
 });
 
 let promiseSetMonitoring = Task.async(function*(to) {
-  Cc["@mozilla.org/toolkit/performance-stats-service;1"].
-    getService(Ci.nsIPerformanceStatsService).
-    isStopwatchActive = to;
+  let service = Cc["@mozilla.org/toolkit/performance-stats-service;1"].
+    getService(Ci.nsIPerformanceStatsService);
+  service.isMonitoringJank = to;
+  service.isMonitoringCPOW = to;
   yield Promise.resolve();
 });
 
-function getBuiltinStatistics(snapshot) {
+function getBuiltinStatistics(name, snapshot) {
   let stats = snapshot.componentsData.find(stats =>
     stats.isSystem && !stats.addonId
   );
+  do_print(`Built-in statistics for ${name} were ${stats?"":"not "}found`);
   return stats;
 }
 
 function burnCPU(ms) {
   do_print("Burning CPU");
   let counter = 0;
   let ignored = [];
   let start = Date.now();
@@ -98,32 +109,32 @@ add_task(function* test_measure() {
   ensureEquals(stats0, stats1, "Initial state vs. Initial state + burn, without stopwatch");
   let process1 = stats1.processData;
   let process2 = stats2.processData;
   let process3 = stats3.processData;
   let process4 = stats4.processData;
   if (skipPrecisionTests) {
     do_print("Skipping totalUserTime check under Windows XP, as timer is not always updated by the OS.")
   } else {
-    Assert.ok(process2.jank.totalUserTime - process1.jank.totalUserTime >= 10000, `At least 10ms counted for process time (${process2.jank.totalUserTime - process1.jank.totalUserTime})`);
+    Assert.ok(process2.totalUserTime - process1.totalUserTime >= 10000, `At least 10ms counted for process time (${process2.totalUserTime - process1.totalUserTime})`);
   }
-  Assert.equal(process2.jank.totalCPOWTime, process1.jank.totalCPOWTime, "We haven't used any CPOW time during the first burn");
-  Assert.equal(process4.jank.totalUserTime, process3.jank.totalUserTime, "After deactivating the stopwatch, we didn't count any time");
-  Assert.equal(process4.jank.totalCPOWTime, process3.jank.totalCPOWTime, "After deactivating the stopwatch, we didn't count any CPOW time");
+  Assert.equal(process2.totalCPOWTime, process1.totalCPOWTime, "We haven't used any CPOW time during the first burn");
+  Assert.equal(process4.totalUserTime, process3.totalUserTime, "After deactivating the stopwatch, we didn't count any time");
+  Assert.equal(process4.totalCPOWTime, process3.totalCPOWTime, "After deactivating the stopwatch, we didn't count any CPOW time");
 
-  let builtin1 = getBuiltinStatistics(stats1) || { jank: { totalUserTime: 0 }, cpow: { totalCPOWTime: 0 } };
-  let builtin2 = getBuiltinStatistics(stats2);
-  let builtin3 = getBuiltinStatistics(stats3);
-  let builtin4 = getBuiltinStatistics(stats4);
+  let builtin1 = getBuiltinStatistics("Built-ins 1", stats1) || { totalUserTime: 0, totalCPOWTime: 0 };
+  let builtin2 = getBuiltinStatistics("Built-ins 2", stats2);
+  let builtin3 = getBuiltinStatistics("Built-ins 3", stats3);
+  let builtin4 = getBuiltinStatistics("Built-ins 4", stats4);
   Assert.notEqual(builtin2, null, "Found the statistics for built-ins 2");
   Assert.notEqual(builtin3, null, "Found the statistics for built-ins 3");
   Assert.notEqual(builtin4, null, "Found the statistics for built-ins 4");
 
   if (skipPrecisionTests) {
     do_print("Skipping totalUserTime check under Windows XP, as timer is not always updated by the OS.")
   } else {
-    Assert.ok(builtin2.jank.totalUserTime - builtin1.jank.totalUserTime >= 10000, `At least 10ms counted for built-in statistics (${builtin2.jank.totalUserTime - builtin1.jank.totalUserTime})`);
+    Assert.ok(builtin2.totalUserTime - builtin1.totalUserTime >= 10000, `At least 10ms counted for built-in statistics (${builtin2.totalUserTime - builtin1.totalUserTime})`);
   }
-  Assert.equal(builtin2.jank.totalCPOWTime, builtin1.jank.totalCPOWTime, "We haven't used any CPOW time during the first burn for the built-in");
-  Assert.equal(builtin2.jank.totalCPOWTime, builtin1.jank.totalCPOWTime, "No CPOW for built-in statistics");
-  Assert.equal(builtin4.jank.totalUserTime, builtin3.jank.totalUserTime, "After deactivating the stopwatch, we didn't count any time for the built-in");
-  Assert.equal(builtin4.jank.totalCPOWTime, builtin3.jank.totalCPOWTime, "After deactivating the stopwatch, we didn't count any CPOW time for the built-in");
+  Assert.equal(builtin2.totalCPOWTime, builtin1.totalCPOWTime, "We haven't used any CPOW time during the first burn for the built-in");
+  Assert.equal(builtin2.totalCPOWTime, builtin1.totalCPOWTime, "No CPOW for built-in statistics");
+  Assert.equal(builtin4.totalUserTime, builtin3.totalUserTime, "After deactivating the stopwatch, we didn't count any time for the built-in");
+  Assert.equal(builtin4.totalCPOWTime, builtin3.totalCPOWTime, "After deactivating the stopwatch, we didn't count any CPOW time for the built-in");
 });