From c2a6dd877346b4188aa5741fdb1e189230360c0c Mon Sep 17 00:00:00 2001 From: Justin Lebar Date: Mon, 2 Apr 2012 22:28:13 -0400 Subject: [PATCH] Bug 737857 - Report number of ghost windows in telemetry. r=njn --HG-- extra : rebase_source : 0139099de839f77405ec1e606fc0540fc892cbd5 --- dom/base/nsWindowMemoryReporter.cpp | 95 +++++++++++++++++-- dom/base/nsWindowMemoryReporter.h | 27 +++++- .../aboutmemory/content/aboutMemory.js | 6 +- .../telemetry/TelemetryHistograms.h | 1 + toolkit/components/telemetry/TelemetryPing.js | 3 +- 5 files changed, 114 insertions(+), 18 deletions(-) diff --git a/dom/base/nsWindowMemoryReporter.cpp b/dom/base/nsWindowMemoryReporter.cpp index 4669c3f1f2bd..249add49e55c 100644 --- a/dom/base/nsWindowMemoryReporter.cpp +++ b/dom/base/nsWindowMemoryReporter.cpp @@ -72,9 +72,13 @@ nsWindowMemoryReporter::Init() /* weakRef = */ true); } - nsGhostWindowMemoryReporter *ghostReporter = - new nsGhostWindowMemoryReporter(windowReporter); - NS_RegisterMemoryMultiReporter(ghostReporter); + GhostURLsReporter *ghostMultiReporter = + new GhostURLsReporter(windowReporter); + NS_RegisterMemoryMultiReporter(ghostMultiReporter); + + NumGhostsReporter *ghostReporter = + new NumGhostsReporter(windowReporter); + NS_RegisterMemoryReporter(ghostReporter); } static already_AddRefed @@ -535,11 +539,11 @@ nsWindowMemoryReporter::CheckForGhostWindows( &ghostEnumData); } -NS_IMPL_ISUPPORTS1(nsWindowMemoryReporter::nsGhostWindowMemoryReporter, +NS_IMPL_ISUPPORTS1(nsWindowMemoryReporter::GhostURLsReporter, nsIMemoryMultiReporter) nsWindowMemoryReporter:: -nsGhostWindowMemoryReporter::nsGhostWindowMemoryReporter( +GhostURLsReporter::GhostURLsReporter( nsWindowMemoryReporter* aWindowReporter) : mWindowReporter(aWindowReporter) { @@ -547,7 +551,7 @@ nsGhostWindowMemoryReporter::nsGhostWindowMemoryReporter( NS_IMETHODIMP nsWindowMemoryReporter:: -nsGhostWindowMemoryReporter::GetName(nsACString& aName) +GhostURLsReporter::GetName(nsACString& aName) { aName.AssignLiteral("ghost-windows"); return NS_OK; @@ -555,7 +559,7 @@ nsGhostWindowMemoryReporter::GetName(nsACString& aName) NS_IMETHODIMP nsWindowMemoryReporter:: -nsGhostWindowMemoryReporter::GetExplicitNonHeap(PRInt64* aOut) +GhostURLsReporter::GetExplicitNonHeap(PRInt64* aOut) { *aOut = 0; return NS_OK; @@ -609,8 +613,9 @@ ReportGhostWindowsEnumerator(nsUint64HashKey* aIDHashKey, void* aClosure) NS_IMETHODIMP nsWindowMemoryReporter:: -nsGhostWindowMemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb, - nsISupports* aClosure) +GhostURLsReporter::CollectReports( + nsIMemoryMultiReporterCallback* aCb, + nsISupports* aClosure) { // Get the IDs of all the ghost windows in existance. nsTHashtable ghostWindows; @@ -626,3 +631,75 @@ nsGhostWindowMemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb, return reportGhostWindowsEnumData.rv; } + +NS_IMPL_ISUPPORTS1(nsWindowMemoryReporter::NumGhostsReporter, + nsIMemoryReporter) + +nsWindowMemoryReporter:: +NumGhostsReporter::NumGhostsReporter( + nsWindowMemoryReporter *aWindowReporter) + : mWindowReporter(aWindowReporter) +{} + +NS_IMETHODIMP +nsWindowMemoryReporter:: +NumGhostsReporter::GetProcess(nsACString& aProcess) +{ + aProcess.AssignLiteral(""); + return NS_OK; +} + +NS_IMETHODIMP +nsWindowMemoryReporter:: +NumGhostsReporter::GetPath(nsACString& aPath) +{ + aPath.AssignLiteral("ghost-windows"); + return NS_OK; +} + +NS_IMETHODIMP +nsWindowMemoryReporter:: +NumGhostsReporter::GetKind(PRInt32* aKind) +{ + *aKind = KIND_OTHER; + return NS_OK; +} + +NS_IMETHODIMP +nsWindowMemoryReporter:: +NumGhostsReporter::GetUnits(PRInt32* aUnits) +{ + *aUnits = nsIMemoryReporter::UNITS_COUNT; + return NS_OK; +} + +NS_IMETHODIMP +nsWindowMemoryReporter:: +NumGhostsReporter::GetDescription(nsACString& aDesc) +{ + nsPrintfCString str(1024, +"The number of ghost windows present (the number of nodes underneath \ +explicit/window-objects/top(none)/ghost, modulo race conditions). A ghost \ +window is not shown in any tab, does not share a domain with any non-detached \ +windows, and has met these criteria for at least %ds \ +(memory.ghost_window_timeout_seconds) or has survived a round of 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->GetGhostTimeout()); + + aDesc.Assign(str); + return NS_OK; +} + +NS_IMETHODIMP +nsWindowMemoryReporter:: +NumGhostsReporter::GetAmount(PRInt64* aAmount) +{ + nsTHashtable ghostWindows; + ghostWindows.Init(); + mWindowReporter->CheckForGhostWindows(&ghostWindows); + + *aAmount = ghostWindows.Count(); + return NS_OK; +} diff --git a/dom/base/nsWindowMemoryReporter.h b/dom/base/nsWindowMemoryReporter.h index fc90fb15e433..b0c7e0b420ee 100644 --- a/dom/base/nsWindowMemoryReporter.h +++ b/dom/base/nsWindowMemoryReporter.h @@ -141,14 +141,15 @@ public: private: /** - * nsGhostWindowMemoryReporter generates the "ghost-windows" memory report. - * If you're only interested in the list of ghost windows, running this - * report is faster than running nsWindowMemoryReporter. + * GhostURLsReporter generates the "ghost-windows" multi-report, which + * includes a list of all ghost windows' URLs. If you're only interested in + * this list, running this report is faster than running + * nsWindowMemoryReporter. */ - class nsGhostWindowMemoryReporter: public nsIMemoryMultiReporter + class GhostURLsReporter: public nsIMemoryMultiReporter { public: - nsGhostWindowMemoryReporter(nsWindowMemoryReporter* aWindowReporter); + GhostURLsReporter(nsWindowMemoryReporter* aWindowReporter); NS_DECL_ISUPPORTS NS_DECL_NSIMEMORYMULTIREPORTER @@ -157,6 +158,22 @@ private: nsRefPtr mWindowReporter; }; + /** + * nsGhostWindowReporter generates the "ghost-windows" single-report, which + * counts the number of ghost windows present. + */ + class NumGhostsReporter: public nsIMemoryReporter + { + public: + NumGhostsReporter(nsWindowMemoryReporter* aWindowReporter); + + NS_DECL_ISUPPORTS + NS_DECL_NSIMEMORYREPORTER + + private: + nsRefPtr mWindowReporter; + }; + // Protect ctor, use Init() instead. nsWindowMemoryReporter(); diff --git a/toolkit/components/aboutmemory/content/aboutMemory.js b/toolkit/components/aboutmemory/content/aboutMemory.js index 01e99bf95603..1acb8e384e79 100644 --- a/toolkit/components/aboutmemory/content/aboutMemory.js +++ b/toolkit/components/aboutmemory/content/aboutMemory.js @@ -263,7 +263,7 @@ function processMemoryReporters(aMgr, aIgnoreSingle, aIgnoreMulti, // This regexp matches sentences and sentence fragments, i.e. strings that // start with a capital letter and ends with a '.'. (The final sentence may be // in parentheses, so a ')' might appear after the '.'.) -const gSentenceRegExp = /^[A-Z].*\.\)?$/; +const gSentenceRegExp = /^[A-Z].*\.\)?$/m; function checkReport(aUnsafePath, aKind, aUnits, aAmount, aDescription) { @@ -287,7 +287,7 @@ function checkReport(aUnsafePath, aKind, aUnits, aAmount, aDescription) assert(aUnsafePath.indexOf("/") === -1, "'other' path contains '/'"); assert(aKind === KIND_OTHER, "bad other kind: " + aUnsafePath); assert(aDescription.match(gSentenceRegExp), - "non-sentence other description"); + "non-sentence other description " + aDescription); } } @@ -1699,7 +1699,7 @@ function getGhostWindowsByProcess(aMgr) aDescription) { let unsafeSplit = aUnsafePath.split('/'); - assert(unsafeSplit[0] == 'ghost-windows/', + assert(unsafeSplit[0] == 'ghost-windows', 'Unexpected path in getGhostWindowsByProcess: ' + aUnsafePath); let unsafeURL = unsafeSplit[1]; diff --git a/toolkit/components/telemetry/TelemetryHistograms.h b/toolkit/components/telemetry/TelemetryHistograms.h index 0d9856e2b38d..be7cf305bc2c 100644 --- a/toolkit/components/telemetry/TelemetryHistograms.h +++ b/toolkit/components/telemetry/TelemetryHistograms.h @@ -102,6 +102,7 @@ HISTOGRAM(MEMORY_STORAGE_SQLITE, 1024, 512 * 1024, 50, EXPONENTIAL, "Memory used HISTOGRAM(MEMORY_IMAGES_CONTENT_USED_UNCOMPRESSED, 1024, 1024 * 1024, 50, EXPONENTIAL, "Memory used for uncompressed, in-use content images (KB)") HISTOGRAM(MEMORY_HEAP_ALLOCATED, 1024, 1024 * 1024, 50, EXPONENTIAL, "Heap memory allocated (KB)") HISTOGRAM(MEMORY_EXPLICIT, 1024, 1024 * 1024, 50, EXPONENTIAL, "Explicit memory allocations (KB)") +HISTOGRAM(GHOST_WINDOWS, 1, 128, 8, EXPONENTIAL, "Number of ghost windows") #if defined(XP_MACOSX) HISTOGRAM(MEMORY_FREE_PURGED_PAGES_MS, 1, 1024, 10, EXPONENTIAL, "Time(ms) to purge MADV_FREE'd heap pages.") #elif defined(XP_WIN) diff --git a/toolkit/components/telemetry/TelemetryPing.js b/toolkit/components/telemetry/TelemetryPing.js index 2d410fd2f842..c06d4294cd2e 100644 --- a/toolkit/components/telemetry/TelemetryPing.js +++ b/toolkit/components/telemetry/TelemetryPing.js @@ -68,7 +68,8 @@ const MEM_HISTOGRAMS = { "page-faults-hard": "PAGE_FAULTS_HARD", "low-memory-events-virtual": "LOW_MEMORY_EVENTS_VIRTUAL", "low-memory-events-commit-space": "LOW_MEMORY_EVENTS_COMMIT_SPACE", - "low-memory-events-physical": "LOW_MEMORY_EVENTS_PHYSICAL" + "low-memory-events-physical": "LOW_MEMORY_EVENTS_PHYSICAL", + "ghost-windows": "GHOST_WINDOWS" }; // Seconds of idle time before pinging. // On idle-daily a gather-telemetry notification is fired, during it probes can