Bug 1344174 -Add measure for memory distribution among child processes. r=chutten

This commit is contained in:
Gabor Krizsanits 2017-04-07 12:14:45 +02:00
Родитель 8e25f6f497
Коммит e2e7641412
4 изменённых файлов: 142 добавлений и 4 удалений

Просмотреть файл

@ -4,3 +4,5 @@ support-files =
file_domainPolicy_base.html
[browser_domainPolicy.js]
[browser_memory_distribution_telemetry.js]
skip-if = !e10 # This is an e10s only probe.

Просмотреть файл

@ -0,0 +1,71 @@
"use strict";
var session = Cu.import("resource://gre/modules/TelemetrySession.jsm", {});
const DUMMY_PAGE_DATA_URI = `data:text/html,
<html>
<head>
<meta charset="utf-8"/>
<title>Dummy</title>
</head>
<body>
<h1 id='header'>Just a regular everyday normal page.</h1>
</body>
</html>`;
/**
* Tests the MEMORY_DISTRIBUTION_AMONG_CONTENT probe by opening a few tabs, then triggering
* the memory probes and waiting for the "gather-memory-telemetry-finished" notification.
*/
add_task(function* test_memory_distribution() {
waitForExplicitFinish();
if (SpecialPowers.getIntPref("dom.ipc.processCount", 1) < 2) {
ok(true, "Skip this test if e10s-multi is disabled.");
finish();
return;
}
yield SpecialPowers.pushPrefEnv({set: [["toolkit.telemetry.enabled", true]]});
Services.telemetry.canRecordExtended = true;
let histogram = Services.telemetry.getKeyedHistogramById("MEMORY_DISTRIBUTION_AMONG_CONTENT");
histogram.clear();
let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, DUMMY_PAGE_DATA_URI);
let tab2 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, DUMMY_PAGE_DATA_URI);
let tab3 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, DUMMY_PAGE_DATA_URI);
let finishedGathering = new Promise(resolve => {
let obs = function () {
Services.obs.removeObserver(obs, "gather-memory-telemetry-finished");
resolve();
}
Services.obs.addObserver(obs, "gather-memory-telemetry-finished");
});
session.TelemetrySession.getPayload();
yield finishedGathering;
let s = histogram.snapshot();
ok("0 - 10 tabs" in s, "We should have some samples by now in this bucket.")
for (var key in s) {
is(key, "0 - 10 tabs");
let fewTabsSnapshot = s[key];
ok(fewTabsSnapshot.sum > 0, "Zero difference between all the content processes is unlikely, what happened?");
ok(fewTabsSnapshot.sum < 80, "20 percentage difference on average is unlikely, what happened?");
let c = fewTabsSnapshot.counts;
for (let i = 10; i < c.length; i++) {
// If this check fails it means that one of the content processes uses at least 20% more or 20% less than the mean.
is(c[i], 0, "All the buckets above 10 should be empty");
}
}
histogram.clear();
yield BrowserTestUtils.removeTab(tab3);
yield BrowserTestUtils.removeTab(tab2);
yield BrowserTestUtils.removeTab(tab1);
finish();
});

Просмотреть файл

@ -1212,6 +1212,16 @@
"n_buckets": 100,
"description": "Total Memory Across All Processes (KB)"
},
"MEMORY_DISTRIBUTION_AMONG_CONTENT": {
"alert_emails": ["memshrink-telemetry-alerts@mozilla.com"],
"bug_numbers": [1344174],
"expires_in_version": "never",
"kind": "linear",
"keyed": true,
"high": 200,
"n_buckets": 100,
"description": "Absolute difference of each content process' USS and the mean of USS's, normalized by the mean, in percentage. 100 means that the content process uses twice as much memory as the mean of the rest (or theoretically it could also mean that it uses 0 while the mean of the others are non 0.)"
},
"MEMORY_UNIQUE": {
"alert_emails": ["memshrink-telemetry-alerts@mozilla.com"],
"bug_numbers": [1198209],

Просмотреть файл

@ -710,6 +710,7 @@ var Impl = {
_childrenToHearFrom: null,
// monotonically-increasing id for USS reports
_nextTotalMemoryId: 1,
_USSFromChildProcesses: null,
_lastEnvironmentChangeDate: 0,
@ -1169,6 +1170,7 @@ var Impl = {
this._childrenToHearFrom.clear();
},
TOTAL_MEMORY_COLLECTOR_TIMEOUT);
this._USSFromChildProcesses = [];
this._childrenToHearFrom = new Set();
for (let i = 1; i < ppmm.childCount; i++) {
let child = ppmm.getChildAt(i);
@ -1193,7 +1195,7 @@ var Impl = {
histogram.add(new Date() - startTime);
},
handleMemoryReport(id, units, amount) {
handleMemoryReport(id, units, amount, key) {
let val;
if (units == Ci.nsIMemoryReporter.UNITS_BYTES) {
val = Math.floor(amount / 1024);
@ -1223,10 +1225,19 @@ var Impl = {
let h = this._histograms[id];
if (!h) {
if (key) {
h = Telemetry.getKeyedHistogramById(id);
} else {
h = Telemetry.getHistogramById(id);
}
this._histograms[id] = h;
}
if (key) {
h.add(key, val);
} else {
h.add(val);
}
},
getChildPayloads: function getChildPayloads() {
@ -1561,6 +1572,18 @@ var Impl = {
return this._delayedInitTask;
},
getOpenTabsCount: function getOpenTabsCount() {
let tabCount = 0;
let browserEnum = Services.wm.getEnumerator("navigator:browser");
while (browserEnum.hasMoreElements()) {
let win = browserEnum.getNext();
tabCount += win.gBrowser.tabs.length;
}
return tabCount;
},
/**
* Initializes telemetry for a content process.
*/
@ -1657,7 +1680,9 @@ var Impl = {
{
// In parent process, receive the USS report from the child
if (this._totalMemoryTimeout && this._childrenToHearFrom.delete(message.data.id)) {
this._totalMemory += message.data.bytes;
let uss = message.data.bytes;
this._totalMemory += uss;
this._USSFromChildProcesses.push(uss);
if (this._childrenToHearFrom.size == 0) {
clearTimeout(this._totalMemoryTimeout);
this._totalMemoryTimeout = undefined;
@ -1665,6 +1690,36 @@ var Impl = {
"MEMORY_TOTAL",
Ci.nsIMemoryReporter.UNITS_BYTES,
this._totalMemory);
let length = this._USSFromChildProcesses.length;
if (length > 1) {
// Mean of the USS of all the content processes.
let mean = this._USSFromChildProcesses.reduce((a, b) => a + b, 0) / length;
// Absolute error of USS for each content process, normalized by the mean (*100 to get it in percentage).
// 20% means for a content process that it is using 20% more or 20% less than the mean.
let diffs = this._USSFromChildProcesses.map(value => Math.floor(Math.abs(value - mean) * 100 / mean));
let tabsCount = this.getOpenTabsCount();
let key;
if (tabsCount < 11) {
key = "0 - 10 tabs";
} else if (tabsCount < 501) {
key = "11 - 500 tabs";
} else {
key = "more tabs";
}
diffs.forEach(value => {
this.handleMemoryReport(
"MEMORY_DISTRIBUTION_AMONG_CONTENT",
Ci.nsIMemoryReporter.UNITS_COUNT,
value,
key);
});
// This notification is for testing only.
Services.obs.notifyObservers(null, "gather-memory-telemetry-finished", null);
}
this._USSFromChildProcesses = undefined;
}
} else {
this._log.trace("Child USS report was missed");