Bug 713799 - Rearrange the "window-objects" sub-tree in about:memory to make per-tab memory usage more obvious. r=jst.

--HG--
extra : rebase_source : f4e9407ad9a5c20ae8523d2ec087b4ee99c43877
This commit is contained in:
Nicholas Nethercote 2012-03-12 23:00:18 -07:00
Родитель f564b11cf6
Коммит feb306dd5d
2 изменённых файлов: 69 добавлений и 99 удалений

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

@ -53,7 +53,7 @@ nsWindowMemoryReporter::Init()
NS_RegisterMemoryMultiReporter(new nsWindowMemoryReporter());
}
static bool
static void
AppendWindowURI(nsGlobalWindow *aWindow, nsACString& aStr)
{
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aWindow->GetExtantDocument());
@ -71,21 +71,19 @@ AppendWindowURI(nsGlobalWindow *aWindow, nsACString& aStr)
}
}
if (!uri) {
return false;
if (uri) {
nsCString spec;
uri->GetSpec(spec);
// A hack: replace forward slashes with '\\' so they aren't
// treated as path separators. Users of the reporters
// (such as about:memory) have to undo this change.
spec.ReplaceChar('/', '\\');
aStr += spec;
} else {
aStr += NS_LITERAL_CSTRING("[system]");
}
nsCString spec;
uri->GetSpec(spec);
// A hack: replace forward slashes with '\\' so they aren't
// treated as path separators. Users of the reporters
// (such as about:memory) have to undo this change.
spec.ReplaceChar('/', '\\');
aStr += spec;
return true;
}
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMStyleMallocSizeOf, "windows")
@ -104,99 +102,68 @@ CollectWindowReports(nsGlobalWindow *aWindow,
// cached) yet held alive by either a website or our code. The
// latter case may be a memory leak, but not necessarily.
//
// For inner windows we show how much memory the window and its
// document etc use, and we report those per URI, where the URI is
// the document URI, if available, or the codebase of the principal
// in the window. In the case where we're unable to find a URI we're
// dealing with a chrome window with no document in it (or
// somesuch), and for that we make the URI be the string "[system]".
// For each window we show how much memory the window and its
// document, etc, use, and we report those per URI, where the URI is
// the document URI, if available, or the codebase of the principal in
// the window. In the case where we're unable to find a URI we're
// dealing with a chrome window with no document in it (or somesuch),
// and for that we make the URI be the string "[system]".
//
// For outer windows we simply group them all together and just show
// the combined count and amount of memory used, which is generally
// a constant amount per window (since all the actual data lives in
// the inner window).
// Outer windows are lumped in with inner windows, because the amount
// of memory used by outer windows is small.
//
// The path we give to the reporter callback for inner windows are
// as follows:
// The path we give to the reporter callback for "active" and "cached"
// windows (both inner and outer) is as follows:
//
// explicit/window-objects/<category>/top=<top-outer-id> (inner=<top-inner-id>)/inner-window(id=<id>, uri=<uri>)
// explicit/window-objects/top(<top-outer-uri>, id=<top-outer-id>)/<category>/window(<window-uri>)/...
//
// The path we give for "other" windows is as follows:
//
// explicit/window-objects/top(none)/window(<window-uri>)/...
//
// Where:
// - <category> is active, cached, or other, as described above.
// - <category> is "active" or "cached", as described above.
// - <top-outer-id> is the window id (nsPIDOMWindow::WindowID()) of
// the top outer window (i.e. tab, or top level chrome window).
// - <top-inner-id> is the window id of the top window's inner
// window.
// - <id> is the window id of the inner window in question.
// - <uri> is the URI per above description.
// - <top-inner-uri> is the URI of the top outer window. Excepting
// special windows (such as browser.xul or hiddenWindow.html) it's
// what the address bar shows for the tab.
// - <window-uri> is the URI of aWindow.
//
// Exposing the window ids is done to get logical grouping in
// about:memory, and also for debuggability since one can get to the
// nsGlobalWindow for a window id by calling the static method
// nsGlobalWindow::GetInnerWindowWithId(id) (or
// GetOuterWindowWithId(id) in a debugger.
//
// For outer windows we simply use:
//
// explicit/window-objects/<category>/outer-windows
//
// Which gives us simple counts of how many outer windows (and their
// combined sizes) per category.
// Exposing the top-outer-id ensures that each tab gets its own
// sub-tree, even if multiple tabs are showing the same URI.
nsCAutoString windowPath("explicit/window-objects/");
nsIDocShell *docShell = aWindow->GetDocShell();
nsGlobalWindow *top = aWindow->GetTop();
nsWindowSizes windowSizes(DOMStyleMallocSizeOf);
aWindow->SizeOfIncludingThis(&windowSizes);
if (docShell && aWindow->IsFrozen()) {
windowPath += NS_LITERAL_CSTRING("cached/");
} else if (docShell) {
windowPath += NS_LITERAL_CSTRING("active/");
windowPath += NS_LITERAL_CSTRING("top(");
if (top) {
AppendWindowURI(top, windowPath);
windowPath += NS_LITERAL_CSTRING(", id=");
windowPath.AppendInt(top->WindowID());
} else {
windowPath += NS_LITERAL_CSTRING("other/");
windowPath += NS_LITERAL_CSTRING("none");
}
windowPath += NS_LITERAL_CSTRING(")/");
nsIDocShell *docShell = aWindow->GetDocShell();
if (docShell) {
MOZ_ASSERT(top, "'cached' or 'active' window lacks a top window");
windowPath += aWindow->IsFrozen() ? NS_LITERAL_CSTRING("cached/")
: NS_LITERAL_CSTRING("active/");
} else {
MOZ_ASSERT(!top, "'other' window has a top window");
}
if (aWindow->IsInnerWindow()) {
windowPath += NS_LITERAL_CSTRING("top=");
windowPath += NS_LITERAL_CSTRING("window(");
AppendWindowURI(aWindow, windowPath);
windowPath += NS_LITERAL_CSTRING(")");
if (top) {
windowPath.AppendInt(top->WindowID());
nsGlobalWindow *topInner = top->GetCurrentInnerWindowInternal();
if (topInner) {
windowPath += NS_LITERAL_CSTRING(" (inner=");
windowPath.AppendInt(topInner->WindowID());
windowPath += NS_LITERAL_CSTRING(")");
}
} else {
windowPath += NS_LITERAL_CSTRING("none");
}
windowPath += NS_LITERAL_CSTRING("/inner-window(id=");
windowPath.AppendInt(aWindow->WindowID());
windowPath += NS_LITERAL_CSTRING(", uri=");
if (!AppendWindowURI(aWindow, windowPath)) {
windowPath += NS_LITERAL_CSTRING("[system]");
}
windowPath += NS_LITERAL_CSTRING(")");
} else {
// Combine all outer windows per section (active/cached/other) as
// they basically never contain anything of interest, and are
// always pretty much the same size.
windowPath += NS_LITERAL_CSTRING("outer-windows");
}
#define REPORT(_path1, _path2, _amount, _desc) \
#define REPORT(_pathTail, _amount, _desc) \
do { \
if (_amount > 0) { \
nsCAutoString path(_path1); \
path += _path2; \
nsCAutoString path(windowPath); \
path += _pathTail; \
nsresult rv; \
rv = aCb->Callback(EmptyCString(), path, nsIMemoryReporter::KIND_HEAP,\
nsIMemoryReporter::UNITS_BYTES, _amount, \
@ -205,24 +172,27 @@ CollectWindowReports(nsGlobalWindow *aWindow,
} \
} while (0)
REPORT(windowPath, "/dom", windowSizes.mDOM,
nsWindowSizes windowSizes(DOMStyleMallocSizeOf);
aWindow->SizeOfIncludingThis(&windowSizes);
REPORT("/dom", windowSizes.mDOM,
"Memory used by a window and the DOM within it.");
aWindowTotalSizes->mDOM += windowSizes.mDOM;
REPORT(windowPath, "/style-sheets", windowSizes.mStyleSheets,
REPORT("/style-sheets", windowSizes.mStyleSheets,
"Memory used by style sheets within a window.");
aWindowTotalSizes->mStyleSheets += windowSizes.mStyleSheets;
REPORT(windowPath, "/layout/arenas", windowSizes.mLayoutArenas,
REPORT("/layout/arenas", windowSizes.mLayoutArenas,
"Memory used by layout PresShell, PresContext, and other related "
"areas within a window.");
aWindowTotalSizes->mLayoutArenas += windowSizes.mLayoutArenas;
REPORT(windowPath, "/layout/style-sets", windowSizes.mLayoutStyleSets,
REPORT("/layout/style-sets", windowSizes.mLayoutStyleSets,
"Memory used by style sets within a window.");
aWindowTotalSizes->mLayoutStyleSets += windowSizes.mLayoutStyleSets;
REPORT(windowPath, "/layout/text-runs", windowSizes.mLayoutTextRuns,
REPORT("/layout/text-runs", windowSizes.mLayoutTextRuns,
"Memory used for text-runs (glyph layout) in the PresShell's frame "
"tree, within a window.");
aWindowTotalSizes->mLayoutTextRuns += windowSizes.mLayoutTextRuns;

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

@ -44,7 +44,7 @@
let areJsCompartmentsPresent = false;
let isSandboxLocationShown = false;
let areInnerWindowsPresent = false;
let areWindowObjectsPresent = false;
let isPlacesPresent = false;
let isImagesPresent = false;
let isXptiWorkingSetPresent = false;
@ -72,8 +72,8 @@
// Check the presence of some other notable reporters.
} else if (aPath.search(/^explicit\/js\/compartment\(/) >= 0) {
areJsCompartmentsPresent = true;
} else if (aPath.search(/^explicit\/window-objects\/.*inner-window\(/) >= 0) {
areInnerWindowsPresent = true;
} else if (aPath.search(/^explicit\/window-objects\/top\(/) >= 0) {
areWindowObjectsPresent = true;
} else if (aPath.search(/^explicit\/storage\/sqlite\/places.sqlite/) >= 0) {
isPlacesPresent = true;
} else if (aPath.search(/^explicit\/images/) >= 0) {
@ -131,7 +131,7 @@
ok(areJsCompartmentsPresent, "js compartments are present");
ok(isSandboxLocationShown, "sandbox locations are present");
ok(areInnerWindowsPresent, "inner-windows are present");
ok(areWindowObjectsPresent, "window objects are present");
ok(isPlacesPresent, "places is present");
ok(isImagesPresent, "images is present");
ok(isXptiWorkingSetPresent, "xpti-working-set is present");