mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 20:35:50 +00:00
Bug 674922 - report per-frame-type numbers in about:memory; r=njn,roc
This commit is contained in:
parent
d958723b7d
commit
620badd810
@ -9600,7 +9600,8 @@ nsIDocument::DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
|
||||
|
||||
if (mPresShell) {
|
||||
mPresShell->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf,
|
||||
&aWindowSizes->mLayoutArenas,
|
||||
&aWindowSizes->mArenaStats,
|
||||
&aWindowSizes->mLayoutPresShell,
|
||||
&aWindowSizes->mLayoutStyleSets,
|
||||
&aWindowSizes->mLayoutTextRuns,
|
||||
&aWindowSizes->mLayoutPresContext);
|
||||
|
@ -181,10 +181,11 @@ CollectWindowReports(nsGlobalWindow *aWindow,
|
||||
"Memory used by style sheets within a window.");
|
||||
aWindowTotalSizes->mStyleSheets += windowSizes.mStyleSheets;
|
||||
|
||||
REPORT("/layout/arenas", windowSizes.mLayoutArenas,
|
||||
"Memory used by layout PresShell, PresContext, and other related "
|
||||
"areas within a window.");
|
||||
aWindowTotalSizes->mLayoutArenas += windowSizes.mLayoutArenas;
|
||||
REPORT("/layout/pres-shell", windowSizes.mLayoutPresShell,
|
||||
"Memory used by layout's PresShell, along with any structures "
|
||||
"allocated in its arena and not measured elsewhere, "
|
||||
"within a window.");
|
||||
aWindowTotalSizes->mLayoutPresShell += windowSizes.mLayoutPresShell;
|
||||
|
||||
REPORT("/layout/style-sets", windowSizes.mLayoutStyleSets,
|
||||
"Memory used by style sets within a window.");
|
||||
@ -200,6 +201,34 @@ CollectWindowReports(nsGlobalWindow *aWindow,
|
||||
"within a window.");
|
||||
aWindowTotalSizes->mLayoutPresContext += windowSizes.mLayoutPresContext;
|
||||
|
||||
// There are many different kinds of frames, but it is very likely
|
||||
// that only a few matter. Implement a cutoff so we don't bloat
|
||||
// about:memory with many uninteresting entries.
|
||||
static const size_t FRAME_SUNDRIES_THRESHOLD = 8192;
|
||||
size_t frameSundriesSize = 0;
|
||||
#define FRAME_ID(classname) \
|
||||
{ \
|
||||
size_t frameSize \
|
||||
= windowSizes.mArenaStats.FRAME_ID_STAT_FIELD(classname); \
|
||||
if (frameSize < FRAME_SUNDRIES_THRESHOLD) { \
|
||||
frameSundriesSize += frameSize; \
|
||||
} else { \
|
||||
REPORT("/layout/frames/" # classname, frameSize, \
|
||||
"Memory used by frames of " \
|
||||
"type " #classname " within a window."); \
|
||||
aWindowTotalSizes->mArenaStats.FRAME_ID_STAT_FIELD(classname) \
|
||||
+= frameSize; \
|
||||
} \
|
||||
}
|
||||
#include "nsFrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
|
||||
if (frameSundriesSize > 0) {
|
||||
REPORT("/layout/frames/sundries", frameSundriesSize,
|
||||
"The sum of all memory used by frames which were too small "
|
||||
"to be shown individually.");
|
||||
}
|
||||
|
||||
#undef REPORT
|
||||
|
||||
return NS_OK;
|
||||
@ -288,7 +317,7 @@ nsWindowMemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
|
||||
"Memory used for style sheets within windows. "
|
||||
"This is the sum of all windows' 'style-sheets' numbers.");
|
||||
|
||||
REPORT("window-objects-layout-arenas", windowTotalSizes.mLayoutArenas,
|
||||
REPORT("window-objects-layout-pres-shell", windowTotalSizes.mLayoutPresShell,
|
||||
"Memory used by layout PresShell and other related "
|
||||
"areas within windows. This is the sum of all windows' "
|
||||
"'layout/arenas' numbers.");
|
||||
@ -305,6 +334,16 @@ nsWindowMemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
|
||||
"Memory used for layout PresContexts within windows. "
|
||||
"This is the sum of all windows' 'layout/pres-contexts' numbers.");
|
||||
|
||||
size_t frameTotal = 0;
|
||||
#define FRAME_ID(classname) \
|
||||
frameTotal += windowTotalSizes.mArenaStats.FRAME_ID_STAT_FIELD(classname);
|
||||
#include "nsFrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
|
||||
REPORT("window-objects-layout-frames", frameTotal,
|
||||
"Memory used for layout frames within windows. "
|
||||
"This is the sum of all windows' 'layout/frames/' numbers.");
|
||||
|
||||
#undef REPORT
|
||||
|
||||
return NS_OK;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsArenaMemoryStats.h"
|
||||
|
||||
// This should be used for any nsINode sub-class that has fields of its own
|
||||
// that it needs to measure; any sub-class that doesn't use it will inherit
|
||||
@ -27,13 +28,14 @@ public:
|
||||
mMallocSizeOf = aMallocSizeOf;
|
||||
}
|
||||
nsMallocSizeOfFun mMallocSizeOf;
|
||||
nsArenaMemoryStats mArenaStats;
|
||||
size_t mDOMElementNodes;
|
||||
size_t mDOMTextNodes;
|
||||
size_t mDOMCDATANodes;
|
||||
size_t mDOMCommentNodes;
|
||||
size_t mDOMOther;
|
||||
size_t mStyleSheets;
|
||||
size_t mLayoutArenas;
|
||||
size_t mLayoutPresShell;
|
||||
size_t mLayoutStyleSets;
|
||||
size_t mLayoutTextRuns;
|
||||
size_t mLayoutPresContext;
|
||||
|
@ -29,6 +29,7 @@ EXPORTS_NAMESPACES = mozilla
|
||||
EXPORTS = \
|
||||
FrameLayerBuilder.h \
|
||||
FramePropertyTable.h \
|
||||
nsArenaMemoryStats.h \
|
||||
nsBidi.h \
|
||||
nsBidiPresUtils.h \
|
||||
nsCaret.h \
|
||||
|
17
layout/base/nsArenaMemoryStats.h
Normal file
17
layout/base/nsArenaMemoryStats.h
Normal file
@ -0,0 +1,17 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsArenaMemoryStats_h
|
||||
#define nsArenaMemoryStats_h
|
||||
|
||||
#define FRAME_ID_STAT_FIELD(classname) mArena##classname
|
||||
|
||||
struct nsArenaMemoryStats {
|
||||
#define FRAME_ID(classname) size_t FRAME_ID_STAT_FIELD(classname);
|
||||
#include "nsFrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
size_t mOther;
|
||||
};
|
||||
|
||||
#endif // nsArenaMemoryStats_h
|
@ -78,6 +78,7 @@ class nsARefreshObserver;
|
||||
class nsAccessibilityService;
|
||||
#endif
|
||||
class nsIWidget;
|
||||
class nsArenaMemoryStats;
|
||||
|
||||
typedef short SelectionType;
|
||||
typedef PRUint64 nsFrameState;
|
||||
@ -1231,10 +1232,11 @@ public:
|
||||
virtual void DispatchSynthMouseMove(nsGUIEvent *aEvent, bool aFlushOnHoverChange) = 0;
|
||||
|
||||
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
size_t *aArenasSize,
|
||||
nsArenaMemoryStats *aArenaObjectsSize,
|
||||
size_t *aPresShellSize,
|
||||
size_t *aStyleSetsSize,
|
||||
size_t *aTextRunsSize,
|
||||
size_t *aPresContextSize) const = 0;
|
||||
size_t *aPresContextSize) = 0;
|
||||
|
||||
/**
|
||||
* Methods that retrieve the cached font inflation preferences.
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "prmem.h"
|
||||
#include "prinit.h"
|
||||
#include "prlog.h"
|
||||
#include "nsArenaMemoryStats.h"
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
#include "nsICrashReporter.h"
|
||||
@ -251,11 +252,13 @@ public:
|
||||
typedef PRUint32 KeyType;
|
||||
nsTArray<void *> mEntries;
|
||||
size_t mEntrySize;
|
||||
size_t mEntriesEverAllocated;
|
||||
|
||||
typedef const void* KeyTypePointer;
|
||||
KeyTypePointer mKey;
|
||||
|
||||
FreeList(KeyTypePointer aKey) : mEntrySize(0), mKey(aKey) {}
|
||||
FreeList(KeyTypePointer aKey)
|
||||
: mEntrySize(0), mEntriesEverAllocated(0), mKey(aKey) {}
|
||||
// Default copy constructor and destructor are ok.
|
||||
|
||||
bool KeyEquals(KeyTypePointer const aKey) const
|
||||
@ -327,6 +330,7 @@ struct nsPresArena::State {
|
||||
}
|
||||
|
||||
// Allocate a new chunk from the arena
|
||||
list->mEntriesEverAllocated++;
|
||||
PL_ARENA_ALLOCATE(result, &mPool, aSize);
|
||||
return result;
|
||||
}
|
||||
@ -354,7 +358,7 @@ struct nsPresArena::State {
|
||||
return aEntry->mEntries.SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
|
||||
size_t SizeOfIncludingThisFromMalloc(nsMallocSizeOfFun aMallocSizeOf) const
|
||||
{
|
||||
size_t n = aMallocSizeOf(this);
|
||||
|
||||
@ -370,12 +374,66 @@ struct nsPresArena::State {
|
||||
aMallocSizeOf);
|
||||
return n;
|
||||
}
|
||||
|
||||
struct EnumerateData {
|
||||
nsArenaMemoryStats* stats;
|
||||
size_t total;
|
||||
};
|
||||
|
||||
static PLDHashOperator FreeListEnumerator(FreeList* aEntry, void* aData)
|
||||
{
|
||||
EnumerateData* data = static_cast<EnumerateData*>(aData);
|
||||
// Note that we're not measuring the size of the entries on the free
|
||||
// list here. The free list knows how many objects we've allocated
|
||||
// ever (which includes any objects that may be on the FreeList's
|
||||
// |mEntries| at this point) and we're using that to determine the
|
||||
// total size of objects allocated with a given ID.
|
||||
size_t totalSize = aEntry->mEntrySize * aEntry->mEntriesEverAllocated;
|
||||
size_t* p;
|
||||
|
||||
switch (NS_PTR_TO_INT32(aEntry->mKey)) {
|
||||
#define FRAME_ID(classname) \
|
||||
case nsQueryFrame::classname##_id: \
|
||||
p = &data->stats->FRAME_ID_STAT_FIELD(classname); \
|
||||
break;
|
||||
#include "nsFrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
default:
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
*p += totalSize;
|
||||
data->total += totalSize;
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
nsArenaMemoryStats* aArenaStats)
|
||||
{
|
||||
// We do a complicated dance here because we want to measure the
|
||||
// space taken up by the different kinds of objects in the arena,
|
||||
// but we don't have pointers to those objects. And even if we did,
|
||||
// we wouldn't be able to use aMallocSizeOf on them, since they were
|
||||
// allocated out of malloc'd chunks of memory. So we compute the
|
||||
// size of the arena as known by malloc and we add up the sizes of
|
||||
// all the objects that we care about. Subtracting these two
|
||||
// quantities gives us a catch-all "other" number, which includes
|
||||
// slop in the arena itself as well as the size of objects that
|
||||
// we've not measured explicitly.
|
||||
|
||||
size_t mallocSize = SizeOfIncludingThisFromMalloc(aMallocSizeOf);
|
||||
EnumerateData data = { aArenaStats, 0 };
|
||||
mFreeLists.EnumerateEntries(FreeListEnumerator, &data);
|
||||
aArenaStats->mOther = mallocSize - data.total;
|
||||
}
|
||||
};
|
||||
|
||||
size_t
|
||||
nsPresArena::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
|
||||
void
|
||||
nsPresArena::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
nsArenaMemoryStats* aArenaStats)
|
||||
{
|
||||
return mState ? mState->SizeOfIncludingThis(aMallocSizeOf) : 0;
|
||||
mState->SizeOfIncludingThis(aMallocSizeOf, aArenaStats);
|
||||
}
|
||||
|
||||
#else
|
||||
@ -402,11 +460,9 @@ struct nsPresArena::State
|
||||
}
|
||||
};
|
||||
|
||||
size_t
|
||||
nsPresArena::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void
|
||||
nsPresArena::SizeOfExcludingThis(nsMallocSizeOfFun, nsArenaMemoryStats*)
|
||||
{}
|
||||
|
||||
#endif // DEBUG_TRACEMALLOC_PRESARENA
|
||||
|
||||
|
@ -13,6 +13,8 @@
|
||||
|
||||
#include "mozilla/StandardInteger.h"
|
||||
|
||||
class nsArenaMemoryStats;
|
||||
|
||||
// Uncomment this to disable arenas, instead forwarding to
|
||||
// malloc for every allocation.
|
||||
//#define DEBUG_TRACEMALLOC_PRESARENA 1
|
||||
@ -56,7 +58,12 @@ public:
|
||||
NS_HIDDEN_(void*) AllocateByObjectID(ObjectID aID, size_t aSize);
|
||||
NS_HIDDEN_(void) FreeByObjectID(ObjectID aID, void* aPtr);
|
||||
|
||||
size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
|
||||
/**
|
||||
* Fill aArenaStats with sizes of interesting objects allocated in
|
||||
* this arena and its mOther field with the size of everything else.
|
||||
*/
|
||||
void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
nsArenaMemoryStats* aArenaStats);
|
||||
|
||||
/**
|
||||
* Get the poison value that can be used to fill a memory space with
|
||||
|
@ -8927,13 +8927,15 @@ PresShell::GetRootPresShell()
|
||||
|
||||
void
|
||||
PresShell::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
size_t *aArenasSize,
|
||||
nsArenaMemoryStats *aArenaObjectsSize,
|
||||
size_t *aPresShellSize,
|
||||
size_t *aStyleSetsSize,
|
||||
size_t *aTextRunsSize,
|
||||
size_t *aPresContextSize) const
|
||||
size_t *aPresContextSize)
|
||||
{
|
||||
*aArenasSize = aMallocSizeOf(this);
|
||||
*aArenasSize += mFrameArena.SizeOfExcludingThis(aMallocSizeOf);
|
||||
mFrameArena.SizeOfExcludingThis(aMallocSizeOf, aArenaObjectsSize);
|
||||
*aPresShellSize = aMallocSizeOf(this);
|
||||
*aPresShellSize += aArenaObjectsSize->mOther;
|
||||
|
||||
*aStyleSetsSize = StyleSet()->SizeOfIncludingThis(aMallocSizeOf);
|
||||
|
||||
|
@ -316,10 +316,11 @@ public:
|
||||
}
|
||||
|
||||
void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
size_t *aArenasSize,
|
||||
nsArenaMemoryStats *aArenaObjectsSize,
|
||||
size_t *aPresShellSize,
|
||||
size_t *aStyleSetsSize,
|
||||
size_t *aTextRunsSize,
|
||||
size_t *aPresContextSize) const;
|
||||
size_t *aPresContextSize);
|
||||
size_t SizeOfTextRuns(nsMallocSizeOfFun aMallocSizeOf) const;
|
||||
|
||||
// This data is stored as a content property (nsGkAtoms::scrolling) on
|
||||
|
Loading…
Reference in New Issue
Block a user