Bug 590790 part 2 - Add memory reporter for VectorImage's SVGDocumentWrapper's document. r=dholbert, r=njn, r=seth

This commit is contained in:
Jonathan Watt 2014-05-08 10:53:00 +01:00
parent 40b8534051
commit 03e0ca5e7f
7 changed files with 135 additions and 17 deletions

View File

@ -10,6 +10,7 @@
#include "imgIContainer.h" #include "imgIContainer.h"
#include "imgStatusTracker.h" #include "imgStatusTracker.h"
#include "ImageURL.h" #include "ImageURL.h"
#include "nsStringFwd.h"
class nsIRequest; class nsIRequest;
class nsIInputStream; class nsIInputStream;
@ -84,6 +85,13 @@ public:
virtual size_t NonHeapSizeOfDecoded() const = 0; virtual size_t NonHeapSizeOfDecoded() const = 0;
virtual size_t OutOfProcessSizeOfDecoded() const = 0; virtual size_t OutOfProcessSizeOfDecoded() const = 0;
/**
* Gets the size of the memory taken up for the parsed vector image's
* document (e.g. SVGDocument), and returns the document's URL via the
* aDocURL outparam.
*/
virtual size_t HeapSizeOfVectorImageDocument(nsACString* aDocURL = nullptr) const = 0;
virtual void IncrementAnimationConsumers() = 0; virtual void IncrementAnimationConsumers() = 0;
virtual void DecrementAnimationConsumers() = 0; virtual void DecrementAnimationConsumers() = 0;
#ifdef DEBUG #ifdef DEBUG

View File

@ -35,6 +35,10 @@ public:
virtual size_t NonHeapSizeOfDecoded() const MOZ_OVERRIDE; virtual size_t NonHeapSizeOfDecoded() const MOZ_OVERRIDE;
virtual size_t OutOfProcessSizeOfDecoded() const MOZ_OVERRIDE; virtual size_t OutOfProcessSizeOfDecoded() const MOZ_OVERRIDE;
virtual size_t HeapSizeOfVectorImageDocument(nsACString* aDocURL = nullptr) const MOZ_OVERRIDE {
return mInnerImage->HeapSizeOfVectorImageDocument(aDocURL);
}
virtual void IncrementAnimationConsumers() MOZ_OVERRIDE; virtual void IncrementAnimationConsumers() MOZ_OVERRIDE;
virtual void DecrementAnimationConsumers() MOZ_OVERRIDE; virtual void DecrementAnimationConsumers() MOZ_OVERRIDE;
#ifdef DEBUG #ifdef DEBUG

View File

@ -181,6 +181,10 @@ public:
virtual size_t NonHeapSizeOfDecoded() const; virtual size_t NonHeapSizeOfDecoded() const;
virtual size_t OutOfProcessSizeOfDecoded() const; virtual size_t OutOfProcessSizeOfDecoded() const;
virtual size_t HeapSizeOfVectorImageDocument(nsACString* aDocURL = nullptr) const MOZ_OVERRIDE {
return 0;
}
/* Triggers discarding. */ /* Triggers discarding. */
void Discard(bool force = false); void Discard(bool force = false);
void ForceDiscard() { Discard(/* force = */ true); } void ForceDiscard() { Discard(/* force = */ true); }

View File

