Bug 964039 - Memory used by the new cache backend is not reported, r=michal

This commit is contained in:
Honza Bambas 2014-02-27 00:11:40 +01:00
Родитель d238a88c49
Коммит 260271bf43
21 изменённых файлов: 681 добавлений и 31 удалений

Просмотреть файл

@ -15,6 +15,7 @@
#include "nsICacheStorage.h"
#include "nsISerializable.h"
#include "nsIStreamTransportService.h"
#include "nsISizeOf.h"
#include "nsComponentManagerUtils.h"
#include "nsServiceManagerUtils.h"
@ -1554,5 +1555,40 @@ NS_IMETHODIMP CacheOutputCloseListener::Run()
return NS_OK;
}
// Memory reporting
size_t CacheEntry::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
size_t n = 0;
nsCOMPtr<nsISizeOf> sizeOf;
n += mCallbacks.SizeOfExcludingThis(mallocSizeOf);
if (mFile) {
n += mFile->SizeOfIncludingThis(mallocSizeOf);
}
sizeOf = do_QueryInterface(mURI);
if (sizeOf) {
n += sizeOf->SizeOfIncludingThis(mallocSizeOf);
}
n += mEnhanceID.SizeOfExcludingThisIfUnshared(mallocSizeOf);
n += mStorageID.SizeOfExcludingThisIfUnshared(mallocSizeOf);
// mDoomCallback is an arbitrary class that is probably reported elsewhere.
// mOutputStream is reported in mFile.
// mWriter is one of many handles we create, but (intentionally) not keep
// any reference to, so those unfortunatelly cannot be reported. Handles are
// small, though.
// mSecurityInfo doesn't impl nsISizeOf.
return n;
}
size_t CacheEntry::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
return mallocSizeOf(this) + SizeOfExcludingThis(mallocSizeOf);
}
} // net
} // mozilla

Просмотреть файл

@ -105,6 +105,10 @@ public:
double mFrecency;
uint32_t mSortingExpirationTime;
// Memory reporting
size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
private:
virtual ~CacheEntry();

Просмотреть файл

@ -918,7 +918,7 @@ CacheFile::Unlock()
}
void
CacheFile::AssertOwnsLock()
CacheFile::AssertOwnsLock() const
{
mLock.AssertCurrentThreadOwns();
}
@ -1554,5 +1554,57 @@ CacheFile::InitIndexEntry()
return NS_OK;
}
// Memory reporting
namespace { // anon
size_t
CollectChunkSize(uint32_t const & aIdx,
nsRefPtr<mozilla::net::CacheFileChunk> const & aChunk,
mozilla::MallocSizeOf mallocSizeOf, void* aClosure)
{
return aChunk->SizeOfIncludingThis(mallocSizeOf);
}
} // anon
size_t
CacheFile::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
CacheFileAutoLock lock(const_cast<CacheFile*>(this));
size_t n = 0;
n += mChunks.SizeOfExcludingThis(CollectChunkSize, mallocSizeOf);
n += mCachedChunks.SizeOfExcludingThis(CollectChunkSize, mallocSizeOf);
if (mMetadata) {
n += mMetadata->SizeOfIncludingThis(mallocSizeOf);
}
// Input streams are not elsewhere reported.
n += mInputs.SizeOfExcludingThis(mallocSizeOf);
for (uint32_t i = 0; i < mInputs.Length(); ++i) {
n += mInputs[i]->SizeOfIncludingThis(mallocSizeOf);
}
// Output streams are not elsewhere reported.
if (mOutput) {
n += mOutput->SizeOfIncludingThis(mallocSizeOf);
}
// The listeners are usually classes reported just above.
n += mChunkListeners.SizeOfExcludingThis(nullptr, mallocSizeOf);
n += mObjsToRelease.SizeOfExcludingThis(mallocSizeOf);
// mHandle reported directly from CacheFileIOManager.
return n;
}
size_t
CacheFile::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
return mallocSizeOf(this) + SizeOfExcludingThis(mallocSizeOf);
}
} // net
} // mozilla

Просмотреть файл

