Bug 913260 (part 2) - Tweak ghost window reporters. r=mccr8.

This commit is contained in:
Nicholas Nethercote 2013-09-18 19:01:29 -07:00
parent 12216d4f00
commit 0069cbfda7
2 changed files with 76 additions and 129 deletions

View File

@ -9,8 +9,10 @@
#include "nsGlobalWindow.h"
#include "nsIDocument.h"
#include "nsIEffectiveTLDService.h"
#include "mozilla/Services.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"
#include "nsNetCID.h"
#include "nsPrintfCString.h"
#include "XPCJSMemoryReporter.h"
@ -19,6 +21,8 @@
using namespace mozilla;
StaticRefPtr<nsWindowMemoryReporter> sWindowReporter;
nsWindowMemoryReporter::nsWindowMemoryReporter()
: mCheckForGhostWindowsCallbackPending(false)
{
@ -31,27 +35,22 @@ NS_IMPL_ISUPPORTS3(nsWindowMemoryReporter, nsIMemoryReporter, nsIObserver,
void
nsWindowMemoryReporter::Init()
{
// The memory reporter manager will own this object.
nsRefPtr<nsWindowMemoryReporter> windowReporter = new nsWindowMemoryReporter();
NS_RegisterMemoryReporter(windowReporter);
MOZ_ASSERT(!sWindowReporter);
sWindowReporter = new nsWindowMemoryReporter();
ClearOnShutdown(&sWindowReporter);
NS_RegisterMemoryReporter(sWindowReporter);
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
if (os) {
// DOM_WINDOW_DESTROYED_TOPIC announces what we call window "detachment",
// when a window's docshell is set to NULL.
os->AddObserver(windowReporter, DOM_WINDOW_DESTROYED_TOPIC,
os->AddObserver(sWindowReporter, DOM_WINDOW_DESTROYED_TOPIC,
/* weakRef = */ true);
os->AddObserver(windowReporter, "after-minimize-memory-usage",
os->AddObserver(sWindowReporter, "after-minimize-memory-usage",
/* weakRef = */ true);
}
nsRefPtr<GhostURLsReporter> ghostURLsReporter =
new GhostURLsReporter(windowReporter);
NS_RegisterMemoryReporter(ghostURLsReporter);
nsRefPtr<NumGhostsReporter> numGhostsReporter =
new NumGhostsReporter(windowReporter);
NS_RegisterMemoryReporter(numGhostsReporter);
NS_RegisterMemoryReporter(new GhostWindowsReporter());
}
static already_AddRefed<nsIURI>
@ -311,6 +310,52 @@ GetWindows(const uint64_t& aId, nsGlobalWindow*& aWindow, void* aClosure)
return PL_DHASH_NEXT;
}
struct ReportGhostWindowsEnumeratorData
{
nsIMemoryReporterCallback* callback;
nsISupports* closure;
nsresult rv;
};
static PLDHashOperator
ReportGhostWindowsEnumerator(nsUint64HashKey* aIDHashKey, void* aClosure)
{
ReportGhostWindowsEnumeratorData *data =
static_cast<ReportGhostWindowsEnumeratorData*>(aClosure);
nsGlobalWindow::WindowByIdTable* windowsById =
nsGlobalWindow::GetWindowsTable();
if (!windowsById) {
NS_WARNING("Couldn't get window-by-id hashtable?");
return PL_DHASH_NEXT;
}
nsGlobalWindow* window = windowsById->Get(aIDHashKey->GetKey());
if (!window) {
NS_WARNING("Could not look up window?");
return PL_DHASH_NEXT;
}
nsAutoCString path;
path.AppendLiteral("ghost-windows/");
AppendWindowURI(window, path);
nsresult rv = data->callback->Callback(
/* process = */ EmptyCString(),
path,
nsIMemoryReporter::KIND_OTHER,
nsIMemoryReporter::UNITS_COUNT,
/* amount = */ 1,
/* description = */ NS_LITERAL_CSTRING("A ghost window."),
data->closure);
if (NS_FAILED(rv) && NS_SUCCEEDED(data->rv)) {
data->rv = rv;
}
return PL_DHASH_NEXT;
}
NS_IMETHODIMP
nsWindowMemoryReporter::GetName(nsACString &aName)
{
@ -331,12 +376,18 @@ nsWindowMemoryReporter::CollectReports(nsIMemoryReporterCallback* aCb,
WindowArray windows;
windowsById->Enumerate(GetWindows, &windows);
// Get the IDs of all the "ghost" windows.
// Get the IDs of all the "ghost" windows, and call aCb->Callback() for each
// one.
nsTHashtable<nsUint64HashKey> ghostWindows;
CheckForGhostWindows(&ghostWindows);
ReportGhostWindowsEnumeratorData reportGhostWindowsEnumData =
{ aCb, aClosure, NS_OK };
ghostWindows.EnumerateEntries(ReportGhostWindowsEnumerator,
&reportGhostWindowsEnumData);
nsresult rv = reportGhostWindowsEnumData.rv;
NS_ENSURE_SUCCESS(rv, rv);
WindowPaths windowPaths;
WindowPaths topWindowPaths;
// Collect window memory usage.
@ -344,17 +395,17 @@ nsWindowMemoryReporter::CollectReports(nsIMemoryReporterCallback* aCb,
nsCOMPtr<amIAddonManager> addonManager =
do_GetService("@mozilla.org/addons/integration;1");
for (uint32_t i = 0; i < windows.Length(); i++) {
nsresult rv = CollectWindowReports(windows[i], addonManager,
&windowTotalSizes, &ghostWindows,
&windowPaths, &topWindowPaths, aCb,
aClosure);
rv = CollectWindowReports(windows[i], addonManager,
&windowTotalSizes, &ghostWindows,
&windowPaths, &topWindowPaths, aCb,
aClosure);
NS_ENSURE_SUCCESS(rv, rv);
}
// Report JS memory usage. We do this from here because the JS memory
// reporter needs to be passed |windowPaths|.
nsresult rv = xpc::JSReporter::CollectReports(&windowPaths, &topWindowPaths,
aCb, aClosure);
rv = xpc::JSReporter::CollectReports(&windowPaths, &topWindowPaths,
aCb, aClosure);
NS_ENSURE_SUCCESS(rv, rv);
#define REPORT(_path, _amount, _desc) \
@ -662,94 +713,10 @@ nsWindowMemoryReporter::CheckForGhostWindows(
&ghostEnumData);
}
NS_IMPL_ISUPPORTS1(nsWindowMemoryReporter::GhostURLsReporter,
nsIMemoryReporter)
nsWindowMemoryReporter::
GhostURLsReporter::GhostURLsReporter(
nsWindowMemoryReporter* aWindowReporter)
: mWindowReporter(aWindowReporter)
{
}
NS_IMETHODIMP
nsWindowMemoryReporter::
GhostURLsReporter::GetName(nsACString& aName)
{
aName.AssignLiteral("ghost-windows-multi");
return NS_OK;
}
struct ReportGhostWindowsEnumeratorData
{
nsIMemoryReporterCallback* callback;
nsISupports* closure;
nsresult rv;
};
static PLDHashOperator
ReportGhostWindowsEnumerator(nsUint64HashKey* aIDHashKey, void* aClosure)
{
ReportGhostWindowsEnumeratorData *data =
static_cast<ReportGhostWindowsEnumeratorData*>(aClosure);
nsGlobalWindow::WindowByIdTable* windowsById =
nsGlobalWindow::GetWindowsTable();
if (!windowsById) {
NS_WARNING("Couldn't get window-by-id hashtable?");
return PL_DHASH_NEXT;
}
nsGlobalWindow* window = windowsById->Get(aIDHashKey->GetKey());
if (!window) {
NS_WARNING("Could not look up window?");
return PL_DHASH_NEXT;
}
nsAutoCString path;
path.AppendLiteral("ghost-windows/");
AppendWindowURI(window, path);
nsresult rv = data->callback->Callback(
/* process = */ EmptyCString(),
path,
nsIMemoryReporter::KIND_OTHER,
nsIMemoryReporter::UNITS_COUNT,
/* amount = */ 1,
/* description = */ NS_LITERAL_CSTRING("A ghost window."),
data->closure);
if (NS_FAILED(rv) && NS_SUCCEEDED(data->rv)) {
data->rv = rv;
}
return PL_DHASH_NEXT;
}
NS_IMETHODIMP
nsWindowMemoryReporter::
GhostURLsReporter::CollectReports(
nsIMemoryReporterCallback* aCb,
nsISupports* aClosure)
{
// Get the IDs of all the ghost windows in existance.
nsTHashtable<nsUint64HashKey> ghostWindows;
mWindowReporter->CheckForGhostWindows(&ghostWindows);
ReportGhostWindowsEnumeratorData reportGhostWindowsEnumData =
{ aCb, aClosure, NS_OK };
// Call aCb->Callback() for each ghost window.
ghostWindows.EnumerateEntries(ReportGhostWindowsEnumerator,
&reportGhostWindowsEnumData);
return reportGhostWindowsEnumData.rv;
}
int64_t
nsWindowMemoryReporter::NumGhostsReporter::Amount()
nsWindowMemoryReporter::GhostWindowsReporter::Amount()
{
nsTHashtable<nsUint64HashKey> ghostWindows;
mWindowReporter->CheckForGhostWindows(&ghostWindows);
sWindowReporter->CheckForGhostWindows(&ghostWindows);
return ghostWindows.Count();
}

View File

@ -120,31 +120,14 @@ public:
static void Init();
private:
/**
* GhostURLsReporter generates the list of all ghost windows' URLs. If
* you're only interested in this list, running this report is faster than
* running nsWindowMemoryReporter.
*/
class GhostURLsReporter MOZ_FINAL : public nsIMemoryReporter
{
public:
GhostURLsReporter(nsWindowMemoryReporter* aWindowReporter);
NS_DECL_ISUPPORTS
NS_DECL_NSIMEMORYREPORTER
private:
nsRefPtr<nsWindowMemoryReporter> mWindowReporter;
};
/**
* nsGhostWindowReporter generates the "ghost-windows" report, which counts
* the number of ghost windows present.
*/
class NumGhostsReporter MOZ_FINAL : public mozilla::MemoryUniReporter
class GhostWindowsReporter MOZ_FINAL : public mozilla::MemoryUniReporter
{
public:
NumGhostsReporter(nsWindowMemoryReporter* aWindowReporter)
GhostWindowsReporter()
: MemoryUniReporter("ghost-windows", KIND_OTHER, UNITS_COUNT,
"The number of ghost windows present (the number of nodes underneath "
"explicit/window-objects/top(none)/ghost, modulo race conditions). A ghost "
@ -154,13 +137,10 @@ private:
"about:memory's minimize memory usage button.\n\n"
"Ghost windows can happen legitimately, but they are often indicative of "
"leaks in the browser or add-ons.")
, mWindowReporter(aWindowReporter)
{}
private:
int64_t Amount() MOZ_OVERRIDE;
nsRefPtr<nsWindowMemoryReporter> mWindowReporter;
};
// Protect ctor, use Init() instead.