author | Ryan VanderMeulen <ryanvm@gmail.com> |
Wed, 15 Jul 2015 21:30:15 -0400 | |
changeset 253076 | 72835344333faa9c2f746e07aaada32c02104122 |
parent 253075 | ebb47697c795cb57188c4e36b755f777917259e9 (current diff) |
parent 253062 | 61eccd5a10ed3355e13c44ff872e471f25020efd (diff) |
child 253077 | d8023b434e25beed6cb5d38b57d6bb27aaf888df |
child 253128 | 349868f3bec7b199562cabb0425cf3c5135a7c9c |
child 253163 | 9eb7be0f006dc8f4ee8ad92a009bb7e0f5b4357e |
child 253201 | 9e0864ad7475ea6d4ad263e75a5f2bf3d838f3ab |
push id | 29058 |
push user | ryanvm@gmail.com |
push date | Thu, 16 Jul 2015 02:57:02 +0000 |
treeherder | mozilla-central@72835344333f [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 42.0a1 |
first release with | nightly linux32
72835344333f
/
42.0a1
/
20150716030208
/
files
nightly linux64
72835344333f
/
42.0a1
/
20150716030208
/
files
nightly mac
72835344333f
/
42.0a1
/
20150716030208
/
files
nightly win32
72835344333f
/
42.0a1
/
20150716030208
/
files
nightly win64
72835344333f
/
42.0a1
/
20150716030208
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
42.0a1
/
20150716030208
/
pushlog to previous
nightly linux64
42.0a1
/
20150716030208
/
pushlog to previous
nightly mac
42.0a1
/
20150716030208
/
pushlog to previous
nightly win32
42.0a1
/
20150716030208
/
pushlog to previous
nightly win64
42.0a1
/
20150716030208
/
pushlog to previous
|
toolkit/components/perfmonitoring/PerformanceStats-content.js | file | annotate | diff | comparison | revisions |
--- a/toolkit/components/aboutperformance/content/aboutPerformance.js +++ b/toolkit/components/aboutperformance/content/aboutPerformance.js @@ -81,20 +81,17 @@ let AutoUpdate = { updateRefreshRate: function () { AutoUpdate.stop(); AutoUpdate.start(); } }; let State = { - _monitor: PerformanceStats.getMonitor([ - "jank", "cpow", "ticks", - "jank-content", "cpow-content", "ticks-content", - ]), + _monitor: PerformanceStats.getMonitor(["jank", "cpow", "ticks"]), /** * @type{PerformanceData} */ _processData: null, /** * A mapping from name to PerformanceData * @@ -242,17 +239,17 @@ let updateLiveData = Task.async(function try { let dataElt = document.getElementById("liveData"); dataElt.innerHTML = ""; // Generate table headers let headerElt = document.createElement("tr"); dataElt.appendChild(headerElt); headerElt.classList.add("header"); - for (let column of [...MEASURES, {key: "name", name: ""}, {key: "process", name: ""}]) { + for (let column of [...MEASURES, {key: "name", name: ""}]) { let el = document.createElement("td"); el.classList.add(column.key); el.textContent = column.label; headerElt.appendChild(el); } let deltas = yield State.update(); @@ -278,47 +275,30 @@ let updateLiveData = Task.async(function let value = percentOfDeltaT ? Math.round(rawValue / deltas.deltaT) : rawValue; if (key == "longestDuration") { value += 1; el.classList.add("jank" + value); } el.textContent = value; } - { - // Name - let el = document.createElement("td"); - let id = item.id; - el.classList.add("contents"); - el.classList.add("name"); - row.appendChild(el); - if (item.addonId) { - let _el = el; - let _item = item; - AddonManager.getAddonByID(item.addonId, a => { - _el.textContent = a ? a.name : _item.name - }); - } else { - el.textContent = item.title || item.name; - } - } - - { - // Process information. - let el = document.createElement("td"); - el.classList.add("contents"); - el.classList.add("process"); - row.appendChild(el); - if (item.isChildProcess) { - el.textContent = "(child)"; - row.classList.add("child"); - } else { - el.textContent = "(parent)"; - row.classList.add("parent"); - } + // Name + let el = document.createElement("td"); + let id = item.id; + el.classList.add("contents"); + el.classList.add("name"); + row.appendChild(el); + if (item.addonId) { + let _el = el; + let _item = item; + AddonManager.getAddonByID(item.addonId, a => { + _el.textContent = a ? a.name : _item.name + }); + } else { + el.textContent = item.title || item.name; } } } catch (ex) { console.error(ex); } }); function go() {
--- a/toolkit/components/aboutperformance/tests/browser/browser.ini +++ b/toolkit/components/aboutperformance/tests/browser/browser.ini @@ -1,8 +1,9 @@ [DEFAULT] head = head.js support-files = browser_compartments.html browser_compartments_frame.html browser_compartments_script.js [browser_aboutperformance.js] +skip-if = e10s # Feature not implemented yet – bug 1140310
deleted file mode 100644 --- a/toolkit/components/perfmonitoring/PerformanceStats-content.js +++ /dev/null @@ -1,144 +0,0 @@ -/* 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/. */ - -/** - * A proxy implementing communication between the PerformanceStats.jsm modules - * of the parent and children processes. - * - * This script is loaded in all processes but is essentially a NOOP in the - * parent process. - */ - -"use strict"; - -const { utils: Cu, classes: Cc, interfaces: Ci } = Components; -const { Services } = Cu.import("resource://gre/modules/Services.jsm", {}); -const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {}); - -XPCOMUtils.defineLazyModuleGetter(this, "PerformanceStats", - "resource://gre/modules/PerformanceStats.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Task", - "resource://gre/modules/Task.jsm"); - -/** - * A global performance monitor used by this process. - * - * For the sake of simplicity, rather than attempting to map each PerformanceMonitor - * of the parent to a PerformanceMonitor in each child process, we maintain a single - * PerformanceMonitor in each child process. Probes activation/deactivation for this - * monitor is controlled by the activation/deactivation of probes marked as "-content" - * in the parent. - * - * In the parent, this is always an empty monitor. - */ -let gMonitor = PerformanceStats.getMonitor([]); - -/** - * `true` if this is a content process, `false` otherwise. - */ -let isContent = Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT; - -/** - * Handle message `performance-stats-service-acquire`: ensure that the global - * monitor has a given probe. This message must be sent by the parent process - * whenever a probe is activated application-wide. - * - * Note that we may miss acquire messages if they are sent before this process is - * launched. For this reason, `performance-stats-service-collect` automatically - * re-acquires probes if it realizes that they are missing. - * - * This operation is a NOOP on the parent process. - * - * @param {{payload: Array<string>}} msg.data The message received. `payload` - * must be an array of probe names. - */ -Services.cpmm.addMessageListener("performance-stats-service-acquire", function(msg) { - if (!isContent) { - return; - } - let name = msg.data.payload; - ensureAcquired(name); -}); - -/** - * Handle message `performance-stats-service-release`: release a given probe - * from the global monitor. This message must be sent by the parent process - * whenever a probe is deactivated application-wide. - * - * Note that we may miss release messages if they are sent before this process is - * launched. This is ok, as probes are inactive by default: if we miss the release - * message, we have already missed the acquire message, and the effect of both - * messages together is to reset to the default state. - * - * This operation is a NOOP on the parent process. - * - * @param {{payload: Array<string>}} msg.data The message received. `payload` - * must be an array of probe names. - */ -Services.cpmm.addMessageListener("performance-stats-service-release", function(msg) { - if (!isContent) { - return; - } - // Keep only the probes that do not appear in the payload - let probes = gMonitor.getProbeNames - .filter(x => msg.data.payload.indexOf(x) == -1); - gMonitor = PerformanceStats.getMonitor(probes); -}); - -/** - * Ensure that this process has all the probes it needs. - * - * @param {Array<string>} probeNames The name of all probes needed by the - * process. - */ -function ensureAcquired(probeNames) { - let alreadyAcquired = gMonitor.probeNames; - - // Algorithm is O(n^2) because we expect that n ≤ 3. - let shouldAcquire = []; - for (let probeName of probeNames) { - if (alreadyAcquired.indexOf(probeName) == -1) { - shouldAcquire.push(probeName) - } - } - - if (shouldAcquire.length == 0) { - return; - } - gMonitor = PerformanceStats.getMonitor([...alreadyAcquired, ...shouldAcquire]); -} - -/** - * Handle message `performance-stats-service-collected`: collect the data - * obtained by the monitor. This message must be sent by the parent process - * whenever we grab a performance snapshot of the application. - * - * This operation provides `null` on the parent process. - * - * @param {{data: {payload: Array<string>}}} msg The message received. `payload` - * must be an array of probe names. - */ -Services.cpmm.addMessageListener("performance-stats-service-collect", Task.async(function*(msg) { - let {id, payload: {probeNames}} = msg.data; - if (!isContent) { - // This message was sent by the parent process to itself. - // As per protocol, respond `null`. - Services.cpmm.sendAsyncMessage("performance-stats-service-collect", { - id, - data: null - }); - return; - } - - // We may have missed acquire messages if the process was loaded too late. - // Catch up now. - ensureAcquired(probeNames); - - // Collect and return data. - let data = yield gMonitor.promiseSnapshot({probeNames}); - Services.cpmm.sendAsyncMessage("performance-stats-service-collect", { - id, - data - }); -}));
--- a/toolkit/components/perfmonitoring/PerformanceStats.jsm +++ b/toolkit/components/perfmonitoring/PerformanceStats.jsm @@ -18,49 +18,38 @@ const { classes: Cc, interfaces: Ci, uti * from the probes. * * Data is collected by "Performance Group". Typically, a Performance Group * is an add-on, or a frame, or the internals of the application. */ Cu.import("resource://gre/modules/XPCOMUtils.jsm", this); Cu.import("resource://gre/modules/Services.jsm", this); -Cu.import("resource://gre/modules/Task.jsm", this); - -XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils", - "resource://gre/modules/PromiseUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "setTimeout", - "resource://gre/modules/Timer.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "clearTimeout", - "resource://gre/modules/Timer.jsm"); // The nsIPerformanceStatsService provides lower-level // access to SpiderMonkey and the probes. XPCOMUtils.defineLazyServiceGetter(this, "performanceStatsService", "@mozilla.org/toolkit/performance-stats-service;1", Ci.nsIPerformanceStatsService); // The finalizer lets us automatically release (and when possible deactivate) // probes when a monitor is garbage-collected. XPCOMUtils.defineLazyServiceGetter(this, "finalizer", "@mozilla.org/toolkit/finalizationwitness;1", Ci.nsIFinalizationWitnessService ); + // The topic used to notify that a PerformanceMonitor has been garbage-collected // and that we can release/close the probes it holds. const FINALIZATION_TOPIC = "performancemonitor-finalize"; -const PROPERTIES_META_IMMUTABLE = ["addonId", "isSystem", "isChildProcess", "groupId"]; -const PROPERTIES_META = [...PROPERTIES_META_IMMUTABLE, "windowId", "title", "name"]; +const PROPERTIES_META_IMMUTABLE = ["name", "addonId", "isSystem", "groupId"]; +const PROPERTIES_META = [...PROPERTIES_META_IMMUTABLE, "windowId", "title"]; -// How long we wait for children processes to respond. -const MAX_WAIT_FOR_CHILD_PROCESS_MS = 5000; - -let isContent = Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT; /** * Access to a low-level performance probe. * * Each probe is dedicated to some form of performance monitoring. * As each probe may have a performance impact, a probe is activated * only when a client has requested a PerformanceMonitor for this probe, * and deactivated once all clients are disposed of. */ @@ -131,24 +120,24 @@ Probe.prototype = { * @param {object} a An object returned by `this.extract()`. May * NOT be `null`. * @param {object} b An object returned by `this.extract()`. May * be `null`. * * @return {object} An object representing `a - b`. If `b` is * `null`, this is `a`. */ - subtract: function(a, b) { + substract: function(a, b) { if (a == null) { throw new TypeError(); } if (b == null) { return a; } - return this._impl.subtract(a, b); + return this._impl.substract(a, b); }, /** * The name of the probe. */ get name() { return this._name; } @@ -210,17 +199,17 @@ let Probes = { } for (let i = 0; i < a.durations.length; ++i) { if (a.durations[i] != b.durations[i]) { return false; } } return true; }, - subtract: function(a, b) { + substract: function(a, b) { // invariant: `a` and `b` are both non-null let result = { totalUserTime: a.totalUserTime - b.totalUserTime, totalSystemTime: a.totalSystemTime - b.totalSystemTime, durations: [], longestDuration: -1, }; for (let i = 0; i < a.durations.length; ++i) { @@ -249,17 +238,17 @@ let Probes = { extract: function(xpcom) { return { totalCPOWTime: xpcom.totalCPOWTime }; }, isEqual: function(a, b) { return a.totalCPOWTime == b.totalCPOWTime; }, - subtract: function(a, b) { + substract: function(a, b) { return { totalCPOWTime: a.totalCPOWTime - b.totalCPOWTime }; } }), /** * A probe measuring activations, i.e. the number @@ -278,88 +267,22 @@ let Probes = { extract: function(xpcom) { return { ticks: xpcom.ticks }; }, isEqual: function(a, b) { return a.ticks == b.ticks; }, - subtract: function(a, b) { + substract: function(a, b) { return { ticks: a.ticks - b.ticks }; } }), - - "jank-content": new Probe("jank-content", { - _isActive: false, - set isActive(x) { - this._isActive = x; - if (x) { - Process.broadcast("acquire", ["jank"]); - } else { - Process.broadcast("release", ["jank"]); - } - }, - get isActive() { - return this._isActive; - }, - extract: function(xpcom) { - return {}; - }, - isEqual: function(a, b) { - return true; - }, - subtract: function(a, b) { - return null; - } - }), - - "cpow-content": new Probe("cpow-content", { - _isActive: false, - set isActive(x) { - this._isActive = x; - if (x) { - Process.broadcast("acquire", ["cpow"]); - } else { - Process.broadcast("release", ["cpow"]); - } - }, - get isActive() { - return this._isActive; - }, - extract: function(xpcom) { - return {}; - }, - isEqual: function(a, b) { - return true; - }, - subtract: function(a, b) { - return null; - } - }), - - "ticks-content": new Probe("ticks-content", { - set isActive(x) { - // Ignore: This probe is always active. - }, - get isActive() { - return true; - }, - extract: function(xpcom) { - return {}; - }, - isEqual: function(a, b) { - return true; - }, - subtract: function(a, b) { - return null; - } - }), }; /** * A monitor for a set of probes. * * Keeping probes active when they are unused is often a bad * idea for performance reasons. Upon destruction, or whenever @@ -378,86 +301,52 @@ function PerformanceMonitor(probes) { // `this` object, a notification of `FINALIZATION_TOPIC` will be triggered // with `id` as message. this._id = PerformanceMonitor.makeId(); this._finalizer = finalizer.make(FINALIZATION_TOPIC, this._id) PerformanceMonitor._monitors.set(this._id, probes); } PerformanceMonitor.prototype = { /** - * The names of probes activated in this monitor. - */ - get probeNames() { - return [for (probe of this._probes) probe.name]; - }, - - /** * Return asynchronously a snapshot with the data * for each probe monitored by this PerformanceMonitor. * * All numeric values are non-negative and can only increase. Depending on * the probe and the underlying operating system, probes may not be available * immediately and may miss some activity. * * Clients should NOT expect that the first call to `promiseSnapshot()` * will return a `Snapshot` in which all values are 0. For most uses, * the appropriate scenario is to perform a first call to `promiseSnapshot()` * to obtain a baseline, and then watch evolution of the values by calling - * `promiseSnapshot()` and `subtract()`. + * `promiseSnapshot()` and `substract()`. * * On the other hand, numeric values are also monotonic across several instances * of a PerformanceMonitor with the same probes. * let a = PerformanceStats.getMonitor(someProbes); * let snapshot1 = yield a.promiseSnapshot(); * * // ... * let b = PerformanceStats.getMonitor(someProbes); // Same list of probes * let snapshot2 = yield b.promiseSnapshot(); * * // all values of `snapshot2` are greater or equal to values of `snapshot1`. * - * @param {object} options If provided, an object that may contain the following - * fields: - * {Array<string>} probeNames The subset of probes to use for this snapshot. - * These probes must be a subset of the probes active in the monitor. - * * @return {Promise} * @resolve {Snapshot} */ - promiseSnapshot: function(options = null) { + promiseSnapshot: function() { if (!this._finalizer) { throw new Error("dispose() has already been called, this PerformanceMonitor is not usable anymore"); } - let probes; - if (options && options.probeNames || undefined) { - if (!Array.isArray(options.probeNames)) { - throw new TypeError(); - } - // Make sure that we only request probes that we have - for (let probeName of options.probeNames) { - let probe = this._probes.find(probe => probe.name == probeName); - if (!probe) { - throw new TypeError(`I need probe ${probeName} but I only have ${this.probeNames}`); - } - if (!probes) { - probes = []; - } - probes.push(probe); - } - } else { - probes = this._probes; - } - return Task.spawn(function*() { - let collected = yield Process.broadcastAndCollect("collect", {probeNames: [for (probe of probes) probe.name]}); - return new Snapshot({ - xpcom: performanceStatsService.getSnapshot(), - childProcesses: collected, - probes - }); - }); + // Current implementation is actually synchronous. + return Promise.resolve().then(() => new Snapshot({ + xpcom: performanceStatsService.getSnapshot(), + probes: this._probes + })); }, /** * Release the probes used by this monitor. * * Releasing probes as soon as they are unused is a good idea, as some probes * cost CPU and/or memory. */ @@ -487,17 +376,17 @@ PerformanceMonitor._monitors = new Map() PerformanceMonitor.make = function(probeNames) { // Sanity checks if (!Array.isArray(probeNames)) { throw new TypeError("Expected an array, got " + probes); } let probes = []; for (let probeName of probeNames) { if (!(probeName in Probes)) { - throw new TypeError("Probe not implemented: " + probeName); + throw new TypeError("Probe not implemented: " + k); } probes.push(Probes[probeName]); } return new PerformanceMonitor(probes); }; /** @@ -573,34 +462,22 @@ this.PerformanceStats = { * `undefined` if this probe is not active. * * @field {object|undefined} jank See the documentation of probe "jank". * `undefined` if this probe is not active. * * @field {object|undefined} cpow See the documentation of probe "cpow". * `undefined` if this probe is not active. */ -function PerformanceData({xpcom, json, probes}) { - if (xpcom && json) { - throw new TypeError("Cannot import both xpcom and json data"); - } - let source = xpcom || json; +function PerformanceData({xpcom, probes}) { for (let k of PROPERTIES_META) { - this[k] = source[k]; + this[k] = xpcom[k]; } - if (xpcom) { - for (let probe of probes) { - this[probe.name] = probe.extract(xpcom); - } - this.isChildProcess = false; - } else { - for (let probe of probes) { - this[probe.name] = json[probe.name]; - } - this.isChildProcess = true; + for (let probe of probes) { + this[probe.name] = probe.extract(xpcom); } } PerformanceData.prototype = { /** * Compare two instances of `PerformanceData` * * @return `true` if `this` and `to` have equal values in all fields. */ @@ -637,166 +514,25 @@ PerformanceData.prototype = { function PerformanceDiff(current, old = null) { for (let k of PROPERTIES_META) { this[k] = current[k]; } for (let probeName of Object.keys(Probes)) { let other = old ? old[probeName] : null; if (probeName in current) { - this[probeName] = Probes[probeName].subtract(current[probeName], other); + this[probeName] = Probes[probeName].substract(current[probeName], other); } } } /** - * A snapshot of the performance usage of the application. - * - * @param {nsIPerformanceSnapshot} xpcom The data acquired from this process. - * @param {Array<Object>} childProcesses The data acquired from children processes. - * @param {Array<Probe>} probes The active probes. + * A snapshot of the performance usage of the process. */ -function Snapshot({xpcom, childProcesses, probes}) { +function Snapshot({xpcom, probes}) { this.componentsData = []; - - // Parent process - if (xpcom) { - let enumeration = xpcom.getComponentsData().enumerate(); - while (enumeration.hasMoreElements()) { - let xpcom = enumeration.getNext().QueryInterface(Ci.nsIPerformanceStats); - this.componentsData.push(new PerformanceData({xpcom, probes})); - } + let enumeration = xpcom.getComponentsData().enumerate(); + while (enumeration.hasMoreElements()) { + let stat = enumeration.getNext().QueryInterface(Ci.nsIPerformanceStats); + this.componentsData.push(new PerformanceData({xpcom: stat, probes})); } - - // Content processes - if (childProcesses) { - for (let {componentsData} of childProcesses) { - // We are only interested in `componentsData` for the time being. - for (let json of componentsData) { - this.componentsData.push(new PerformanceData({json, probes})); - } - } - } - this.processData = new PerformanceData({xpcom: xpcom.getProcessData(), probes}); } - -/** - * Communication with other processes - */ -let Process = { - // `true` once communications have been initialized - _initialized: false, - - // the message manager - _loader: null, - - // a counter used to match responses to requests - _idcounter: 0, - - /** - * If we are in a child process, return `null`. - * Otherwise, return the global parent process message manager - * and load the script to connect to children processes. - */ - get loader() { - if (this._initialized) { - return this._loader; - } - this._initialized = true; - this._loader = Services.ppmm; - if (!this._loader) { - // We are in a child process. - return null; - } - this._loader.loadProcessScript("resource://gre/modules/PerformanceStats-content.js", - true/*including future processes*/); - return this._loader; - }, - - /** - * Broadcast a message to all children processes. - * - * NOOP if we are in a child process. - */ - broadcast: function(topic, payload) { - if (!this.loader) { - return; - } - this.loader.broadcastAsyncMessage("performance-stats-service-" + topic, {payload}); - }, - - /** - * Brodcast a message to all children processes and wait for answer. - * - * NOOP if we are in a child process, or if we have no children processes, - * in which case we return `undefined`. - * - * @return {undefined} If we have no children processes, in particular - * if we are in a child process. - * @return {Promise<Array<Object>>} If we have children processes, an - * array of objects with a structure similar to PerformanceData. Note - * that the array may be empty if no child process responded. - */ - broadcastAndCollect: Task.async(function*(topic, payload) { - if (!this.loader || this.loader.childCount == 1) { - return undefined; - } - const TOPIC = "performance-stats-service-" + topic; - let id = this._idcounter++; - - // The number of responses we are expecting. Note that we may - // not receive all responses if a process is too long to respond. - let expecting = this.loader.childCount; - - // The responses we have collected, in arbitrary order. - let collected = []; - let deferred = PromiseUtils.defer(); - - // The content script may be loaded more than once (bug 1184115). - // To avoid double-responses, we keep track of who has already responded. - // Note that we could it on the other end, at the expense of implementing - // an additional .jsm just for that purpose. - let responders = new Set(); - let observer = function({data, target}) { - if (data.id != id) { - // Collision between two collections, - // ignore the other one. - return; - } - if (responders.has(target)) { - return; - } - responders.add(target); - if (data.data) { - collected.push(data.data) - } - if (--expecting > 0) { - // We are still waiting for at least one response. - return; - } - deferred.resolve(); - }; - this.loader.addMessageListener(TOPIC, observer); - this.loader.broadcastAsyncMessage( - TOPIC, - {id, payload} - ); - - // Processes can die/freeze/be busy loading a page..., so don't expect - // that they will always respond. - let timeout = setTimeout(() => { - if (expecting == 0) { - return; - } - deferred.resolve(); - }, MAX_WAIT_FOR_CHILD_PROCESS_MS); - - deferred.promise.then(() => { - clearTimeout(timeout); - }); - - yield deferred.promise; - this.loader.removeMessageListener(TOPIC, observer); - - return collected; - }) -};
--- a/toolkit/components/perfmonitoring/moz.build +++ b/toolkit/components/perfmonitoring/moz.build @@ -8,17 +8,16 @@ XPCSHELL_TESTS_MANIFESTS += ['tests/xpcs BROWSER_CHROME_MANIFESTS += ['tests/browser/browser.ini'] FAIL_ON_WARNINGS = True XPIDL_MODULE = 'toolkit_perfmonitoring' EXTRA_JS_MODULES += [ 'AddonWatcher.jsm', - 'PerformanceStats-content.js', 'PerformanceStats.jsm', ] XPIDL_SOURCES += [ 'nsIPerformanceStats.idl', ] UNIFIED_SOURCES += [
--- a/toolkit/components/perfmonitoring/nsPerformanceStats.cpp +++ b/toolkit/components/perfmonitoring/nsPerformanceStats.cpp @@ -255,17 +255,17 @@ nsPerformanceSnapshot::GetGroupId(JSCont uint64_t uid, nsString& groupId) { JSRuntime* rt = JS_GetRuntime(cx); uint64_t runtimeId = reinterpret_cast<uintptr_t>(rt); groupId.AssignLiteral("process: "); groupId.AppendInt(mProcessId); - groupId.AppendLiteral(", thread: "); + groupId.AssignLiteral(", thread: "); groupId.AppendInt(runtimeId); groupId.AppendLiteral(", group: "); groupId.AppendInt(uid); } /* static */ bool nsPerformanceSnapshot::GetIsSystem(JSContext*, JS::Handle<JSObject*> global)
--- a/toolkit/components/perfmonitoring/tests/browser/browser_compartments.js +++ b/toolkit/components/perfmonitoring/tests/browser/browser_compartments.js @@ -81,17 +81,17 @@ let SilentAssert = { } Assert.ok(a, msg); }, leq: function(a, b, msg) { this.ok(a <= b, `${msg}: ${a} <= ${b}`); } }; -let isShuttingDown = false; + function monotinicity_tester(source, testName) { // In the background, check invariants: // - numeric data can only ever increase; // - the name, addonId, isSystem of a component never changes; // - the name, addonId, isSystem of the process data; // - there is at most one component with a combination of `name` and `addonId`; // - types, etc. let previous = { @@ -125,20 +125,16 @@ function monotinicity_tester(source, tes } for (let i = 0; i < next.jank.durations.length - 1; ++i) { SilentAssert.leq(next.jank.durations[i + 1], next.jank.durations[i], `Sanity check (${testName}): durations[${i}] >= durations[${i + 1}].`) } }; let iteration = 0; let frameCheck = Task.async(function*() { - if (isShuttingDown) { - window.clearInterval(interval); - return; - } let name = `${testName}: ${iteration++}`; let snapshot = yield source(); if (!snapshot) { // This can happen at the end of the test when we attempt // to communicate too late with the content process. window.clearInterval(interval); return; } @@ -158,20 +154,17 @@ function monotinicity_tester(source, tes ["jank", "totalSystemTime"], ["cpow", "totalCPOWTime"] ]) { SilentAssert.leq(item[probe][k], snapshot.processData[probe][k], `Sanity check (${testName}): component has a lower ${k} than process`); } let key = item.groupId; - if (map.has(key)) { - let old = map.get(key); - Assert.ok(false, `Component ${key} has already been seen. Latest: ${item.title||item.addonId||item.name}, previous: ${old.title||old.addonId||old.name}`); - } + SilentAssert.ok(!map.has(key), "The component hasn't been seen yet."); map.set(key, item); } for (let [key, item] of map) { sanityCheck(previous.componentsMap.get(key), item); previous.componentsMap.set(key, item); } }); let interval = window.setInterval(frameCheck, 300); @@ -238,25 +231,19 @@ add_task(function* test() { Assert.ok(!titles.includes(FRAME_TITLE), "Searching by title, the frames don't show up in the list of components"); info(`Searching for window title '${PARENT_TITLE}' in ${JSON.stringify(titles)} (I hope to find it)`); let parent = stats.componentsData.find(x => x.title == PARENT_TITLE); if (!parent) { info("Searching by title, we didn't find the main frame"); continue; } - info("Found the main frame"); - if (skipTotalUserTime) { - info("Not looking for total user time on this platform, we're done"); - } else if (parent.jank.totalUserTime > 1000) { - info("Enough CPU time detected, we're done"); + if (skipTotalUserTime || parent.jank.totalUserTime > 1000) { break; } else { - info(`Not enough CPU time detected: ${parent.jank.totalUserTime}`); - info(`Details: ${JSON.stringify(parent, null, "\t")}`); + info(`Not enough CPU time detected: ${parent.jank.totalUserTime}`) } } - isShuttingDown = true; // Cleanup gBrowser.removeTab(newTab); });