@ -99,6 +99,10 @@ public:
void Key(nsACString& aKey) { aKey = mKey; }
bool IsDoomed();
// Memory reporting
size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
private:
friend class CacheFileIOManager;
friend class CacheFileChunk;
@ -111,7 +115,7 @@ private:
void Lock();
void Unlock();
void AssertOwnsLock();
void AssertOwnsLock() const;
void ReleaseOutsideLock(nsISupports *aObject);
nsresult GetChunk(uint32_t aIndex, bool aWriter,

Просмотреть файл

@ -597,7 +597,7 @@ CacheFileChunk::OnFileRenamed(CacheFileHandle *aHandle, nsresult aResult)
}
bool
CacheFileChunk::IsReady()
CacheFileChunk::IsReady() const
{
mFile->AssertOwnsLock();
@ -605,7 +605,7 @@ CacheFileChunk::IsReady()
}
bool
CacheFileChunk::IsDirty()
CacheFileChunk::IsDirty() const
{
mFile->AssertOwnsLock();
@ -613,7 +613,7 @@ CacheFileChunk::IsDirty()
}
char *
CacheFileChunk::BufForWriting()
CacheFileChunk::BufForWriting() const
{
mFile->AssertOwnsLock();
@ -627,7 +627,7 @@ CacheFileChunk::BufForWriting()
}
const char *
CacheFileChunk::BufForReading()
CacheFileChunk::BufForReading() const
{
mFile->AssertOwnsLock();
@ -677,5 +677,24 @@ CacheFileChunk::EnsureBufSize(uint32_t aBufSize)
DoMemoryReport(MemorySize());
}
// Memory reporting
size_t
CacheFileChunk::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
size_t n = 0;
n += mallocSizeOf(mBuf);
n += mallocSizeOf(mRWBuf);
n += mValidityMap.SizeOfExcludingThis(mallocSizeOf);
return n;
}
size_t
CacheFileChunk::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
return mallocSizeOf(this) + SizeOfExcludingThis(mallocSizeOf);
}
} // net
} // mozilla

Просмотреть файл

@ -94,13 +94,17 @@ public:
NS_IMETHOD OnEOFSet(CacheFileHandle *aHandle, nsresult aResult);
NS_IMETHOD OnFileRenamed(CacheFileHandle *aHandle, nsresult aResult);
bool IsReady();
bool IsDirty();
bool IsReady() const;
bool IsDirty() const;
char * BufForWriting();
const char * BufForReading();
char * BufForWriting() const;
const char * BufForReading() const;
void EnsureBufSize(uint32_t aBufSize);
uint32_t MemorySize() { return mRWBufSize + mBufSize; }
uint32_t MemorySize() const { return mRWBufSize + mBufSize; }
// Memory reporting
size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
private:
friend class CacheFileInputStream;

Просмотреть файл

