зеркало из https://github.com/mozilla/pjs.git
Bug 689583 - Add names for memory multi-reporters. r=jlebar.
--HG-- extra : rebase_source : adb3fb2cbbb8a07b60edd48c7dc9a3a4a4763b79
This commit is contained in:
Родитель
5f0fe4ee5f
Коммит
a7a02724d9
|
@ -235,6 +235,13 @@ GetWindows(const PRUint64& aId, nsGlobalWindow*& aWindow, void* aClosure)
|
|||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMMemoryMultiReporter::GetName(nsACString &aName)
|
||||
{
|
||||
aName.AssignLiteral("dom+style");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMMemoryMultiReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
|
||||
nsISupports* aClosure)
|
||||
|
|
|
@ -228,6 +228,12 @@ public:
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD GetName(nsACString &aName)
|
||||
{
|
||||
aName.AssignLiteral("workers");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
CollectReports(nsIMemoryMultiReporterCallback* aCallback,
|
||||
nsISupports* aClosure)
|
||||
|
|
|
@ -1711,6 +1711,12 @@ class XPConnectJSCompartmentsMultiReporter : public nsIMemoryMultiReporter
|
|||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD GetName(nsACString &name)
|
||||
{
|
||||
name.AssignLiteral("js");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *callback,
|
||||
nsISupports *closure)
|
||||
{
|
||||
|
|
|
@ -690,6 +690,13 @@ PresShell::MemoryReporter::SizeEnumerator(PresShellPtrKey *aEntry,
|
|||
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(GfxTextrunWordCacheMallocSizeOf, "gfx/textrun-word-cache")
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresShell::MemoryReporter::GetName(nsACString &aName)
|
||||
{
|
||||
aName.AssignLiteral("layout");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresShell::MemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
|
||||
nsISupports* aClosure)
|
||||
|
|
|
@ -182,6 +182,12 @@ public:
|
|||
"associated with connections to this database.");
|
||||
}
|
||||
|
||||
NS_IMETHOD GetName(nsACString &aName)
|
||||
{
|
||||
aName.AssignLiteral("storage-sqlite");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Warning: To get a Connection's measurements requires holding its lock.
|
||||
// There may be a delay getting the lock if another thread is accessing the
|
||||
// Connection. This isn't very nice if CollectReports is called from the
|
||||
|
|
|
@ -121,7 +121,8 @@ const kTreeNames = {
|
|||
'other': 'Other Measurements'
|
||||
};
|
||||
|
||||
const kMapTreePaths = ['map/resident', 'map/pss', 'map/vsize', 'map/swap'];
|
||||
const kMapTreePaths =
|
||||
['smaps/resident', 'smaps/pss', 'smaps/vsize', 'smaps/swap'];
|
||||
|
||||
function onLoad()
|
||||
{
|
||||
|
@ -283,6 +284,11 @@ function getReportersByProcess(aMgr)
|
|||
var e = aMgr.enumerateMultiReporters();
|
||||
while (e.hasMoreElements()) {
|
||||
var mrOrig = e.getNext().QueryInterface(Ci.nsIMemoryMultiReporter);
|
||||
// Ignore the "smaps" reporters in non-verbose mode.
|
||||
if (!gVerbose && mrOrig.name === "smaps") {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
mrOrig.collectReports(addReporter, null);
|
||||
}
|
||||
|
@ -453,7 +459,7 @@ function buildTree(aReporters, aTreeName)
|
|||
// traversal.
|
||||
|
||||
// There should always be at least one matching reporter when |aTreeName| is
|
||||
// "explicit". But there may be zero for "map" trees; if that happens,
|
||||
// "explicit". But there may be zero for "smaps" trees; if that happens,
|
||||
// bail.
|
||||
var foundReporter = false;
|
||||
for (var unsafePath in aReporters) {
|
||||
|
@ -552,19 +558,17 @@ function buildTree(aReporters, aTreeName)
|
|||
}
|
||||
|
||||
/**
|
||||
* Ignore all the memory reporters that belong to a tree; this involves
|
||||
* Ignore all the memory reports that belong to a "smaps" tree; this involves
|
||||
* explicitly marking them as done.
|
||||
*
|
||||
* @param aReporters
|
||||
* The table of Reporters, indexed by _unsafePath.
|
||||
* @param aTreeName
|
||||
* The name of the tree being built.
|
||||
*/
|
||||
function ignoreTree(aReporters, aTreeName)
|
||||
function ignoreSmapsTrees(aReporters)
|
||||
{
|
||||
for (var unsafePath in aReporters) {
|
||||
var r = aReporters[unsafePath];
|
||||
if (r.treeNameMatches(aTreeName)) {
|
||||
if (r.treeNameMatches("smaps")) {
|
||||
var dummy = getBytes(aReporters, unsafePath);
|
||||
}
|
||||
}
|
||||
|
@ -785,21 +789,24 @@ function appendProcessElements(aP, aProcess, aReporters,
|
|||
appendTreeElements(aP, explicitTree, aProcess);
|
||||
|
||||
// We only show these breakdown trees in verbose mode.
|
||||
kMapTreePaths.forEach(function(t) {
|
||||
if (gVerbose) {
|
||||
if (gVerbose) {
|
||||
kMapTreePaths.forEach(function(t) {
|
||||
var tree = buildTree(aReporters, t);
|
||||
|
||||
// |tree| will be null if we don't have any reporters for the given
|
||||
// unsafePath.
|
||||
if (tree) {
|
||||
sortTreeAndInsertAggregateNodes(tree._amount, tree);
|
||||
tree._hideKids = true; // map trees are always initially collapsed
|
||||
tree._hideKids = true; // smaps trees are always initially collapsed
|
||||
appendTreeElements(aP, tree, aProcess);
|
||||
}
|
||||
} else {
|
||||
ignoreTree(aReporters, t);
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Although we skip the "smaps" multi-reporter in getReportersByProcess(),
|
||||
// we might get some smaps reports from a child process, and they must be
|
||||
// explicitly ignored.
|
||||
ignoreSmapsTrees(aReporters);
|
||||
}
|
||||
|
||||
// We have to call appendOtherElements after we process all the trees,
|
||||
// because it looks at all the reporters which aren't part of a tree.
|
||||
|
|
|
@ -92,7 +92,8 @@
|
|||
f2("", "other4", OTHER, COUNT_CUMULATIVE, 888)
|
||||
];
|
||||
var fakeMultiReporters = [
|
||||
{ collectReports: function(cbObj, closure) {
|
||||
{ name: "fake1",
|
||||
collectReports: function(cbObj, closure) {
|
||||
function f(p, k, u, a) { cbObj.callback("", p, k, u, a, "(desc)", closure); }
|
||||
f("explicit/c/d", NONHEAP, BYTES, 13 * MB),
|
||||
f("explicit/c/d", NONHEAP, BYTES, 10 * MB), // dup
|
||||
|
@ -105,7 +106,8 @@
|
|||
},
|
||||
explicitNonHeap: (100 + 13 + 10)*MB + (499 + 100)*KB
|
||||
},
|
||||
{ collectReports: function(cbObj, closure) {
|
||||
{ name: "fake2",
|
||||
collectReports: function(cbObj, closure) {
|
||||
function f(p, k, u, a) { cbObj.callback("", p, k, u, a, "(desc)", closure); }
|
||||
f("other3", OTHER, COUNT, 777);
|
||||
f("other2", OTHER, BYTES, 222 * MB);
|
||||
|
@ -114,16 +116,17 @@
|
|||
},
|
||||
explicitNonHeap: 0
|
||||
},
|
||||
{ collectReports: function(cbObj, closure) {
|
||||
{ name: "smaps",
|
||||
collectReports: function(cbObj, closure) {
|
||||
// The amounts are given in pages, so multiply here by 4kb.
|
||||
function f(p, a) { cbObj.callback("", p, NONHEAP, BYTES, a * 4 * KB, "(desc)", closure); }
|
||||
f("map/vsize/a", 24);
|
||||
f("map/swap/a", 1);
|
||||
f("map/swap/a", 2);
|
||||
f("map/vsize/a", 19);
|
||||
f("map/swap/b/c", 10);
|
||||
f("map/resident/a", 42);
|
||||
f("map/pss/a", 43);
|
||||
f("smaps/vsize/a", 24);
|
||||
f("smaps/swap/a", 1);
|
||||
f("smaps/swap/a", 2);
|
||||
f("smaps/vsize/a", 19);
|
||||
f("smaps/swap/b/c", 10);
|
||||
f("smaps/resident/a", 42);
|
||||
f("smaps/pss/a", 43);
|
||||
},
|
||||
explicitNonHeap: 0
|
||||
}
|
||||
|
@ -197,10 +200,28 @@
|
|||
f("5th", "explicit/a/neg1", NONHEAP, -20 * KB),
|
||||
f("5th", "explicit/a/neg2", NONHEAP, -10 * KB)
|
||||
];
|
||||
var fakeMultiReporters2 = [
|
||||
// Because this multi-reporter is in a child process, the fact that we
|
||||
// skip the "smaps" multi-reporter in the parent process won't cause
|
||||
// these to be skipped; the fall-back skipping will be hit instead.
|
||||
{ name: "smaps",
|
||||
collectReports: function(cbObj, closure) {
|
||||
// The amounts are given in pages, so multiply here by 4kb.
|
||||
function f(p, a) { cbObj.callback("2nd", p, NONHEAP, BYTES, a * 4 * KB, "(desc)", closure); }
|
||||
f("smaps/vsize/a", 24);
|
||||
f("smaps/vsize/b", 24);
|
||||
},
|
||||
explicitNonHeap: 0
|
||||
}
|
||||
];
|
||||
for (var i = 0; i < fakeReporters2.length; i++) {
|
||||
mgr.registerReporter(fakeReporters2[i]);
|
||||
}
|
||||
for (var i = 0; i < fakeMultiReporters2.length; i++) {
|
||||
mgr.registerMultiReporter(fakeMultiReporters2[i]);
|
||||
}
|
||||
fakeReporters = fakeReporters.concat(fakeReporters2);
|
||||
fakeMultiReporters = fakeMultiReporters.concat(fakeMultiReporters2);
|
||||
]]>
|
||||
</script>
|
||||
|
||||
|
@ -393,6 +414,9 @@ Explicit Allocations\n\
|
|||
├────209,715,200 B (20.00%) ── compartment(compartment-url)\n\
|
||||
└────105,906,176 B (10.10%) ── heap-unclassified\n\
|
||||
\n\
|
||||
Virtual Size Breakdown\n\
|
||||
196,608 B (100.0%) ++ vsize\n\
|
||||
\n\
|
||||
Other Measurements\n\
|
||||
698,351,616 B ── danger<script>window.alert(1)</script>\n\
|
||||
1,048,576,000 B ── heap-allocated\n\
|
||||
|
|
|
@ -123,7 +123,8 @@ void GetBasename(const nsCString &aPath, nsACString &aOut)
|
|||
}
|
||||
|
||||
// MapsReporter::CollectReports uses this stuct to keep track of whether it's
|
||||
// seen a mapping under 'map/resident', 'map/vsize', and 'map/swap'.
|
||||
// seen a mapping under 'smaps/resident', 'smaps/pss', 'smaps/vsize', and
|
||||
// 'smaps/swap'.
|
||||
struct CategoriesSeen {
|
||||
CategoriesSeen() :
|
||||
mSeenResident(false),
|
||||
|
@ -148,6 +149,12 @@ public:
|
|||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD GetName(nsACString &aName)
|
||||
{
|
||||
aName.AssignLiteral("smaps");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
CollectReports(nsIMemoryMultiReporterCallback *aCallback,
|
||||
nsISupports *aClosure);
|
||||
|
@ -221,16 +228,16 @@ MapsReporter::CollectReports(nsIMemoryMultiReporterCallback *aCallback,
|
|||
|
||||
fclose(f);
|
||||
|
||||
// For sure we should have created some node under 'map/resident' and
|
||||
// 'map/vsize'; otherwise we're probably not reading smaps correctly. If we
|
||||
// didn't create a node under 'map/swap', create one here so about:memory
|
||||
// knows to create an empty 'map/swap' tree. See also bug 682735.
|
||||
// For sure we should have created some node under 'smaps/resident' and
|
||||
// 'smaps/vsize'; otherwise we're probably not reading smaps correctly. If we
|
||||
// didn't create a node under 'smaps/swap', create one here so about:memory
|
||||
// knows to create an empty 'smaps/swap' tree. See also bug 682735.
|
||||
|
||||
NS_ASSERTION(categoriesSeen.mSeenVsize, "Didn't create a vsize node?");
|
||||
NS_ASSERTION(categoriesSeen.mSeenVsize, "Didn't create a resident node?");
|
||||
if (!categoriesSeen.mSeenSwap) {
|
||||
aCallback->Callback(NS_LITERAL_CSTRING(""),
|
||||
NS_LITERAL_CSTRING("map/swap/total"),
|
||||
NS_LITERAL_CSTRING("smaps/swap/total"),
|
||||
nsIMemoryReporter::KIND_NONHEAP,
|
||||
nsIMemoryReporter::UNITS_BYTES,
|
||||
0,
|
||||
|
@ -510,7 +517,7 @@ MapsReporter::ParseMapBody(
|
|||
}
|
||||
|
||||
nsCAutoString path;
|
||||
path.Append("map/");
|
||||
path.Append("smaps/");
|
||||
path.Append(category);
|
||||
path.Append("/");
|
||||
path.Append(aName);
|
||||
|
|
|
@ -216,6 +216,16 @@ interface nsIMemoryMultiReporterCallback : nsISupports
|
|||
[scriptable, uuid(61d498d5-b460-4398-a8ea-7f75208534b4)]
|
||||
interface nsIMemoryMultiReporter : nsISupports
|
||||
{
|
||||
/*
|
||||
* The name of the multi-reporter. Useful when only one multi-reporter
|
||||
* needs to be run. Must be unique; if multi-reporters share names it's
|
||||
* likely the wrong one will be called in certain circumstances.
|
||||
*/
|
||||
readonly attribute ACString name;
|
||||
|
||||
/*
|
||||
* Run the multi-reporter.
|
||||
*/
|
||||
void collectReports(in nsIMemoryMultiReporterCallback callback,
|
||||
in nsISupports closure);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче