Bug 829439 (part 1) - Add MemoryReporterBase class that promotes better encapsulation within nsIMemoryReporter sub-classes. r=jlebar.

--HG--
extra : rebase_source : 53a77ea456f2aedafe05954ceece7e64db743e66
This commit is contained in:
Nicholas Nethercote 2013-01-14 16:26:47 -08:00
parent 66edabde03
commit dc051e917d
14 changed files with 339 additions and 241 deletions

View File

@ -1,5 +1,5 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 sw=2 et tw=78: */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public /* 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 * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -247,25 +247,29 @@ static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID); static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
static PLDHashTable sEventListenerManagersHash; static PLDHashTable sEventListenerManagersHash;
static nsCOMPtr<nsIMemoryReporter> sEventListenerManagersHashReporter;
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(EventListenerManagersHashMallocSizeOf) class DOMEventListenerManagersHashReporter MOZ_FINAL : public MemoryReporterBase
static int64_t GetEventListenerManagersHash()
{ {
// We don't measure the |nsEventListenerManager| objects pointed to by the public:
// entries because those references are non-owning. DOMEventListenerManagersHashReporter()
return PL_DHashTableSizeOfExcludingThis(&sEventListenerManagersHash, : MemoryReporterBase(
nullptr,
EventListenerManagersHashMallocSizeOf);
}
NS_MEMORY_REPORTER_IMPLEMENT(EventListenerManagersHash,
"explicit/dom/event-listener-managers-hash", "explicit/dom/event-listener-managers-hash",
KIND_HEAP, KIND_HEAP,
UNITS_BYTES, UNITS_BYTES,
GetEventListenerManagersHash,
"Memory used by the event listener manager's hash table.") "Memory used by the event listener manager's hash table.")
{}
private:
int64_t Amount()
{
// We don't measure the |nsEventListenerManager| objects pointed to by the
// entries because those references are non-owning.
return sEventListenerManagersHash.ops
? PL_DHashTableSizeOfExcludingThis(&sEventListenerManagersHash,
nullptr, MallocSizeOf)
: 0;
}
};
class EventListenerManagerMapEntry : public PLDHashEntryHdr class EventListenerManagerMapEntry : public PLDHashEntryHdr
{ {
@ -403,9 +407,7 @@ nsContentUtils::Init()
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
sEventListenerManagersHashReporter = NS_RegisterMemoryReporter(new DOMEventListenerManagersHashReporter);
new NS_MEMORY_REPORTER_NAME(EventListenerManagersHash);
(void)::NS_RegisterMemoryReporter(sEventListenerManagersHashReporter);
} }
sBlockedScriptRunners = new nsTArray< nsCOMPtr<nsIRunnable> >; sBlockedScriptRunners = new nsTArray< nsCOMPtr<nsIRunnable> >;
@ -1487,9 +1489,6 @@ nsContentUtils::Shutdown()
if (sEventListenerManagersHash.entryCount == 0) { if (sEventListenerManagersHash.entryCount == 0) {
PL_DHashTableFinish(&sEventListenerManagersHash); PL_DHashTableFinish(&sEventListenerManagersHash);
sEventListenerManagersHash.ops = nullptr; sEventListenerManagersHash.ops = nullptr;
(void)::NS_UnregisterMemoryReporter(sEventListenerManagersHashReporter);
sEventListenerManagersHashReporter = nullptr;
} }
} }

View File

@ -130,7 +130,6 @@ static NS_NAMED_LITERAL_STRING(kDefaultFontStyle, "10px sans-serif");
const Float SIGMA_MAX = 100; const Float SIGMA_MAX = 100;
/* Memory reporter stuff */ /* Memory reporter stuff */
static nsIMemoryReporter *gCanvasAzureMemoryReporter = nullptr;
static int64_t gCanvasAzureMemoryUsed = 0; static int64_t gCanvasAzureMemoryUsed = 0;
static int64_t GetCanvasAzureMemoryUsed() { static int64_t GetCanvasAzureMemoryUsed() {
@ -792,9 +791,10 @@ CanvasRenderingContext2D::EnsureTarget()
} }
if (mTarget) { if (mTarget) {
if (gCanvasAzureMemoryReporter == nullptr) { static bool registered = false;
gCanvasAzureMemoryReporter = new NS_MEMORY_REPORTER_NAME(CanvasAzureMemory); if (!registered) {
NS_RegisterMemoryReporter(gCanvasAzureMemoryReporter); registered = true;
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(CanvasAzureMemory));
} }
gCanvasAzureMemoryUsed += mWidth * mHeight * 4; gCanvasAzureMemoryUsed += mWidth * mHeight * 4;

View File

@ -1,5 +1,5 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 sw=2 et tw=78: */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public /* 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 * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -175,24 +175,6 @@ static bool sNeedsFullCC = false;
static nsJSContext *sContextList = nullptr; static nsJSContext *sContextList = nullptr;
static nsScriptNameSpaceManager *gNameSpaceManager; static nsScriptNameSpaceManager *gNameSpaceManager;
static nsIMemoryReporter *gReporter;
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(ScriptNameSpaceManagerMallocSizeOf)
static int64_t
GetScriptNameSpaceManagerSize()
{
MOZ_ASSERT(gNameSpaceManager);
return gNameSpaceManager->SizeOfIncludingThis(
ScriptNameSpaceManagerMallocSizeOf);
}
NS_MEMORY_REPORTER_IMPLEMENT(ScriptNameSpaceManager,
"explicit/script-namespace-manager",
KIND_HEAP,
nsIMemoryReporter::UNITS_BYTES,
GetScriptNameSpaceManagerSize,
"Memory used for the script namespace manager.")
static nsIJSRuntimeService *sRuntimeService; static nsIJSRuntimeService *sRuntimeService;
JSRuntime *nsJSRuntime::sRuntime; JSRuntime *nsJSRuntime::sRuntime;
@ -3729,7 +3711,6 @@ nsJSRuntime::Startup()
sDisableExplicitCompartmentGC = false; sDisableExplicitCompartmentGC = false;
sNeedsFullCC = false; sNeedsFullCC = false;
gNameSpaceManager = nullptr; gNameSpaceManager = nullptr;
gReporter = nullptr;
sRuntimeService = nullptr; sRuntimeService = nullptr;
sRuntime = nullptr; sRuntime = nullptr;
sIsInitialized = false; sIsInitialized = false;
@ -4072,9 +4053,6 @@ nsJSRuntime::GetNameSpaceManager()
nsresult rv = gNameSpaceManager->Init(); nsresult rv = gNameSpaceManager->Init();
NS_ENSURE_SUCCESS(rv, nullptr); NS_ENSURE_SUCCESS(rv, nullptr);
gReporter = new NS_MEMORY_REPORTER_NAME(ScriptNameSpaceManager);
NS_RegisterMemoryReporter(gReporter);
} }
return gNameSpaceManager; return gNameSpaceManager;
@ -4091,10 +4069,6 @@ nsJSRuntime::Shutdown()
nsJSContext::KillInterSliceGCTimer(); nsJSContext::KillInterSliceGCTimer();
NS_IF_RELEASE(gNameSpaceManager); NS_IF_RELEASE(gNameSpaceManager);
if (gReporter) {
(void)::NS_UnregisterMemoryReporter(gReporter);
gReporter = nullptr;
}
if (!sContextCount) { if (!sContextCount) {
// We're being shutdown, and there are no more contexts // We're being shutdown, and there are no more contexts

View File

@ -1,4 +1,5 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public /* 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 * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -111,6 +112,24 @@ GlobalNameHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry,
return true; return true;
} }
class ScriptNameSpaceManagerReporter MOZ_FINAL : public MemoryReporterBase
{
public:
ScriptNameSpaceManagerReporter(nsScriptNameSpaceManager* aManager)
: MemoryReporterBase(
"explicit/script-namespace-manager",
KIND_HEAP,
nsIMemoryReporter::UNITS_BYTES,
"Memory used for the script namespace manager.")
, mManager(aManager)
{}
private:
int64_t Amount() { return mManager->SizeOfIncludingThis(MallocSizeOf); }
nsScriptNameSpaceManager* mManager;
};
NS_IMPL_ISUPPORTS2(nsScriptNameSpaceManager, NS_IMPL_ISUPPORTS2(nsScriptNameSpaceManager,
nsIObserver, nsIObserver,
nsISupportsWeakReference) nsISupportsWeakReference)
@ -124,6 +143,7 @@ nsScriptNameSpaceManager::nsScriptNameSpaceManager()
nsScriptNameSpaceManager::~nsScriptNameSpaceManager() nsScriptNameSpaceManager::~nsScriptNameSpaceManager()
{ {
if (mIsInitialized) { if (mIsInitialized) {
NS_UnregisterMemoryReporter(mReporter);
// Destroy the hash // Destroy the hash
PL_DHashTableFinish(&mGlobalNames); PL_DHashTableFinish(&mGlobalNames);
PL_DHashTableFinish(&mNavigatorNames); PL_DHashTableFinish(&mNavigatorNames);
@ -398,6 +418,9 @@ nsScriptNameSpaceManager::Init()
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
mReporter = new ScriptNameSpaceManagerReporter(this);
NS_RegisterMemoryReporter(mReporter);
nsresult rv = NS_OK; nsresult rv = NS_OK;
rv = FillHashWithDOMInterfaces(); rv = FillHashWithDOMInterfaces();

View File

@ -1,6 +1,6 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
* /* vim: set ts=8 sts=2 et sw=2 tw=80: */
* This Source Code Form is subject to the terms of the Mozilla Public /* 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 * 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/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
* *
@ -78,6 +78,7 @@ private:
class nsIScriptContext; class nsIScriptContext;
class nsICategoryManager; class nsICategoryManager;
class nsIMemoryReporter;
class GlobalNameMapEntry; class GlobalNameMapEntry;
@ -191,6 +192,8 @@ private:
PLDHashTable mNavigatorNames; PLDHashTable mNavigatorNames;
bool mIsInitialized; bool mIsInitialized;
nsCOMPtr<nsIMemoryReporter> mReporter;
}; };
#endif /* nsScriptNameSpaceManager_h__ */ #endif /* nsScriptNameSpaceManager_h__ */

View File

@ -1,5 +1,5 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */ /* vim: set ts=8 sts=4 et sw=4 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public /* 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 * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -21,7 +21,6 @@
#include "nsDiskCacheDevice.h" #include "nsDiskCacheDevice.h"
#include "nsDiskCacheDeviceSQL.h" #include "nsDiskCacheDeviceSQL.h"
#include "nsIMemoryReporter.h"
#include "nsIObserverService.h" #include "nsIObserverService.h"
#include "nsIPrefService.h" #include "nsIPrefService.h"
#include "nsIPrefBranch.h" #include "nsIPrefBranch.h"
@ -1071,26 +1070,6 @@ private:
*****************************************************************************/ *****************************************************************************/
nsCacheService * nsCacheService::gService = nullptr; nsCacheService * nsCacheService::gService = nullptr;
static nsCOMPtr<nsIMemoryReporter> MemoryCacheReporter = nullptr;
NS_THREADSAFE_MEMORY_REPORTER_IMPLEMENT(NetworkMemoryCache,
"explicit/network/memory-cache",
KIND_HEAP,
UNITS_BYTES,
nsCacheService::MemoryDeviceSize,
"Memory used by the network memory cache.")
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(NetworkDiskCacheMallocSizeOf)
static nsCOMPtr<nsIMemoryReporter> DiskCacheReporter = nullptr;
NS_THREADSAFE_MEMORY_REPORTER_IMPLEMENT(NetworkDiskCache,
"explicit/network/disk-cache",
KIND_HEAP,
UNITS_BYTES,
nsCacheService::DiskDeviceHeapSize,
"Memory used by the network disk cache.")
NS_IMPL_THREADSAFE_ISUPPORTS1(nsCacheService, nsICacheService) NS_IMPL_THREADSAFE_ISUPPORTS1(nsCacheService, nsICacheService)
nsCacheService::nsCacheService() nsCacheService::nsCacheService()
@ -1245,14 +1224,6 @@ nsCacheService::Shutdown()
parentDir = mObserver->DiskCacheParentDirectory(); parentDir = mObserver->DiskCacheParentDirectory();
shouldSanitize = mObserver->SanitizeAtShutdown(); shouldSanitize = mObserver->SanitizeAtShutdown();
// unregister memory reporters, before deleting the devices, just
// to be safe
NS_UnregisterMemoryReporter(MemoryCacheReporter);
MemoryCacheReporter = nullptr;
NS_UnregisterMemoryReporter(DiskCacheReporter);
DiskCacheReporter = nullptr;
// deallocate memory and disk caches // deallocate memory and disk caches
delete mMemoryDevice; delete mMemoryDevice;
mMemoryDevice = nullptr; mMemoryDevice = nullptr;
@ -1605,9 +1576,6 @@ nsCacheService::CreateDiskDevice()
// Ignore state of the timer and return success since the purpose of the // Ignore state of the timer and return success since the purpose of the
// method (create the disk-device) has been fulfilled // method (create the disk-device) has been fulfilled
DiskCacheReporter = new NS_MEMORY_REPORTER_NAME(NetworkDiskCache);
NS_RegisterMemoryReporter(DiskCacheReporter);
return NS_OK; return NS_OK;
} }
@ -1773,10 +1741,6 @@ nsCacheService::CreateMemoryDevice()
mMemoryDevice = nullptr; mMemoryDevice = nullptr;
} }
MemoryCacheReporter =
new NS_MEMORY_REPORTER_NAME(NetworkMemoryCache);
NS_RegisterMemoryReporter(MemoryCacheReporter);
return rv; return rv;
} }
@ -2274,21 +2238,6 @@ nsCacheService::EnsureEntryHasDevice(nsCacheEntry * entry)
return device; return device;
} }
int64_t
nsCacheService::MemoryDeviceSize()
{
nsMemoryCacheDevice *memoryDevice = GlobalInstance()->mMemoryDevice;
return memoryDevice ? memoryDevice->TotalSize() : 0;
}
int64_t
nsCacheService::DiskDeviceHeapSize()
{
nsCacheServiceAutoLock lock(LOCK_TELEM(NSCACHESERVICE_DISKDEVICEHEAPSIZE));
nsDiskCacheDevice *diskDevice = GlobalInstance()->mDiskDevice;
return (int64_t)(diskDevice ? diskDevice->SizeOfIncludingThis(NetworkDiskCacheMallocSizeOf) : 0);
}
nsresult nsresult
nsCacheService::DoomEntry(nsCacheEntry * entry) nsCacheService::DoomEntry(nsCacheEntry * entry)
{ {

View File

@ -1,10 +1,9 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
* /* vim: set ts=8 sts=4 et sw=4 tw=80: */
* This Source Code Form is subject to the terms of the Mozilla Public /* 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 * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _nsCacheService_h_ #ifndef _nsCacheService_h_
#define _nsCacheService_h_ #define _nsCacheService_h_
@ -130,10 +129,6 @@ public:
static static
nsCacheService * GlobalInstance() { return gService; } nsCacheService * GlobalInstance() { return gService; }
static int64_t MemoryDeviceSize();
static int64_t DiskDeviceHeapSize();
static nsresult DoomEntry(nsCacheEntry * entry); static nsresult DoomEntry(nsCacheEntry * entry);
static bool IsStorageEnabledForPolicy_Locked(nsCacheStoragePolicy policy); static bool IsStorageEnabledForPolicy_Locked(nsCacheStoragePolicy policy);

View File

@ -9,6 +9,7 @@
#include "mozilla/DebugOnly.h" #include "mozilla/DebugOnly.h"
#include "nsCache.h" #include "nsCache.h"
#include "nsIMemoryReporter.h"
// include files for ftruncate (or equivalent) // include files for ftruncate (or equivalent)
#if defined(XP_UNIX) #if defined(XP_UNIX)
@ -368,16 +369,43 @@ nsDiskCache::Truncate(PRFileDesc * fd, uint32_t newEOF)
* nsDiskCacheDevice * nsDiskCacheDevice
*****************************************************************************/ *****************************************************************************/
class NetworkDiskCacheReporter MOZ_FINAL : public MemoryReporterBase
{
public:
NetworkDiskCacheReporter(nsDiskCacheDevice* aDevice)
: MemoryReporterBase(
"explicit/network/disk-cache",
KIND_HEAP,
UNITS_BYTES,
"Memory used by the network disk cache.")
, mDevice(aDevice)
{}
private:
int64_t Amount()
{
nsCacheServiceAutoLock
lock(LOCK_TELEM(NSCACHESERVICE_DISKDEVICEHEAPSIZE));
return mDevice->SizeOfIncludingThis(MallocSizeOf);
}
nsDiskCacheDevice* mDevice;
};
nsDiskCacheDevice::nsDiskCacheDevice() nsDiskCacheDevice::nsDiskCacheDevice()
: mCacheCapacity(0) : mCacheCapacity(0)
, mMaxEntrySize(-1) // -1 means "no limit" , mMaxEntrySize(-1) // -1 means "no limit"
, mInitialized(false) , mInitialized(false)
, mClearingDiskCache(false) , mClearingDiskCache(false)
, mReporter(nullptr)
{ {
mReporter = new NetworkDiskCacheReporter(this);
NS_RegisterMemoryReporter(mReporter);
} }
nsDiskCacheDevice::~nsDiskCacheDevice() nsDiskCacheDevice::~nsDiskCacheDevice()
{ {
NS_UnregisterMemoryReporter(mReporter);
Shutdown(); Shutdown();
} }

View File

@ -17,6 +17,7 @@
#include "nsCOMArray.h" #include "nsCOMArray.h"
class nsDiskCacheMap; class nsDiskCacheMap;
class nsIMemoryReporter;
class nsDiskCacheDevice : public nsCacheDevice { class nsDiskCacheDevice : public nsCacheDevice {
@ -110,6 +111,8 @@ private:
nsDiskCacheMap mCacheMap; nsDiskCacheMap mCacheMap;
bool mInitialized; bool mInitialized;
bool mClearingDiskCache; bool mClearingDiskCache;
nsCOMPtr<nsIMemoryReporter> mReporter;
}; };
#endif // _nsDiskCacheDevice_h_ #endif // _nsDiskCacheDevice_h_

View File

@ -1,6 +1,6 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
* /* vim: set ts=8 sts=4 et sw=4 tw=80: */
* This Source Code Form is subject to the terms of the Mozilla Public /* 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 * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -8,8 +8,9 @@
#include "nsMemoryCacheDevice.h" #include "nsMemoryCacheDevice.h"
#include "nsCacheService.h" #include "nsCacheService.h"
#include "nsICacheService.h" #include "nsICacheService.h"
#include "nsIStorageStream.h"
#include "nsICacheVisitor.h" #include "nsICacheVisitor.h"
#include "nsIStorageStream.h"
#include "nsIMemoryReporter.h"
#include "nsCRT.h" #include "nsCRT.h"
#include "nsReadableUtils.h" #include "nsReadableUtils.h"
#include "mozilla/Telemetry.h" #include "mozilla/Telemetry.h"
@ -26,6 +27,26 @@
const char *gMemoryDeviceID = "memory"; const char *gMemoryDeviceID = "memory";
class NetworkMemoryCacheReporter MOZ_FINAL :
public mozilla::MemoryReporterBase
{
public:
NetworkMemoryCacheReporter(nsMemoryCacheDevice* aDevice)
: MemoryReporterBase(
"explicit/network/memory-cache",
KIND_HEAP,
UNITS_BYTES,
"Memory used by the network memory cache.")
, mDevice(aDevice)
{}
private:
int64_t Amount() { return mDevice->TotalSize(); }
nsMemoryCacheDevice* mDevice;
};
nsMemoryCacheDevice::nsMemoryCacheDevice() nsMemoryCacheDevice::nsMemoryCacheDevice()
: mInitialized(false), : mInitialized(false),
mHardLimit(4 * 1024 * 1024), // default, if no pref mHardLimit(4 * 1024 * 1024), // default, if no pref
@ -34,15 +55,20 @@ nsMemoryCacheDevice::nsMemoryCacheDevice()
mInactiveSize(0), mInactiveSize(0),
mEntryCount(0), mEntryCount(0),
mMaxEntryCount(0), mMaxEntryCount(0),
mMaxEntrySize(-1) // -1 means "no limit" mMaxEntrySize(-1), // -1 means "no limit"
mReporter(nullptr)
{ {
for (int i=0; i<kQueueCount; ++i) for (int i=0; i<kQueueCount; ++i)
PR_INIT_CLIST(&mEvictionList[i]); PR_INIT_CLIST(&mEvictionList[i]);
mReporter = new NetworkMemoryCacheReporter(this);
NS_RegisterMemoryReporter(mReporter);
} }
nsMemoryCacheDevice::~nsMemoryCacheDevice() nsMemoryCacheDevice::~nsMemoryCacheDevice()
{ {
NS_UnregisterMemoryReporter(mReporter);
Shutdown(); Shutdown();
} }

View File

@ -1,6 +1,6 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
* /* vim: set ts=8 sts=4 et sw=4 tw=80: */
* This Source Code Form is subject to the terms of the Mozilla Public /* 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 * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -12,6 +12,7 @@
#include "nsCacheEntry.h" #include "nsCacheEntry.h"
class nsIMemoryReporter;
class nsMemoryCacheDeviceInfo; class nsMemoryCacheDeviceInfo;
/****************************************************************************** /******************************************************************************
@ -99,6 +100,8 @@ private:
int32_t mMaxEntrySize; // internal unit is bytes int32_t mMaxEntrySize; // internal unit is bytes
// XXX what other stats do we want to keep? // XXX what other stats do we want to keep?
nsCOMPtr<nsIMemoryReporter> mReporter;
}; };

View File

@ -1,5 +1,5 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set cindent tabstop=4 expandtab shiftwidth=4: */ /* vim: set ts=8 sts=4 et sw=4 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public /* 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 * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -1041,6 +1041,8 @@ struct nsCycleCollector
CC_BeforeUnlinkCallback mBeforeUnlinkCB; CC_BeforeUnlinkCallback mBeforeUnlinkCB;
CC_ForgetSkippableCallback mForgetSkippableCB; CC_ForgetSkippableCallback mForgetSkippableCB;
nsCOMPtr<nsIMemoryMultiReporter> mReporter;
nsPurpleBuffer mPurpleBuf; nsPurpleBuffer mPurpleBuf;
void RegisterJSRuntime(nsCycleCollectionJSRuntime *aJSRuntime); void RegisterJSRuntime(nsCycleCollectionJSRuntime *aJSRuntime);
@ -1139,7 +1141,6 @@ public:
static nsCycleCollector *sCollector = nullptr; static nsCycleCollector *sCollector = nullptr;
static nsIMemoryMultiReporter *sCollectorReporter = nullptr;
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
@ -2440,6 +2441,87 @@ nsCycleCollector::CollectWhite(nsICycleCollectorListener *aListener)
} }
////////////////////////
// Memory reporter
////////////////////////
class CycleCollectorMultiReporter MOZ_FINAL : public nsIMemoryMultiReporter
{
public:
CycleCollectorMultiReporter(nsCycleCollector* aCollector)
: mCollector(aCollector)
{}
NS_DECL_ISUPPORTS
NS_IMETHOD GetName(nsACString& name)
{
name.AssignLiteral("cycle-collector");
return NS_OK;
}
NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback* aCb,
nsISupports* aClosure)
{
size_t objectSize, graphNodesSize, graphEdgesSize, whiteNodesSize,
purpleBufferSize;
mCollector->SizeOfIncludingThis(MallocSizeOf,
&objectSize, &graphNodesSize,
&graphEdgesSize, &whiteNodesSize,
&purpleBufferSize);
#define REPORT(_path, _amount, _desc) \
do { \
size_t amount = _amount; /* evaluate |_amount| only once */ \
if (amount > 0) { \
nsresult rv; \
rv = aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \
nsIMemoryReporter::KIND_HEAP, \
nsIMemoryReporter::UNITS_BYTES, _amount, \
NS_LITERAL_CSTRING(_desc), aClosure); \
NS_ENSURE_SUCCESS(rv, rv); \
} \
} while (0)
REPORT("explicit/cycle-collector/collector-object", objectSize,
"Memory used for the cycle collector object itself.");
REPORT("explicit/cycle-collector/graph-nodes", graphNodesSize,
"Memory used for the nodes of the cycle collector's graph. "
"This should be zero when the collector is idle.");
REPORT("explicit/cycle-collector/graph-edges", graphEdgesSize,
"Memory used for the edges of the cycle collector's graph. "
"This should be zero when the collector is idle.");
REPORT("explicit/cycle-collector/white-nodes", whiteNodesSize,
"Memory used for the cycle collector's white nodes array. "
"This should be zero when the collector is idle.");
REPORT("explicit/cycle-collector/purple-buffer", purpleBufferSize,
"Memory used for the cycle collector's purple buffer.");
#undef REPORT
return NS_OK;
}
NS_IMETHOD GetExplicitNonHeap(int64_t* n)
{
// This reporter does neither "explicit" nor NONHEAP measurements.
*n = 0;
return NS_OK;
}
private:
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(MallocSizeOf)
nsCycleCollector* mCollector;
};
NS_IMPL_ISUPPORTS1(CycleCollectorMultiReporter, nsIMemoryMultiReporter)
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Collector implementation // Collector implementation
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
@ -2455,6 +2537,7 @@ nsCycleCollector::nsCycleCollector() :
mVisitedGCed(0), mVisitedGCed(0),
mBeforeUnlinkCB(nullptr), mBeforeUnlinkCB(nullptr),
mForgetSkippableCB(nullptr), mForgetSkippableCB(nullptr),
mReporter(nullptr),
#ifdef DEBUG_CC #ifdef DEBUG_CC
mPurpleBuf(mParams, mStats), mPurpleBuf(mParams, mStats),
mPtrLog(nullptr) mPtrLog(nullptr)
@ -2470,6 +2553,7 @@ nsCycleCollector::nsCycleCollector() :
nsCycleCollector::~nsCycleCollector() nsCycleCollector::~nsCycleCollector()
{ {
NS_UnregisterMemoryMultiReporter(mReporter);
} }
@ -2483,6 +2567,15 @@ nsCycleCollector::RegisterJSRuntime(nsCycleCollectionJSRuntime *aJSRuntime)
Fault("multiple registrations of cycle collector JS runtime", aJSRuntime); Fault("multiple registrations of cycle collector JS runtime", aJSRuntime);
mJSRuntime = aJSRuntime; mJSRuntime = aJSRuntime;
// We can't register the reporter in nsCycleCollector() because that runs
// before the memory reporter manager is initialized. So we do it here
// instead.
static bool registered = false;
if (!registered) {
NS_RegisterMemoryMultiReporter(new CycleCollectorMultiReporter(this));
registered = true;
}
} }
void void
@ -3023,13 +3116,6 @@ nsCycleCollector::WasFreed(nsISupports *n)
} }
#endif #endif
////////////////////////
// Memory reporter
////////////////////////
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(CycleCollectorMallocSizeOf)
void void
nsCycleCollector::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, nsCycleCollector::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
size_t *aObjectSize, size_t *aObjectSize,
@ -3057,73 +3143,6 @@ nsCycleCollector::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
// - mStats, mPtrLog, mExpectedGarbage: because they're DEBUG_CC-only. // - mStats, mPtrLog, mExpectedGarbage: because they're DEBUG_CC-only.
} }
class CycleCollectorMultiReporter MOZ_FINAL : public nsIMemoryMultiReporter
{
public:
NS_DECL_ISUPPORTS
NS_IMETHOD GetName(nsACString &name)
{
name.AssignLiteral("cycle-collector");
return NS_OK;
}
NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *aCb,
nsISupports *aClosure)
{
if (!sCollector)
return NS_OK;
size_t objectSize, graphNodesSize, graphEdgesSize, whiteNodesSize,
purpleBufferSize;
sCollector->SizeOfIncludingThis(CycleCollectorMallocSizeOf,
&objectSize, &graphNodesSize,
&graphEdgesSize, &whiteNodesSize,
&purpleBufferSize);
#define REPORT(_path, _amount, _desc) \
do { \
size_t amount = _amount; /* evaluate |_amount| just once */ \
if (amount > 0) { \
nsresult rv; \
rv = aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \
nsIMemoryReporter::KIND_HEAP, \
nsIMemoryReporter::UNITS_BYTES, _amount, \
NS_LITERAL_CSTRING(_desc), aClosure); \
NS_ENSURE_SUCCESS(rv, rv); \
} \
} while (0)
REPORT("explicit/cycle-collector/collector-object", objectSize,
"Memory used for the cycle collector object itself.");
REPORT("explicit/cycle-collector/graph-nodes", graphNodesSize,
"Memory used for the nodes of the cycle collector's graph. "
"This should be zero when the collector is idle.");
REPORT("explicit/cycle-collector/graph-edges", graphEdgesSize,
"Memory used for the edges of the cycle collector's graph. "
"This should be zero when the collector is idle.");
REPORT("explicit/cycle-collector/white-nodes", whiteNodesSize,
"Memory used for the cycle collector's white nodes array. "
"This should be zero when the collector is idle.");
REPORT("explicit/cycle-collector/purple-buffer", purpleBufferSize,
"Memory used for the cycle collector's purple buffer.");
return NS_OK;
}
NS_IMETHOD GetExplicitNonHeap(int64_t *n)
{
// This reporter does neither "explicit" nor NONHEAP measurements.
*n = 0;
return NS_OK;
}
};
NS_IMPL_ISUPPORTS1(CycleCollectorMultiReporter, nsIMemoryMultiReporter)
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Module public API (exported in nsCycleCollector.h) // Module public API (exported in nsCycleCollector.h)
@ -3133,14 +3152,8 @@ NS_IMPL_ISUPPORTS1(CycleCollectorMultiReporter, nsIMemoryMultiReporter)
void void
nsCycleCollector_registerJSRuntime(nsCycleCollectionJSRuntime *rt) nsCycleCollector_registerJSRuntime(nsCycleCollectionJSRuntime *rt)
{ {
static bool regMemReport = true;
if (sCollector) if (sCollector)
sCollector->RegisterJSRuntime(rt); sCollector->RegisterJSRuntime(rt);
if (regMemReport) {
regMemReport = false;
sCollectorReporter = new CycleCollectorMultiReporter;
NS_RegisterMemoryMultiReporter(sCollectorReporter);
}
} }
void void
@ -3148,10 +3161,6 @@ nsCycleCollector_forgetJSRuntime()
{ {
if (sCollector) if (sCollector)
sCollector->ForgetJSRuntime(); sCollector->ForgetJSRuntime();
if (sCollectorReporter) {
NS_UnregisterMemoryMultiReporter(sCollectorReporter);
sCollectorReporter = nullptr;
}
} }
nsPurpleBufferEntry* nsPurpleBufferEntry*