@ -17,6 +17,7 @@
#include "nsITimer.h"
#include "nsISimpleEnumerator.h"
#include "nsIDirectoryEnumerator.h"
#include "nsISizeOf.h"
#include "mozilla/Telemetry.h"
#include "mozilla/DebugOnly.h"
#include "nsDirectoryServiceUtils.h"
@ -163,7 +164,7 @@ CacheFileHandle::Log()
}
uint32_t
CacheFileHandle::FileSizeInK()
CacheFileHandle::FileSizeInK() const
{
MOZ_ASSERT(mFileSize != -1);
uint64_t size64 = mFileSize;
@ -183,6 +184,30 @@ CacheFileHandle::FileSizeInK()
return size;
}
// Memory reporting
size_t
CacheFileHandle::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
size_t n = 0;
nsCOMPtr<nsISizeOf> sizeOf;
sizeOf = do_QueryInterface(mFile);
if (sizeOf) {
n += sizeOf->SizeOfIncludingThis(mallocSizeOf);
}
n += mallocSizeOf(mFD);
n += mKey.SizeOfExcludingThisIfUnshared(mallocSizeOf);
return n;
}
size_t
CacheFileHandle::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
return mallocSizeOf(this) + SizeOfExcludingThis(mallocSizeOf);
}
/******************************************************************************
* CacheFileHandles::HandleHashKey
*****************************************************************************/
@ -242,6 +267,20 @@ CacheFileHandles::HandleHashKey::AssertHandlesState()
#endif
size_t
CacheFileHandles::HandleHashKey::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
size_t n = 0;
n += mallocSizeOf(mHash);
for (uint32_t i = 0; i < mHandles.Length(); ++i) {
n += mHandles[i]->SizeOfIncludingThis(mallocSizeOf);
}
return n;
}
/******************************************************************************
* CacheFileHandles
*****************************************************************************/
@ -431,6 +470,28 @@ CacheFileHandles::Log(CacheFileHandlesEntry *entry)
}
#endif
// Memory reporting
namespace { // anon
size_t
CollectHandlesMemory(CacheFileHandles::HandleHashKey* key,
mozilla::MallocSizeOf mallocSizeOf,
void *arg)
{
return key->SizeOfExcludingThis(mallocSizeOf);
}
} // anon
size_t
CacheFileHandles::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
return mTable.SizeOfExcludingThis(&CollectHandlesMemory, mallocSizeOf);
}
// Events
class ShutdownEvent : public nsRunnable {
@ -3137,5 +3198,128 @@ CacheFileIOManager::NSPRHandleUsed(CacheFileHandle *aHandle)
mHandlesByLastUsed.AppendElement(aHandle);
}
// Memory reporting
namespace { // anon
// A helper class that dispatches and waits for an event that gets result of
// CacheFileIOManager->mHandles.SizeOfExcludingThis() on the I/O thread
// to safely get handles memory report.
// We must do this, since the handle list is only accessed and managed w/o
// locking on the I/O thread. That is by design.
class SizeOfHandlesRunnable : public nsRunnable
{
public:
SizeOfHandlesRunnable(mozilla::MallocSizeOf mallocSizeOf,
CacheFileHandles const &handles,
nsTArray<nsRefPtr<CacheFileHandle> > const &specialHandles)
: mMonitor("SizeOfHandlesRunnable.mMonitor")
, mMallocSizeOf(mallocSizeOf)
, mHandles(handles)
, mSpecialHandles(specialHandles)
{
}
size_t Get(CacheIOThread* thread)
{
nsCOMPtr<nsIEventTarget> target = thread->Target();
if (!target) {
NS_ERROR("If we have the I/O thread we also must have the I/O target");
return 0;
}
mozilla::MonitorAutoLock mon(mMonitor);
nsresult rv = target->Dispatch(this, nsIEventTarget::DISPATCH_NORMAL);
if (NS_FAILED(rv)) {
NS_ERROR("Dispatch failed, cannot do memory report of CacheFileHandles");
return 0;
}
mon.Wait();
return mSize;
}
NS_IMETHOD Run()
{
mozilla::MonitorAutoLock mon(mMonitor);
// Excluding this since the object itself is a member of CacheFileIOManager
// reported in CacheFileIOManager::SizeOfIncludingThis as part of |this|.
mSize = mHandles.SizeOfExcludingThis(mMallocSizeOf);
for (uint32_t i = 0; i < mSpecialHandles.Length(); ++i) {
mSize += mSpecialHandles[i]->SizeOfIncludingThis(mMallocSizeOf);
}
mon.Notify();
return NS_OK;
}
private:
mozilla::Monitor mMonitor;
mozilla::MallocSizeOf mMallocSizeOf;
CacheFileHandles const &mHandles;
nsTArray<nsRefPtr<CacheFileHandle> > const &mSpecialHandles;
size_t mSize;
};
} // anon
size_t
CacheFileIOManager::SizeOfExcludingThisInternal(mozilla::MallocSizeOf mallocSizeOf) const
{
size_t n = 0;
nsCOMPtr<nsISizeOf> sizeOf;
if (mIOThread) {
n += mIOThread->SizeOfIncludingThis(mallocSizeOf);
// mHandles and mSpecialHandles must be accessed only on the I/O thread,
// must sync dispatch.
nsRefPtr<SizeOfHandlesRunnable> sizeOfHandlesRunnable =
new SizeOfHandlesRunnable(mallocSizeOf, mHandles, mSpecialHandles);
n += sizeOfHandlesRunnable->Get(mIOThread);
}
// mHandlesByLastUsed just refers handles reported by mHandles.
sizeOf = do_QueryInterface(mCacheDirectory);
if (sizeOf)
n += sizeOf->SizeOfIncludingThis(mallocSizeOf);
sizeOf = do_QueryInterface(mMetadataWritesTimer);
if (sizeOf)
n += sizeOf->SizeOfIncludingThis(mallocSizeOf);
sizeOf = do_QueryInterface(mTrashTimer);
if (sizeOf)
n += sizeOf->SizeOfIncludingThis(mallocSizeOf);
sizeOf = do_QueryInterface(mTrashDir);
if (sizeOf)
n += sizeOf->SizeOfIncludingThis(mallocSizeOf);
for (uint32_t i = 0; i < mFailedTrashDirs.Length(); ++i) {
n += mFailedTrashDirs[i].SizeOfExcludingThisIfUnshared(mallocSizeOf);
}
return n;
}
// static
size_t
CacheFileIOManager::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
{
if (!gInstance)
return 0;
return gInstance->SizeOfExcludingThisInternal(mallocSizeOf);
}
// static
size_t
CacheFileIOManager::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
{
return mallocSizeOf(gInstance) + SizeOfExcludingThis(mallocSizeOf);
}
} // net
} // mozilla

