Bug 1184486 - Let PerformanceStats.jsm play nicer with process-per-tab. r=mconley

This commit is contained in:
David Rajchenbach-Teller
2015-07-16 12:19:17 +02:00
parent b17ea7ab47
commit 1b943fd2f1
4 changed files with 41 additions and 13 deletions

View File

@@ -49,7 +49,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "finalizer",
// 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_IMMUTABLE = ["addonId", "isSystem", "isChildProcess", "groupId", "processId"];
const PROPERTIES_META = [...PROPERTIES_META_IMMUTABLE, "windowId", "title", "name"];
// How long we wait for children processes to respond.

View File

@@ -22,7 +22,7 @@
* All values are monotonic and are updated only when
* `nsIPerformanceStatsService.isStopwatchActive` is `true`.
*/
[scriptable, uuid(1bc2d016-e9ae-4186-97c6-9478eddda245)]
[scriptable, uuid(80e638bf-db19-4550-97bd-06e1f74c1c1f)]
interface nsIPerformanceStats: nsISupports {
/**
* An identifier unique to the component.
@@ -91,6 +91,11 @@ interface nsIPerformanceStats: nsISupports {
*/
readonly attribute bool isSystem;
/**
* The process running this group.
*/
readonly attribute unsigned long long processId;
/**
* Jank indicator.
*
@@ -104,7 +109,7 @@ interface nsIPerformanceStats: nsISupports {
/**
* A snapshot of the performance data of the process.
*/
[scriptable, uuid(29ecebd0-908a-4b34-8f62-a6015dea1141)]
[scriptable, uuid(2e0c50e2-3aff-4cc8-88a6-c0dc200da8fc)]
interface nsIPerformanceSnapshot: nsISupports {
/**
* Data on all individual components.

View File

@@ -35,6 +35,7 @@ public:
const nsAString& aAddonId,
const nsAString& aTitle,
const uint64_t aWindowId,
const uint64_t aProcessId,
const bool aIsSystem,
const js::PerformanceData& aPerformanceData)
: mName(aName)
@@ -42,6 +43,7 @@ public:
, mAddonId(aAddonId)
, mTitle(aTitle)
, mWindowId(aWindowId)
, mProcessId(aProcessId)
, mIsSystem(aIsSystem)
, mPerformanceData(aPerformanceData)
{
@@ -121,7 +123,7 @@ public:
};
/* void getDurations (out unsigned long aCount, [array, size_is (aCount), retval] out unsigned long long aNumberOfOccurrences); */
NS_IMETHODIMP GetDurations(uint32_t *aCount, uint64_t **aNumberOfOccurrences) override {
NS_IMETHOD GetDurations(uint32_t *aCount, uint64_t **aNumberOfOccurrences) override {
const size_t length = mozilla::ArrayLength(mPerformanceData.durations);
if (aCount) {
*aCount = length;
@@ -133,6 +135,15 @@ public:
return NS_OK;
};
/*
readonly attribute unsigned long long processId;
*/
NS_IMETHODIMP GetProcessId(uint64_t* processId)
{
*processId = mProcessId;
return NS_OK;
}
private:
nsString mName;
nsString mParentId;
@@ -140,6 +151,7 @@ private:
nsString mAddonId;
nsString mTitle;
uint64_t mWindowId;
uint64_t mProcessId;
bool mIsSystem;
js::PerformanceData mPerformanceData;
@@ -358,7 +370,7 @@ nsPerformanceSnapshot::ImportStats(JSContext* cx, const js::PerformanceData& per
bool isSystem = GetIsSystem(cx, global);
nsCOMPtr<nsIPerformanceStats> result =
new nsPerformanceStats(name, parent, groupId, addonId, title, windowId, isSystem, performance);
new nsPerformanceStats(name, parent, groupId, addonId, title, windowId, mProcessId, isSystem, performance);
return result.forget();
}
@@ -402,6 +414,7 @@ nsPerformanceSnapshot::Init(JSContext* cx, uint64_t processId) {
NS_LITERAL_STRING(""), // add-on id
NS_LITERAL_STRING(""), // title
0, // window id
mProcessId, // process id
true, // isSystem
processStats);
return NS_OK;

View File

@@ -9,12 +9,16 @@
* to the top window.
*/
Cu.import("resource://gre/modules/PerformanceStats.jsm", this);
Cu.import("resource://gre/modules/Services.jsm", this);
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()}`;
const PARENT_PID = Services.appinfo.processID;
// This function is injected as source as a frameScript
function frameScript() {
try {
@@ -22,7 +26,7 @@ function frameScript() {
const { utils: Cu, classes: Cc, interfaces: Ci } = Components;
Cu.import("resource://gre/modules/PerformanceStats.jsm");
Cu.import("resource://gre/modules/Services.jsm");
let performanceStatsService =
Cc["@mozilla.org/toolkit/performance-stats-service;1"].
getService(Ci.nsIPerformanceStatsService);
@@ -33,7 +37,7 @@ function frameScript() {
addMessageListener("compartments-test:getStatistics", () => {
try {
monitor.promiseSnapshot().then(snapshot => {
sendAsyncMessage("compartments-test:getStatistics", snapshot);
sendAsyncMessage("compartments-test:getStatistics", {snapshot, pid: Services.appinfo.processID});
});
} catch (ex) {
Cu.reportError("Error in content (getStatistics): " + ex);
@@ -135,19 +139,21 @@ function monotinicity_tester(source, testName) {
return;
}
let name = `${testName}: ${iteration++}`;
let snapshot = yield source();
if (!snapshot) {
let result = yield source();
if (!result) {
// This can happen at the end of the test when we attempt
// to communicate too late with the content process.
window.clearInterval(interval);
return;
}
let {pid, snapshot} = result;
// Sanity check on the process data.
sanityCheck(previous.processData, snapshot.processData);
SilentAssert.equal(snapshot.processData.isSystem, true);
SilentAssert.equal(snapshot.processData.name, "<process>");
SilentAssert.equal(snapshot.processData.addonId, "");
SilentAssert.equal(snapshot.processData.processId, pid);
previous.procesData = snapshot.processData;
// Sanity check on components data.
@@ -160,10 +166,14 @@ function monotinicity_tester(source, testName) {
]) {
// Note that we cannot expect components data to be always smaller
// than process data, as `getrusage` & co are not monotonic.
SilentAssert.leq(item[probe][k], 2 * snapshot.processData[probe][k],
`Sanity check (${testName}): ${k} of component is not impossibly larger than that of process`);
SilentAssert.leq(item[probe][k], 3 * snapshot.processData[probe][k],
`Sanity check (${name}): ${k} of component is not impossibly larger than that of process`);
}
let isCorrectPid = (item.processId == pid && !item.isChildProcess)
|| (item.processId != pid && item.isChildProcess);
SilentAssert.ok(isCorrectPid, `Pid check (${name}): the item comes from the right process`);
let key = item.groupId;
if (map.has(key)) {
let old = map.get(key);
@@ -222,7 +232,7 @@ add_task(function* test() {
info("Deactivating sanity checks under Windows (bug 1151240)");
} else {
info("Setting up sanity checks");
monotinicity_tester(() => monitor.promiseSnapshot(), "parent process");
monotinicity_tester(() => monitor.promiseSnapshot().then(snapshot => ({snapshot, pid: PARENT_PID})), "parent process");
monotinicity_tester(() => promiseContentResponseOrNull(browser, "compartments-test:getStatistics", null), "content process" );
}
@@ -242,7 +252,7 @@ add_task(function* test() {
});
info("Titles set");
let stats = (yield promiseContentResponse(browser, "compartments-test:getStatistics", null));
let {snapshot: stats} = (yield promiseContentResponse(browser, "compartments-test:getStatistics", null));
let titles = [for(stat of stats.componentsData) stat.title];