View File

@ -1,4 +1,5 @@
/* -*- Mode: C++; tab-width: 50; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public /* 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 * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -304,9 +305,13 @@ interface nsIMemoryReporterManager : nsISupports
%{C++ %{C++
/* #include "nsStringGlue.h"
* Note that this defaults 'process' to "", which is usually what's desired.
*/ // The NS_*MEMORY_REPORTER_IMPLEMENT* macros are the deprecated short-cut way
// of defining memory reporters. You should instead subclass the
// MemoryReporterBase class below.
// Note that this defaults 'process' to "", which is usually what's desired.
#define NS_MEMORY_REPORTER_IMPLEMENT_HELPER(_classname, _path, _kind, _units, _amountFunction, _desc, _ts) \ #define NS_MEMORY_REPORTER_IMPLEMENT_HELPER(_classname, _path, _kind, _units, _amountFunction, _desc, _ts) \
class MemoryReporter_##_classname MOZ_FINAL : public nsIMemoryReporter { \ class MemoryReporter_##_classname MOZ_FINAL : public nsIMemoryReporter { \
public: \ public: \
@ -320,18 +325,16 @@ interface nsIMemoryReporterManager : nsISupports
}; \ }; \
NS_IMPL##_ts##ISUPPORTS1(MemoryReporter_##_classname, nsIMemoryReporter) NS_IMPL##_ts##ISUPPORTS1(MemoryReporter_##_classname, nsIMemoryReporter)
/* // The only difference between this and NS_MEMORY_REPORTER_IMPLEMENT_HELPER
* The only difference between this and NS_MEMORY_REPORTER_IMPLEMENT_HELPER // is that the function used to implement GetAmount is fallible.
* is that the function used to implement GetAmount is fallible.
*/
#define NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT_HELPER(_classname, _path, _kind, _units, _amountFunction, _desc, _ts) \ #define NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT_HELPER(_classname, _path, _kind, _units, _amountFunction, _desc, _ts) \
class MemoryReporter_##_classname MOZ_FINAL : public nsIMemoryReporter { \ class MemoryReporter_##_classname MOZ_FINAL : public nsIMemoryReporter { \
public: \ public: \
NS_DECL_ISUPPORTS \ NS_DECL_ISUPPORTS \
NS_IMETHOD GetProcess(nsACString &process) { process.Truncate(); return NS_OK; } \ NS_IMETHOD GetProcess(nsACString &process) { process.Truncate(); return NS_OK; } \
NS_IMETHOD GetPath(nsACString &memoryPath) { memoryPath.AssignLiteral(_path); return NS_OK; } \ NS_IMETHOD GetPath(nsACString &memoryPath) { memoryPath.AssignLiteral(_path); return NS_OK; } \
NS_IMETHOD GetKind(int *kind) { *kind = _kind; return NS_OK; } \ NS_IMETHOD GetKind(int32_t *kind) { *kind = _kind; return NS_OK; } \
NS_IMETHOD GetUnits(int *units) { *units = _units; return NS_OK; } \ NS_IMETHOD GetUnits(int32_t *units) { *units = _units; return NS_OK; } \
NS_IMETHOD GetAmount(int64_t *amount) { return _amountFunction(amount); } \ NS_IMETHOD GetAmount(int64_t *amount) { return _amountFunction(amount); } \
NS_IMETHOD GetDescription(nsACString &desc) { desc.AssignLiteral(_desc); return NS_OK; }\ NS_IMETHOD GetDescription(nsACString &desc) { desc.AssignLiteral(_desc); return NS_OK; }\
}; \ }; \
@ -421,4 +424,82 @@ void RunReporters();
return moz_malloc_size_of(ptr); \ return moz_malloc_size_of(ptr); \
} }
namespace mozilla {
// The following base class reduces the amount of boilerplate code required for
// memory reporters. You just need to provide the following.
// - The constant values: path, kind, units, and description. They are passed
// to the MemoryReporterBase constructor.
// - An Amount() method. It can use the MallocSizeOf method if necessary.
//
// The class name of subclasses should match the path, minus the "explicit"
// (if present), and with "Reporter" at the end. For example:
// - "explicit/dom/xyzzy" --> DOMXyzzyReporter
// - "js-compartments/system" --> JSCompartmentsSystemReporter
//
class MemoryReporterBase : public nsIMemoryReporter
{
public:
MemoryReporterBase(const char* aPath, int32_t aKind, int32_t aUnits,
const char* aDescription)
: mPath(aPath)
, mKind(aKind)
, mUnits(aUnits)
, mDescription(aDescription)
{}
virtual ~MemoryReporterBase() {}
NS_DECL_ISUPPORTS
NS_IMETHOD GetProcess(nsACString& aProcess)
{
aProcess.Truncate();
return NS_OK;
}
NS_IMETHOD GetPath(nsACString& aPath)
{
aPath.Assign(mPath);
return NS_OK;
}
NS_IMETHOD GetKind(int32_t* aKind)
{
*aKind = mKind;
return NS_OK;
}
NS_IMETHOD GetUnits(int32_t* aUnits)
{
*aUnits = mUnits;
return NS_OK;
}
NS_IMETHOD GetAmount(int64_t* aAmount)
{
*aAmount = Amount();
return NS_OK;
}
NS_IMETHOD GetDescription(nsACString& aDescription)
{
aDescription.Assign(mDescription);
return NS_OK;
}
protected:
virtual int64_t Amount() = 0;
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(MallocSizeOf)
const nsCString mPath;
const int32_t mKind;
const int32_t mUnits;
const nsCString mDescription;
};
} // namespace mozilla
%} %}

View File

@ -1,5 +1,5 @@
/* -*- Mode: C++; tab-width: 50; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=4 et sw=4 tw=80: */ /* vim: set ts=8 sts=4 et sw=4 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public /* 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 * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -1083,6 +1083,11 @@ NS_IMETHODIMP nsMemoryReporter::GetDescription(nsACString &aDescription)
return NS_OK; return NS_OK;
} }
// Most memory reporters don't need thread safety, but some do. Make them all
// thread-safe just to be safe. Memory reporters are created and destroyed
// infrequently enough that the performance cost should be negligible.
NS_IMPL_THREADSAFE_ISUPPORTS1(MemoryReporterBase, nsIMemoryReporter)
nsresult nsresult
NS_RegisterMemoryReporter (nsIMemoryReporter *reporter) NS_RegisterMemoryReporter (nsIMemoryReporter *reporter)
{ {