Просмотреть файл

@ -45,16 +45,20 @@ public:
CacheFileHandle(const nsACString &aKey, bool aPriority);
CacheFileHandle(const CacheFileHandle &aOther);
void Log();
bool IsDoomed() { return mIsDoomed; }
const SHA1Sum::Hash *Hash() { return mHash; }
int64_t FileSize() { return mFileSize; }
uint32_t FileSizeInK();
bool IsPriority() { return mPriority; }
bool FileExists() { return mFileExists; }
bool IsClosed() { return mClosed; }
bool IsSpecialFile() { return !mHash; }
bool IsDoomed() const { return mIsDoomed; }
const SHA1Sum::Hash *Hash() const { return mHash; }
int64_t FileSize() const { return mFileSize; }
uint32_t FileSizeInK() const;
bool IsPriority() const { return mPriority; }
bool FileExists() const { return mFileExists; }
bool IsClosed() const { return mClosed; }
bool IsSpecialFile() const { return !mHash; }
nsCString & Key() { return mKey; }
// Memory reporting
size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
private:
friend class CacheFileIOManager;
friend class CacheFileHandles;
@ -93,6 +97,10 @@ public:
void Log(CacheFileHandlesEntry *entry);
#endif
// Memory reporting
size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
class HandleHashKey : public PLDHashEntryHdr
{
public:
@ -132,8 +140,8 @@ public:
already_AddRefed<CacheFileHandle> GetNewestHandle();
void GetHandles(nsTArray<nsRefPtr<CacheFileHandle> > &aResult);
SHA1Sum::Hash *Hash() { return mHash; }
bool IsEmpty() { return mHandles.Length() == 0; }
SHA1Sum::Hash *Hash() const { return mHash; }
bool IsEmpty() const { return mHandles.Length() == 0; }
enum { ALLOW_MEMMOVE = true };
@ -141,6 +149,10 @@ public:
void AssertHandlesState();
#endif
// Memory reporting
size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
private:
nsAutoArrayPtr<SHA1Sum::Hash> mHash;
// Use weak pointers since the hash table access is on a single thread
@ -264,6 +276,10 @@ public:
static void GetCacheDirectory(nsIFile** result);
// Memory reporting
static size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
static size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
private:
friend class CacheFileHandle;
friend class CacheFileChunk;
@ -330,6 +346,9 @@ private:
nsresult UnscheduleMetadataWriteInternal(CacheFile * aFile);
nsresult ShutdownMetadataWriteSchedulingInternal();
// Memory reporting (private part)
size_t SizeOfExcludingThisInternal(mozilla::MallocSizeOf mallocSizeOf) const;
static CacheFileIOManager *gInstance;
TimeStamp mStartTime;
bool mShuttingDown;

Просмотреть файл

@ -630,5 +630,17 @@ CacheFileInputStream::MaybeNotifyListener()
}
}
// Memory reporting
size_t
CacheFileInputStream::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
// Everything the stream keeps a reference to is already reported somewhere else.
// mFile reports itself.
// mChunk reported as part of CacheFile.
// mCallback is usually CacheFile or a class that is reported elsewhere.
return mallocSizeOf(this);
}
} // net
} // mozilla

Просмотреть файл

