From 6007d234f5c54642d48758e7a01429205377b630 Mon Sep 17 00:00:00 2001 From: Justin Lebar Date: Sun, 23 Dec 2012 21:48:03 -0500 Subject: [PATCH] Bug 824395 - Report used stacks separately from unused stacks. r=njn --- memory/replace/dmd/DMD.cpp | 56 ++++++++++++++++++++++---- memory/replace/dmd/DMD.h | 3 +- xpcom/base/nsMemoryReporterManager.cpp | 14 +++++-- 3 files changed, 60 insertions(+), 13 deletions(-) diff --git a/memory/replace/dmd/DMD.cpp b/memory/replace/dmd/DMD.cpp index c84bcecb52a..24342660033 100644 --- a/memory/replace/dmd/DMD.cpp +++ b/memory/replace/dmd/DMD.cpp @@ -1859,20 +1859,43 @@ PrintSortedTraceAndFrameRecords(const Writer& aWriter, // |nsMallocSizeOfFun| argument. That's because those arguments are primarily // to aid DMD track heap blocks... but DMD deliberately doesn't track heap // blocks it allocated for itself! -MOZ_EXPORT void -SizeOf(Sizes* aSizes) +// +// SizeOfInternal should be called while you're holding the state lock and while +// intercepts are blocked; SizeOf acquires the lock and blocks intercepts. + +static void +SizeOfInternal(Sizes* aSizes) { + MOZ_ASSERT(gStateLock->IsLocked()); + MOZ_ASSERT(Thread::Fetch()->InterceptsAreBlocked()); + + aSizes->Clear(); + if (!gIsDMDRunning) { - aSizes->Clear(); return; } - aSizes->mStackTraces = 0; + js::HashSet, + InfallibleAllocPolicy> usedStackTraces; + usedStackTraces.init(1024); + + for(BlockTable::Range r = gBlockTable->all(); !r.empty(); r.popFront()) { + const Block& b = r.front(); + usedStackTraces.put(b.AllocStackTrace()); + usedStackTraces.put(b.ReportStackTrace1()); + usedStackTraces.put(b.ReportStackTrace2()); + } + for (StackTraceTable::Range r = gStackTraceTable->all(); !r.empty(); r.popFront()) { StackTrace* const& st = r.front(); - aSizes->mStackTraces += MallocSizeOf(st); + + if (usedStackTraces.has(st)) { + aSizes->mStackTracesUsed += MallocSizeOf(st); + } else { + aSizes->mStackTracesUnused += MallocSizeOf(st); + } } aSizes->mStackTraceTable = @@ -1881,6 +1904,20 @@ SizeOf(Sizes* aSizes) aSizes->mBlockTable = gBlockTable->sizeOfIncludingThis(MallocSizeOf); } +MOZ_EXPORT void +SizeOf(Sizes* aSizes) +{ + aSizes->Clear(); + + if (!gIsDMDRunning) { + return; + } + + AutoBlockIntercepts block(Thread::Fetch()); + AutoLockState lock; + SizeOfInternal(aSizes); +} + static void ClearGlobalState() { @@ -2013,14 +2050,17 @@ Dump(Writer aWriter) // Stats are non-deterministic, so don't show them in test mode. if (gMode != Test) { Sizes sizes; - SizeOf(&sizes); + SizeOfInternal(&sizes); WriteTitle("Execution measurements\n"); W("Data structures that persist after Dump() ends:\n"); - W(" Stack traces: %10s bytes\n", - Show(sizes.mStackTraces, gBuf1, kBufLen)); + W(" Used stack traces: %10s bytes\n", + Show(sizes.mStackTracesUsed, gBuf1, kBufLen)); + + W(" Unused stack traces: %10s bytes\n", + Show(sizes.mStackTracesUnused, gBuf1, kBufLen)); W(" Stack trace table: %10s bytes (%s entries, %s used)\n", Show(sizes.mStackTraceTable, gBuf1, kBufLen), diff --git a/memory/replace/dmd/DMD.h b/memory/replace/dmd/DMD.h index d984d22b4f2..9abb8380574 100644 --- a/memory/replace/dmd/DMD.h +++ b/memory/replace/dmd/DMD.h @@ -52,7 +52,8 @@ FpWrite(void* aFp, const char* aFmt, va_list aAp); struct Sizes { - size_t mStackTraces; + size_t mStackTracesUsed; + size_t mStackTracesUnused; size_t mStackTraceTable; size_t mBlockTable; diff --git a/xpcom/base/nsMemoryReporterManager.cpp b/xpcom/base/nsMemoryReporterManager.cpp index 8d850468339..019e0f2b102 100644 --- a/xpcom/base/nsMemoryReporterManager.cpp +++ b/xpcom/base/nsMemoryReporterManager.cpp @@ -596,11 +596,17 @@ public: NS_ENSURE_SUCCESS(rv, rv); \ } while (0) - REPORT("explicit/dmd/stack-traces", - sizes.mStackTraces, - "Memory used by DMD's stack traces."); + REPORT("explicit/dmd/stack-traces/used", + sizes.mStackTracesUsed, + "Memory used by stack traces which correspond to at least " + "one heap block DMD is tracking."); - REPORT("explicit/dmd/stack-trace-table", + REPORT("explicit/dmd/stack-traces/unused", + sizes.mStackTracesUnused, + "Memory used by stack traces which don't correspond to any heap " + "blocks DMD is currently tracking."); + + REPORT("explicit/dmd/stack-traces/table", sizes.mStackTraceTable, "Memory used by DMD's stack trace table.");