@ -22,8 +22,10 @@
#include "nsMimeTypes.h" #include "nsMimeTypes.h"
#include "nsPresContext.h" #include "nsPresContext.h"
#include "nsRect.h" #include "nsRect.h"
#include "nsString.h"
#include "nsStubDocumentObserver.h" #include "nsStubDocumentObserver.h"
#include "nsSVGEffects.h" // for nsSVGRenderingObserver #include "nsSVGEffects.h" // for nsSVGRenderingObserver
#include "nsWindowMemoryReporter.h"
#include "Orientation.h" #include "Orientation.h"
#include "SVGDocumentWrapper.h" #include "SVGDocumentWrapper.h"
#include "nsIDOMEventListener.h" #include "nsIDOMEventListener.h"
@ -359,28 +361,61 @@ VectorImage::HeapSizeOfSourceWithComputedFallback(mozilla::MallocSizeOf aMallocS
// We're not storing the source data -- we just feed that directly to // We're not storing the source data -- we just feed that directly to
// our helper SVG document as we receive it, for it to parse. // our helper SVG document as we receive it, for it to parse.
// So 0 is an appropriate return value here. // So 0 is an appropriate return value here.
// If implementing this, we'll need to restructure our callers to make sure
// any amount we return is attributed to the vector images measure (i.e.
// "explicit/images/{content,chrome}/vector/{used,unused}/...")
return 0; return 0;
} }
size_t size_t
VectorImage::HeapSizeOfDecodedWithComputedFallback(mozilla::MallocSizeOf aMallocSizeOf) const VectorImage::HeapSizeOfDecodedWithComputedFallback(mozilla::MallocSizeOf aMallocSizeOf) const
{ {
// XXXdholbert TODO: return num bytes used by helper SVG doc. (bug 590790) // If implementing this, we'll need to restructure our callers to make sure
// any amount we return is attributed to the vector images measure (i.e.
// "explicit/images/{content,chrome}/vector/{used,unused}/...")
return 0; return 0;
} }
size_t size_t
VectorImage::NonHeapSizeOfDecoded() const VectorImage::NonHeapSizeOfDecoded() const
{ {
// If implementing this, we'll need to restructure our callers to make sure
// any amount we return is attributed to the vector images measure (i.e.
// "explicit/images/{content,chrome}/vector/{used,unused}/...")
return 0; return 0;
} }
size_t size_t
VectorImage::OutOfProcessSizeOfDecoded() const VectorImage::OutOfProcessSizeOfDecoded() const
{ {
// If implementing this, we'll need to restructure our callers to make sure
// any amount we return is attributed to the vector images measure (i.e.
// "explicit/images/{content,chrome}/vector/{used,unused}/...")
return 0; return 0;
} }
MOZ_DEFINE_MALLOC_SIZE_OF(WindowsMallocSizeOf);
size_t
VectorImage::HeapSizeOfVectorImageDocument(nsACString* aDocURL) const
{
nsIDocument* doc = mSVGDocumentWrapper->GetDocument();
if (!doc) {
if (aDocURL) {
mURI->GetSpec(*aDocURL);
}
return 0; // No document, so no memory used for the document
}
if (aDocURL) {
doc->GetDocumentURI()->GetSpec(*aDocURL);
}
nsWindowSizes windowSizes(WindowsMallocSizeOf);
doc->DocAddSizeOfExcludingThis(&windowSizes);
return windowSizes.getTotalSize();
}
nsresult nsresult
VectorImage::OnImageDataComplete(nsIRequest* aRequest, VectorImage::OnImageDataComplete(nsIRequest* aRequest,
nsISupports* aContext, nsISupports* aContext,

View File

@ -48,6 +48,8 @@ public:
virtual size_t NonHeapSizeOfDecoded() const; virtual size_t NonHeapSizeOfDecoded() const;
virtual size_t OutOfProcessSizeOfDecoded() const; virtual size_t OutOfProcessSizeOfDecoded() const;
virtual size_t HeapSizeOfVectorImageDocument(nsACString* aDocURL = nullptr) const MOZ_OVERRIDE;
virtual nsresult OnImageDataAvailable(nsIRequest* aRequest, virtual nsresult OnImageDataAvailable(nsIRequest* aRequest,
nsISupports* aContext, nsISupports* aContext,
nsIInputStream* aInStr, nsIInputStream* aInStr,

View File

@ -75,56 +75,101 @@ public:
NS_ENSURE_SUCCESS(rv, rv); \ NS_ENSURE_SUCCESS(rv, rv); \
} while (0) } while (0)
REPORT("explicit/images/chrome/used/raw", REPORT("explicit/images/chrome/raster/used/raw",
KIND_HEAP, chrome.mUsedRaw, KIND_HEAP, chrome.mUsedRaw,
"Memory used by in-use chrome images (compressed data)."); "Memory used by in-use chrome images (compressed data).");
REPORT("explicit/images/chrome/used/uncompressed-heap", REPORT("explicit/images/chrome/raster/used/uncompressed-heap",
KIND_HEAP, chrome.mUsedUncompressedHeap, KIND_HEAP, chrome.mUsedUncompressedHeap,
"Memory used by in-use chrome images (uncompressed data)."); "Memory used by in-use chrome images (uncompressed data).");
REPORT("explicit/images/chrome/used/uncompressed-nonheap", REPORT("explicit/images/chrome/raster/used/uncompressed-nonheap",
KIND_NONHEAP, chrome.mUsedUncompressedNonheap, KIND_NONHEAP, chrome.mUsedUncompressedNonheap,
"Memory used by in-use chrome images (uncompressed data)."); "Memory used by in-use chrome images (uncompressed data).");
REPORT("explicit/images/chrome/unused/raw", REPORT("explicit/images/chrome/raster/unused/raw",
KIND_HEAP, chrome.mUnusedRaw, KIND_HEAP, chrome.mUnusedRaw,
"Memory used by not in-use chrome images (compressed data)."); "Memory used by not in-use chrome images (compressed data).");
REPORT("explicit/images/chrome/unused/uncompressed-heap", REPORT("explicit/images/chrome/raster/unused/uncompressed-heap",
KIND_HEAP, chrome.mUnusedUncompressedHeap, KIND_HEAP, chrome.mUnusedUncompressedHeap,
"Memory used by not in-use chrome images (uncompressed data)."); "Memory used by not in-use chrome images (uncompressed data).");
REPORT("explicit/images/chrome/unused/uncompressed-nonheap", REPORT("explicit/images/chrome/raster/unused/uncompressed-nonheap",
KIND_NONHEAP, chrome.mUnusedUncompressedNonheap, KIND_NONHEAP, chrome.mUnusedUncompressedNonheap,
"Memory used by not in-use chrome images (uncompressed data)."); "Memory used by not in-use chrome images (uncompressed data).");
REPORT("explicit/images/content/used/raw", REPORT("explicit/images/content/raster/used/raw",
KIND_HEAP, content.mUsedRaw, KIND_HEAP, content.mUsedRaw,
"Memory used by in-use content images (compressed data)."); "Memory used by in-use content images (compressed data).");
REPORT("explicit/images/content/used/uncompressed-heap", REPORT("explicit/images/content/raster/used/uncompressed-heap",
KIND_HEAP, content.mUsedUncompressedHeap, KIND_HEAP, content.mUsedUncompressedHeap,
"Memory used by in-use content images (uncompressed data)."); "Memory used by in-use content images (uncompressed data).");
REPORT("explicit/images/content/used/uncompressed-nonheap", REPORT("explicit/images/content/raster/used/uncompressed-nonheap",
KIND_NONHEAP, content.mUsedUncompressedNonheap, KIND_NONHEAP, content.mUsedUncompressedNonheap,
"Memory used by in-use content images (uncompressed data)."); "Memory used by in-use content images (uncompressed data).");
REPORT("explicit/images/content/unused/raw", REPORT("explicit/images/content/raster/unused/raw",
KIND_HEAP, content.mUnusedRaw, KIND_HEAP, content.mUnusedRaw,
"Memory used by not in-use content images (compressed data)."); "Memory used by not in-use content images (compressed data).");
REPORT("explicit/images/content/unused/uncompressed-heap", REPORT("explicit/images/content/raster/unused/uncompressed-heap",
KIND_HEAP, content.mUnusedUncompressedHeap, KIND_HEAP, content.mUnusedUncompressedHeap,
"Memory used by not in-use content images (uncompressed data)."); "Memory used by not in-use content images (uncompressed data).");
REPORT("explicit/images/content/unused/uncompressed-nonheap", REPORT("explicit/images/content/raster/unused/uncompressed-nonheap",
KIND_NONHEAP, content.mUnusedUncompressedNonheap, KIND_NONHEAP, content.mUnusedUncompressedNonheap,
"Memory used by not in-use content images (uncompressed data)."); "Memory used by not in-use content images (uncompressed data).");
#undef REPORT #undef REPORT
#define REPORT_VECTOR(_path, _uri, _amount, _desc) \
do { \
nsAutoCString path(NS_LITERAL_CSTRING(_path)); \
path.Append("/("); \
path.Append(_uri); \
path.Append(")"); \
nsresult rv; \
rv = callback->Callback(EmptyCString(), path, \
KIND_HEAP, UNITS_BYTES, _amount, \
NS_LITERAL_CSTRING(_desc), closure); \
NS_ENSURE_SUCCESS(rv, rv); \
} while (0)
for (uint32_t i = 0; i < chrome.mVectorImageDocInfo.Length(); i++) {
chrome.mVectorImageDocInfo[i].mURI.ReplaceChar('/', '\\');
if (chrome.mVectorImageDocInfo[i].mUsed) {
REPORT_VECTOR("explicit/images/chrome/vector/used/documents",
chrome.mVectorImageDocInfo[i].mURI,
chrome.mVectorImageDocInfo[i].mSize,
"Memory used by in-use chrome vector images for their parsed vector documents.");
} else {
REPORT_VECTOR("explicit/images/chrome/vector/unused/documents",
chrome.mVectorImageDocInfo[i].mURI,
chrome.mVectorImageDocInfo[i].mSize,
"Memory used by not in-use chrome vector images for their parsed vector documents.");
}
}
for (uint32_t i = 0; i < content.mVectorImageDocInfo.Length(); i++) {
content.mVectorImageDocInfo[i].mURI.ReplaceChar('/', '\\');
if (content.mVectorImageDocInfo[i].mUsed) {
REPORT_VECTOR("explicit/images/content/vector/used/documents",
content.mVectorImageDocInfo[i].mURI,
content.mVectorImageDocInfo[i].mSize,
"Memory used by in-use content vector images for their parsed vector documents.");
} else {
REPORT_VECTOR("explicit/images/content/vector/unused/documents",
content.mVectorImageDocInfo[i].mURI,
content.mVectorImageDocInfo[i].mSize,
"Memory used by not in-use content vector images for their parsed vector documents.");
}
}
#undef REPORT_VECTOR
return NS_OK; return NS_OK;
} }
@ -150,6 +195,12 @@ public:
private: private:
nsTArray<imgLoader*> mKnownLoaders; nsTArray<imgLoader*> mKnownLoaders;
struct VectorImageDocInfo {
size_t mSize;
bool mUsed;
nsAutoCString mURI;
};
struct AllSizes { struct AllSizes {
size_t mUsedRaw; size_t mUsedRaw;
size_t mUsedUncompressedHeap; size_t mUsedUncompressedHeap;
@ -157,10 +208,18 @@ private:
size_t mUnusedRaw; size_t mUnusedRaw;
size_t mUnusedUncompressedHeap; size_t mUnusedUncompressedHeap;
size_t mUnusedUncompressedNonheap; size_t mUnusedUncompressedNonheap;
// The size of VectorImages' documents are recorded individually so that we
// can report on each SVG-as-an-image individually.
nsTArray<VectorImageDocInfo> mVectorImageDocInfo;
AllSizes() { AllSizes()
memset(this, 0, sizeof(*this)); : mUsedRaw(0)
} , mUsedUncompressedHeap(0)
, mUsedUncompressedNonheap(0)
, mUnusedRaw(0)
, mUnusedUncompressedHeap(0)
, mUnusedUncompressedNonheap(0)
{}
}; };
static PLDHashOperator EntryAllSizes(const nsACString&, static PLDHashOperator EntryAllSizes(const nsACString&,
@ -184,6 +243,12 @@ private:
image->HeapSizeOfDecodedWithComputedFallback(ImagesMallocSizeOf); image->HeapSizeOfDecodedWithComputedFallback(ImagesMallocSizeOf);
sizes->mUsedUncompressedNonheap += image->NonHeapSizeOfDecoded(); sizes->mUsedUncompressedNonheap += image->NonHeapSizeOfDecoded();
} }
VectorImageDocInfo vectInfo;
vectInfo.mSize = image->HeapSizeOfVectorImageDocument(&vectInfo.mURI);
if (!vectInfo.mURI.IsEmpty()) {
vectInfo.mUsed = !entry->HasNoProxies();
sizes->mVectorImageDocInfo.AppendElement(vectInfo);
}
} }
return PL_DHASH_NEXT; return PL_DHASH_NEXT;

View File

@ -328,7 +328,7 @@ interface nsIMemoryReporterManager : nsISupports
* {system,user} compartments in the main JS runtime. * {system,user} compartments in the main JS runtime.
* *
* |imagesContentUsedUncompressed| (UNITS_BYTES) Memory used for decoded * |imagesContentUsedUncompressed| (UNITS_BYTES) Memory used for decoded
* images in content. * raster images in content.
* *
* |storageSQLite| (UNITS_BYTES) Memory used by SQLite. * |storageSQLite| (UNITS_BYTES) Memory used by SQLite.
* *