@ -35,6 +35,9 @@ public:
CacheFileChunk *aChunk);
NS_IMETHOD OnChunkUpdated(CacheFileChunk *aChunk);
// Memory reporting
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
private:
virtual ~CacheFileInputStream();

Просмотреть файл

@ -861,5 +861,27 @@ CacheFileMetadata::ParseKey(const nsACString &aKey)
return NS_OK;
}
// Memory reporting
size_t
CacheFileMetadata::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
size_t n = 0;
// mHandle reported via CacheFileIOManager.
n += mKey.SizeOfExcludingThisIfUnshared(mallocSizeOf);
n += mallocSizeOf(mHashArray);
n += mallocSizeOf(mBuf);
n += mallocSizeOf(mWriteBuf);
// mListener is usually the owning CacheFile.
return n;
}
size_t
CacheFileMetadata::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
return mallocSizeOf(this) + SizeOfExcludingThis(mallocSizeOf);
}
} // net
} // mozilla

Просмотреть файл

@ -108,6 +108,10 @@ public:
NS_IMETHOD OnEOFSet(CacheFileHandle *aHandle, nsresult aResult);
NS_IMETHOD OnFileRenamed(CacheFileHandle *aHandle, nsresult aResult);
// Memory reporting
size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
private:
virtual ~CacheFileMetadata();

Просмотреть файл

@ -391,5 +391,18 @@ CacheFileOutputStream::NotifyListener()
asyncCallback->OnOutputStreamReady(this);
}
// Memory reporting
size_t
CacheFileOutputStream::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
// Everything the stream keeps a reference to is already reported somewhere else.
// mFile reports itself.
// mChunk reported as part of CacheFile.
// mCloseListener is CacheEntry, already reported.
// mCallback is usually CacheFile or a class that is reported elsewhere.
return mallocSizeOf(this);
}
} // net
} // mozilla

Просмотреть файл

@ -38,6 +38,9 @@ public:
void NotifyCloseListener();
// Memory reporting
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
private:
virtual ~CacheFileOutputStream();

Просмотреть файл

@ -251,5 +251,28 @@ NS_IMETHODIMP CacheIOThread::AfterProcessNextEvent(nsIThreadInternal *thread, ui
return NS_OK;
}
// Memory reporting
size_t CacheIOThread::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
MonitorAutoLock lock(const_cast<CacheIOThread*>(this)->mMonitor);
size_t n = 0;
n += mallocSizeOf(mThread);
for (uint32_t level = 0; level < LAST_LEVEL; ++level) {
n += mEventQueue[level].SizeOfExcludingThis(mallocSizeOf);
// Events referenced by the queues are arbitrary objects we cannot be sure
// are reported elsewhere as well as probably not implementing nsISizeOf
// interface. Deliberatly omitting them from reporting here.
}
return n;
}
size_t CacheIOThread::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
return mallocSizeOf(this) + SizeOfExcludingThis(mallocSizeOf);
}
} // net
} // mozilla

Просмотреть файл

@ -45,6 +45,10 @@ public:
nsresult Shutdown();
already_AddRefed<nsIEventTarget> Target();
// Memory reporting
size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
private:
static void ThreadFunc(void* aClosure);
void ThreadFunc();

Просмотреть файл

