diff --git a/toolkit/components/aboutmemory/content/aboutMemory.js b/toolkit/components/aboutmemory/content/aboutMemory.js index ffe4d0a31978..aa87e9d3672f 100644 --- a/toolkit/components/aboutmemory/content/aboutMemory.js +++ b/toolkit/components/aboutmemory/content/aboutMemory.js @@ -720,12 +720,23 @@ function getTreesByProcess(aProcessMemoryReports, aTreesByProcess, // "ghost-windows" multi-reporters all the time. (Note that reports from // these multi-reporters can reach here as single reports if they were in the // child process.) + // + // Also ignore the resident-fast reporter; we use the vanilla resident + // reporter because it's more important that we get accurate results than + // that we avoid the (small) possibility of a long pause when loading + // about:memory. + // + // We don't show both resident and resident-fast because running the resident + // reporter can purge pages on MacOS, which affects the results of the + // resident-fast reporter. We don't want about:memory's results to be + // affected by the order of memory reporter execution. function ignoreSingle(aUnsafePath) { return (isSmapsPath(aUnsafePath) && !gVerbose && !aForceShowSmaps) || aUnsafePath.startsWith("compartments/") || - aUnsafePath.startsWith("ghost-windows/"); + aUnsafePath.startsWith("ghost-windows/") || + aUnsafePath == "resident-fast"; } function ignoreMulti(aMRName) diff --git a/toolkit/components/telemetry/TelemetryPing.js b/toolkit/components/telemetry/TelemetryPing.js index a682ad8378b9..f99a39a048ed 100644 --- a/toolkit/components/telemetry/TelemetryPing.js +++ b/toolkit/components/telemetry/TelemetryPing.js @@ -56,7 +56,7 @@ const MEM_HISTOGRAMS = { "js-compartments/system": "MEMORY_JS_COMPARTMENTS_SYSTEM", "js-compartments/user": "MEMORY_JS_COMPARTMENTS_USER", "explicit": "MEMORY_EXPLICIT", - "resident": "MEMORY_RESIDENT", + "resident-fast": "MEMORY_RESIDENT", "vsize": "MEMORY_VSIZE", "storage-sqlite": "MEMORY_STORAGE_SQLITE", "images-content-used-uncompressed": diff --git a/xpcom/base/nsMemoryReporterManager.cpp b/xpcom/base/nsMemoryReporterManager.cpp index 8f5907f00dc2..c43016913beb 100644 --- a/xpcom/base/nsMemoryReporterManager.cpp +++ b/xpcom/base/nsMemoryReporterManager.cpp @@ -242,6 +242,11 @@ static nsresult GetResident(int64_t *n) return NS_OK; } +static nsresult GetResidentFast(int64_t *n) +{ + return GetResident(n); +} + #elif defined(XP_MACOSX) #include @@ -269,16 +274,17 @@ static nsresult GetVsize(int64_t *n) return NS_OK; } -static nsresult GetResident(int64_t *n) +// If we're using jemalloc on Mac, we need to instruct jemalloc to purge the +// pages it has madvise(MADV_FREE)'d before we read our RSS in order to get +// an accurate result. The OS will take away MADV_FREE'd pages when there's +// memory pressure, so ideally, they shouldn't count against our RSS. +// +// Purging these pages can take a long time for some users (see bug 789975), +// so we provide the option to get the RSS without purging first. +static nsresult GetResident(int64_t *n, bool aDoPurge) { #ifdef HAVE_JEMALLOC_STATS - // If we're using jemalloc on Mac, we need to instruct jemalloc to purge - // the pages it has madvise(MADV_FREE)'d before we read our RSS. The OS - // will take away MADV_FREE'd pages when there's memory pressure, so they - // shouldn't count against our RSS. - // - // Purging these pages shouldn't take more than 10ms or so, but we want to - // keep an eye on it since GetResident() is called on each Telemetry ping. + if (aDoPurge) { Telemetry::AutoTimer timer; jemalloc_purge_freed_pages(); @@ -293,6 +299,16 @@ static nsresult GetResident(int64_t *n) return NS_OK; } +static nsresult GetResidentFast(int64_t *n) +{ + return GetResident(n, /* doPurge = */ false); +} + +static nsresult GetResident(int64_t *n) +{ + return GetResident(n, /* doPurge = */ true); +} + #elif defined(XP_WIN) #include @@ -325,6 +341,11 @@ static nsresult GetResident(int64_t *n) return NS_OK; } +static nsresult GetResidentFast(int64_t *n) +{ + return GetResident(n); +} + #define HAVE_PRIVATE_REPORTER static nsresult GetPrivate(int64_t *n) { @@ -377,6 +398,18 @@ NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT(Resident, "but it depends both on other processes being run and details of the OS " "kernel and so is best used for comparing the memory usage of a single " "process at different points in time.") + +NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT(ResidentFast, + "resident-fast", + KIND_OTHER, + UNITS_BYTES, + GetResidentFast, + "This reporter measures the same value as the resident memory reporter, but " + "it tries to be as fast as possible, at the expense of accuracy. On most " + "platforms this is identical to the vanilla resident reporter, but on MacOS" + "in particular, this reporter may over-count our RSS. You should use " + "resident-fast where you care about latency of collection (e.g. in " + "telemetry). Otherwise you should use the regular resident reporter.") #endif // HAVE_VSIZE_AND_RESIDENT_REPORTERS #ifdef HAVE_PAGE_FAULT_REPORTERS @@ -665,6 +698,7 @@ nsMemoryReporterManager::Init() #ifdef HAVE_VSIZE_AND_RESIDENT_REPORTERS REGISTER(Vsize); REGISTER(Resident); + REGISTER(ResidentFast); #endif #ifdef HAVE_PAGE_FAULT_REPORTERS