Bug 803684 - Add a memory reporter for in-memory file data. r=khuey,njn

This commit is contained in:
Justin Lebar 2012-10-24 12:40:35 -04:00
parent 29ab4a7b54
commit a2894d092c
3 changed files with 149 additions and 5 deletions

View File

@ -21,7 +21,9 @@
#include "nsAutoPtr.h"
#include "mozilla/GuardObjects.h"
#include "mozilla/LinkedList.h"
#include "mozilla/StandardInteger.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/dom/DOMError.h"
#include "mozilla/dom/indexedDB/FileInfo.h"
#include "mozilla/dom/indexedDB/FileManager.h"
@ -360,7 +362,7 @@ public:
const nsAString& aName,
const nsAString& aContentType)
: nsDOMFile(aName, aContentType, aLength, UINT64_MAX),
mDataOwner(new DataOwner(aMemoryBuffer))
mDataOwner(new DataOwner(aMemoryBuffer, aLength))
{
NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data");
}
@ -370,7 +372,7 @@ public:
uint64_t aLength,
const nsAString& aContentType)
: nsDOMFile(aContentType, aLength),
mDataOwner(new DataOwner(aMemoryBuffer))
mDataOwner(new DataOwner(aMemoryBuffer, aLength))
{
NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data");
}
@ -391,18 +393,40 @@ protected:
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType);
friend class DataOwnerAdapter; // Needs to see DataOwner
class DataOwner {
// These classes need to see DataOwner.
friend class DataOwnerAdapter;
friend class nsDOMMemoryFileDataOwnerMemoryReporter;
class DataOwner : public mozilla::LinkedListElement<DataOwner> {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataOwner)
DataOwner(void* aMemoryBuffer)
DataOwner(void* aMemoryBuffer, uint64_t aLength)
: mData(aMemoryBuffer)
, mLength(aLength)
{
if (!sDataOwners) {
sDataOwners = new mozilla::LinkedList<DataOwner>();
EnsureMemoryReporterRegistered();
}
sDataOwners->insertBack(this);
}
~DataOwner() {
remove();
if (sDataOwners->isEmpty()) {
// Free the linked list if it's empty.
sDataOwners = nullptr;
}
PR_Free(mData);
}
static void EnsureMemoryReporterRegistered();
static bool sMemoryReporterRegistered;
static mozilla::StaticAutoPtr<mozilla::LinkedList<DataOwner> > sDataOwners;
void* mData;
uint64_t mLength;
};
// Used when backed by a memory store

View File

@ -18,6 +18,7 @@
#include "nsIFileStreams.h"
#include "nsIInputStream.h"
#include "nsIIPCSerializableInputStream.h"
#include "nsIMemoryReporter.h"
#include "nsIMIMEService.h"
#include "nsIPlatformCharset.h"
#include "nsISeekableStream.h"
@ -29,6 +30,8 @@
#include "nsBlobProtocolHandler.h"
#include "nsStringStream.h"
#include "nsJSUtils.h"
#include "nsPrintfCString.h"
#include "mozilla/SHA1.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/Preferences.h"
#include "mozilla/Attributes.h"
@ -687,6 +690,121 @@ nsDOMMemoryFile::GetInternalStream(nsIInputStream **aStream)
return DataOwnerAdapter::Create(mDataOwner, mStart, mLength, aStream);
}
/* static */ StaticAutoPtr<LinkedList<nsDOMMemoryFile::DataOwner> >
nsDOMMemoryFile::DataOwner::sDataOwners;
/* static */ bool
nsDOMMemoryFile::DataOwner::sMemoryReporterRegistered;
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMMemoryFileDataOwnerSizeOf,
"memory-file-data");
class nsDOMMemoryFileDataOwnerMemoryReporter
: public nsIMemoryMultiReporter
{
NS_DECL_ISUPPORTS
NS_IMETHOD GetName(nsACString& aName)
{
aName.AssignASCII("dom-memory-file-data-owner");
return NS_OK;
}
NS_IMETHOD GetExplicitNonHeap(int64_t *aResult)
{
// All of this reporter's memory is on the heap.
*aResult = 0;
return NS_OK;
}
NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *aCallback,
nsISupports *aClosure)
{
typedef nsDOMMemoryFile::DataOwner DataOwner;
if (!DataOwner::sDataOwners) {
return NS_OK;
}
const size_t LARGE_OBJECT_MIN_SIZE = 8 * 1024;
size_t smallObjectsTotal = 0;
for (DataOwner *owner = DataOwner::sDataOwners->getFirst();
owner; owner = owner->getNext()) {
size_t size = DOMMemoryFileDataOwnerSizeOf(owner->mData);
if (size < LARGE_OBJECT_MIN_SIZE) {
smallObjectsTotal += size;
}
else {
SHA1Sum sha1;
sha1.update(owner->mData, owner->mLength);
uint8_t digest[SHA1Sum::HashSize]; // SHA1 digests are 20 bytes long.
sha1.finish(digest);
nsAutoCString digestString;
for (uint8_t i = 0; i < sizeof(digest); i++) {
digestString.AppendPrintf("%02x", digest[i]);
}
nsresult rv = aCallback->Callback(
/* process */ NS_LITERAL_CSTRING(""),
nsPrintfCString(
"explicit/dom/memory-file-data/large/file(length=%d, sha1=%s)",
owner->mLength, digestString.get()),
nsIMemoryReporter::KIND_HEAP,
nsIMemoryReporter::UNITS_BYTES,
size,
nsPrintfCString(
"Memory used to back a memory file of length %d. The file has a "
"sha1 of %s.\n\n"
"Note that the allocator may round up a memory file's length -- "
"that is, an N-byte memory file may take up more than N bytes of "
"memory.",
owner->mLength, digestString.get()),
aClosure);
NS_ENSURE_SUCCESS(rv, rv);
}
}
if (smallObjectsTotal > 0) {
nsresult rv = aCallback->Callback(
/* process */ NS_LITERAL_CSTRING(""),
NS_LITERAL_CSTRING("explicit/dom/memory-file-data/small"),
nsIMemoryReporter::KIND_HEAP,
nsIMemoryReporter::UNITS_BYTES,
smallObjectsTotal,
nsPrintfCString(
"Memory used to back small memory files (less than %d bytes each).\n\n"
"Note that the allocator may round up a memory file's length -- "
"that is, an N-byte memory file may take up more than N bytes of "
"memory."),
aClosure);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
};
NS_IMPL_ISUPPORTS1(nsDOMMemoryFileDataOwnerMemoryReporter,
nsIMemoryMultiReporter);
/* static */ void
nsDOMMemoryFile::DataOwner::EnsureMemoryReporterRegistered()
{
if (sMemoryReporterRegistered) {
return;
}
nsRefPtr<nsDOMMemoryFileDataOwnerMemoryReporter> reporter = new
nsDOMMemoryFileDataOwnerMemoryReporter();
NS_RegisterMemoryMultiReporter(reporter);
sMemoryReporterRegistered = true;
}
////////////////////////////////////////////////////////////////////////////
// nsDOMFileList implementation

View File

@ -139,6 +139,8 @@ STATIC_LIBS += \
snappy_s \
$(NULL)
OS_LIBS += $(call EXPAND_LIBNAME_PATH,mfbt,$(DEPTH)/mfbt)
# component libraries
COMPONENT_LIBS += \
necko \