@ -10,6 +10,7 @@
#include "nsThreadUtils.h"
#include "nsISimpleEnumerator.h"
#include "nsIDirectoryEnumerator.h"
#include "nsISizeOf.h"
#include "nsPrintfCString.h"
#include "mozilla/DebugOnly.h"
#include "prinrval.h"
@ -3268,5 +3269,73 @@ CacheIndex::OnFileRenamed(CacheFileHandle *aHandle, nsresult aResult)
return NS_OK;
}
// Memory reporting
namespace { // anon
size_t
CollectIndexEntryMemory(CacheIndexEntry* aEntry,
mozilla::MallocSizeOf mallocSizeOf,
void *arg)
{
return aEntry->SizeOfExcludingThis(mallocSizeOf);
}
} // anon
size_t
CacheIndex::SizeOfExcludingThisInternal(mozilla::MallocSizeOf mallocSizeOf) const
{
CacheIndexAutoLock lock(const_cast<CacheIndex*>(this));
size_t n = 0;
nsCOMPtr<nsISizeOf> sizeOf;
// mIndexHandle and mJournalHandle are reported via SizeOfHandlesRunnable
// in CacheFileIOManager::SizeOfExcludingThisInternal as part of special
// handles array.
sizeOf = do_QueryInterface(mCacheDirectory);
if (sizeOf) {
n += sizeOf->SizeOfIncludingThis(mallocSizeOf);
}
sizeOf = do_QueryInterface(mTimer);
if (sizeOf) {
n += sizeOf->SizeOfIncludingThis(mallocSizeOf);
}
n += mallocSizeOf(mRWBuf);
n += mallocSizeOf(mRWHash);
n += mIndex.SizeOfExcludingThis(&CollectIndexEntryMemory, mallocSizeOf);
n += mPendingUpdates.SizeOfExcludingThis(&CollectIndexEntryMemory, mallocSizeOf);
n += mTmpJournal.SizeOfExcludingThis(&CollectIndexEntryMemory, mallocSizeOf);
// mFrecencyArray and mExpirationArray items are reported by
// mIndex/mPendingUpdates
n += mFrecencyArray.SizeOfExcludingThis(mallocSizeOf);
n += mExpirationArray.SizeOfExcludingThis(mallocSizeOf);
return n;
}
// static
size_t
CacheIndex::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
{
if (!gInstance)
return 0;
return gInstance->SizeOfExcludingThisInternal(mallocSizeOf);
}
// static
size_t
CacheIndex::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
{
return mallocSizeOf(gInstance) + SizeOfExcludingThis(mallocSizeOf);
}
} // net
} // mozilla

Просмотреть файл

@ -86,7 +86,7 @@ public:
{
MOZ_COUNT_CTOR(CacheIndexEntry);
mRec = new CacheIndexRecord();
LOG(("CacheIndexEntry::CacheIndexEntry() - Created record [rec=%p]", mRec));
LOG(("CacheIndexEntry::CacheIndexEntry() - Created record [rec=%p]", mRec.get()));
memcpy(&mRec->mHash, aKey, sizeof(SHA1Sum::Hash));
}
CacheIndexEntry(const CacheIndexEntry& aOther)
@ -97,8 +97,7 @@ public:
{
MOZ_COUNT_DTOR(CacheIndexEntry);
LOG(("CacheIndexEntry::~CacheIndexEntry() - Deleting record [rec=%p]",
mRec));
delete mRec;
mRec.get()));
}
// KeyEquals(): does this entry match this key?
@ -247,6 +246,17 @@ public:
GetExpirationTime(), GetFileSize()));
}
// Memory reporting
size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
return mallocSizeOf(mRec.get());
}
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
return mallocSizeOf(this) + SizeOfExcludingThis(mallocSizeOf);
}
private:
friend class CacheIndex;
friend class CacheIndexEntryAutoManage;
@ -273,7 +283,7 @@ private:
// FileSize in kilobytes
static const uint32_t kFileSizeMask = 0x00FFFFFF;
CacheIndexRecord *mRec;
nsAutoPtr<CacheIndexRecord> mRec;
};
class CacheIndexStats
@ -520,6 +530,9 @@ public:
// Returns cache size in kB.
static nsresult GetCacheSize(uint32_t *_retval);
// Memory reporting
static size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
static size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
private:
friend class CacheIndexEntryAutoManage;
@ -762,6 +775,9 @@ private:
void RemoveRecordFromFrecencyArray(CacheIndexRecord *aRecord);
void RemoveRecordFromExpirationArray(CacheIndexRecord *aRecord);
// Memory reporting (private part)
size_t SizeOfExcludingThisInternal(mozilla::MallocSizeOf mallocSizeOf) const;
static CacheIndex *gInstance;
nsCOMPtr<nsIFile> mCacheDirectory;

Просмотреть файл

@ -25,7 +25,24 @@ namespace net {
// This dance is needed to make CacheEntryTable declarable-only in headers
// w/o exporting CacheEntry.h file to make nsNetModule.cpp compilable.
typedef nsRefPtrHashtable<nsCStringHashKey, CacheEntry> TCacheEntryTable;
class CacheEntryTable : public TCacheEntryTable { };
class CacheEntryTable : public TCacheEntryTable
{
public:
enum EType
{
MEMORY_ONLY,
ALL_ENTRIES
};
CacheEntryTable(EType aType) : mType(aType) { }
EType Type() const
{
return mType;
}
private:
EType const mType;
CacheEntryTable() MOZ_DELETE;
};
class CacheStorage : public nsICacheStorage
{

Просмотреть файл

@ -6,6 +6,7 @@
#include "CacheStorageService.h"
#include "CacheFileIOManager.h"
#include "CacheObserver.h"
#include "CacheIndex.h"
#include "nsICacheStorageVisitor.h"
#include "nsIObserverService.h"
@ -68,7 +69,7 @@ CacheMemoryConsumer::DoMemoryReport(uint32_t aCurrentSize)
CacheStorageService::Self()->OnMemoryConsumptionChange(this, aCurrentSize);
}
NS_IMPL_ISUPPORTS1(CacheStorageService, nsICacheStorageService)
NS_IMPL_ISUPPORTS2(CacheStorageService, nsICacheStorageService, nsIMemoryReporter)
CacheStorageService* CacheStorageService::sSelf = nullptr;
@ -84,6 +85,8 @@ CacheStorageService::CacheStorageService()
sSelf = this;
sGlobalEntryTables = new GlobalEntryTables();
RegisterStrongMemoryReporter(this);
}
CacheStorageService::~CacheStorageService()
@ -584,7 +587,7 @@ void CacheFilesDeletor::Callback()
nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
if (obsSvc) {
obsSvc->NotifyObservers(CacheStorageService::Self(),
obsSvc->NotifyObservers(CacheStorageService::SelfISupports(),
"cacheservice:empty-cache",
nullptr);
}
@ -973,7 +976,7 @@ CacheStorageService::RecordMemoryOnlyEntry(CacheEntry* aEntry,
return;
}
entries = new CacheEntryTable();
entries = new CacheEntryTable(CacheEntryTable::MEMORY_ONLY);
sGlobalEntryTables->Put(memoryStorageID, entries);
LOG((" new memory-only storage table for %s", memoryStorageID.get()));
}
@ -1191,7 +1194,7 @@ CacheStorageService::AddStorageEntry(nsCSubstring const& aContextKey,
// Ensure storage table
CacheEntryTable* entries;
if (!sGlobalEntryTables->Get(aContextKey, &entries)) {
entries = new CacheEntryTable();
entries = new CacheEntryTable(CacheEntryTable::ALL_ENTRIES);
sGlobalEntryTables->Put(aContextKey, entries);
LOG((" new storage entries table for context %s", aContextKey.BeginReading()));
}
@ -1469,6 +1472,136 @@ CacheStorageService::CacheFileDoomed(nsILoadContextInfo* aLoadContextInfo,
return NS_OK;
}
// nsIMemoryReporter
size_t
CacheStorageService::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
CacheStorageService::Self()->Lock().AssertCurrentThreadOwns();
size_t n = 0;
// The elemets are referenced by sGlobalEntryTables and are reported from there
n += mFrecencyArray.SizeOfExcludingThis(mallocSizeOf);
// The elemets are referenced by sGlobalEntryTables and are reported from there
n += mExpirationArray.SizeOfExcludingThis(mallocSizeOf);
// Entries reported manually in CacheStorageService::CollectReports callback
if (sGlobalEntryTables) {
n += sGlobalEntryTables->SizeOfIncludingThis(nullptr, mallocSizeOf);
}
return n;
}
size_t
CacheStorageService::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
return mallocSizeOf(this) + SizeOfExcludingThis(mallocSizeOf);
}
namespace { // anon
class ReportStorageMemoryData
{
public:
nsIMemoryReporterCallback *mHandleReport;
nsISupports *mData;
};
size_t CollectEntryMemory(nsACString const & aKey,
nsRefPtr<mozilla::net::CacheEntry> const & aEntry,
mozilla::MallocSizeOf mallocSizeOf,
void * aClosure)
{
CacheStorageService::Self()->Lock().AssertCurrentThreadOwns();
CacheEntryTable* aTable = static_cast<CacheEntryTable*>(aClosure);
size_t n = 0;
n += aKey.SizeOfExcludingThisIfUnshared(mallocSizeOf);
// Bypass memory-only entries, those will be reported when iterating
// the memory only table. Memory-only entries are stored in both ALL_ENTRIES
// and MEMORY_ONLY hashtables.
if (aTable->Type() == CacheEntryTable::MEMORY_ONLY || aEntry->UsingDisk())
n += aEntry->SizeOfIncludingThis(mallocSizeOf);
return n;
}
PLDHashOperator ReportStorageMemory(const nsACString& aKey,
CacheEntryTable* aTable,
void* aClosure)
{
CacheStorageService::Self()->Lock().AssertCurrentThreadOwns();
size_t size = aTable->SizeOfIncludingThis(&CollectEntryMemory,
CacheStorageService::MallocSizeOf,
aTable);
ReportStorageMemoryData& data = *static_cast<ReportStorageMemoryData*>(aClosure);
data.mHandleReport->Callback(
EmptyCString(),
nsPrintfCString("explicit/network/cache2/%s-storage(%s)",
aTable->Type() == CacheEntryTable::MEMORY_ONLY ? "memory" : "disk",
aKey.BeginReading()),
nsIMemoryReporter::KIND_HEAP,
nsIMemoryReporter::UNITS_BYTES,
size,
NS_LITERAL_CSTRING("Memory used by the cache storage."),
data.mData);
return PL_DHASH_NEXT;
}
} // anon
NS_IMETHODIMP
CacheStorageService::CollectReports(nsIMemoryReporterCallback* aHandleReport, nsISupports* aData)
{
nsresult rv;
rv = MOZ_COLLECT_REPORT(
"explicit/network/cache2/io", KIND_HEAP, UNITS_BYTES,
CacheFileIOManager::SizeOfIncludingThis(MallocSizeOf),
"Memory used by the cache IO manager.");
if (NS_WARN_IF(NS_FAILED(rv)))
return rv;
rv = MOZ_COLLECT_REPORT(
"explicit/network/cache2/index", KIND_HEAP, UNITS_BYTES,
CacheIndex::SizeOfIncludingThis(MallocSizeOf),
"Memory used by the cache index.");
if (NS_WARN_IF(NS_FAILED(rv)))
return rv;
MutexAutoLock lock(mLock);
// Report the service instance, this doesn't report entries, done lower
rv = MOZ_COLLECT_REPORT(
"explicit/network/cache2/service", KIND_HEAP, UNITS_BYTES,
SizeOfIncludingThis(MallocSizeOf),
"Memory used by the cache storage service.");
if (NS_WARN_IF(NS_FAILED(rv)))
return rv;
// Report all entries, each storage separately (by the context key)
//
// References are:
// sGlobalEntryTables to N CacheEntryTable
// CacheEntryTable to N CacheEntry
// CacheEntry to 1 CacheFile
// CacheFile to
// N CacheFileChunk (keeping the actual data)
// 1 CacheFileMetadata (keeping http headers etc.)
// 1 CacheFileOutputStream
// N CacheFileInputStream
ReportStorageMemoryData data;
data.mHandleReport = aHandleReport;
data.mData = aData;
sGlobalEntryTables->EnumerateRead(&ReportStorageMemory, &data);
return NS_OK;
}
} // net
} // mozilla

Просмотреть файл

@ -6,6 +6,7 @@
#define CacheStorageService__h__
#include "nsICacheStorageService.h"
#include "nsIMemoryReporter.h"
#include "nsClassHashtable.h"
#include "nsString.h"
@ -43,10 +44,12 @@ protected:
};
class CacheStorageService : public nsICacheStorageService
, public nsIMemoryReporter
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSICACHESTORAGESERVICE
NS_DECL_NSIMEMORYREPORTER
CacheStorageService();
@ -57,12 +60,18 @@ public:
static void WipeCacheDirectory(uint32_t aVersion);
static CacheStorageService* Self() { return sSelf; }
static nsISupports* SelfISupports() { return static_cast<nsICacheStorageService*>(Self()); }
nsresult Dispatch(nsIRunnable* aEvent);
static bool IsRunning() { return sSelf && !sSelf->mShutdown; }
static bool IsOnManagementThread();
already_AddRefed<nsIEventTarget> Thread() const;
mozilla::Mutex& Lock() { return mLock; }
// Memory reporting
size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
private:
virtual ~CacheStorageService();
void ShutdownBackground();