Bug 1157954 - Report each surface in the ImageLib SurfaceCache individually in about:memory. r=dholbert

This commit is contained in:
Seth Fowler 2015-04-28 11:46:17 -07:00
parent fb9d0727c1
commit 8e4a491d49
16 changed files with 349 additions and 179 deletions

View File

@ -42,12 +42,12 @@ DynamicImage::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const
return 0;
}
size_t
DynamicImage::SizeOfDecoded(gfxMemoryLocation aLocation,
MallocSizeOf aMallocSizeOf) const
void
DynamicImage::CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
MallocSizeOf aMallocSizeOf) const
{
// We don't know the answer since gfxDrawable doesn't expose this information.
return 0;
// We can't report anything useful because gfxDrawable doesn't expose this
// information.
}
void

View File

@ -36,8 +36,8 @@ public:
virtual already_AddRefed<ProgressTracker> GetProgressTracker() override;
virtual size_t SizeOfSourceWithComputedFallback(
MallocSizeOf aMallocSizeOf) const override;
virtual size_t SizeOfDecoded(gfxMemoryLocation aLocation,
MallocSizeOf aMallocSizeOf) const override;
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
MallocSizeOf aMallocSizeOf) const override;
virtual void IncrementAnimationConsumers() override;
virtual void DecrementAnimationConsumers() override;

View File

@ -317,20 +317,51 @@ FrameAnimator::GetTimeoutForFrame(uint32_t aFrameNum) const
return data.mRawTimeout;
}
size_t
FrameAnimator::SizeOfCompositingFrames(gfxMemoryLocation aLocation,
MallocSizeOf aMallocSizeOf) const
static void
DoCollectSizeOfCompositingSurfaces(const RawAccessFrameRef& aSurface,
SurfaceMemoryCounterType aType,
nsTArray<SurfaceMemoryCounter>& aCounters,
MallocSizeOf aMallocSizeOf)
{
size_t n = 0;
// Concoct a SurfaceKey for this surface.
SurfaceKey key = RasterSurfaceKey(aSurface->GetImageSize(),
imgIContainer::DECODE_FLAGS_DEFAULT,
/* aFrameNum = */ 0);
// Create a counter for this surface.
SurfaceMemoryCounter counter(key, /* aIsLocked = */ true, aType);
// Extract the surface's memory usage information.
size_t heap = aSurface
->SizeOfExcludingThis(gfxMemoryLocation::IN_PROCESS_HEAP, aMallocSizeOf);
counter.Values().SetDecodedHeap(heap);
size_t nonHeap = aSurface
->SizeOfExcludingThis(gfxMemoryLocation::IN_PROCESS_NONHEAP, nullptr);
counter.Values().SetDecodedNonHeap(nonHeap);
// Record it.
aCounters.AppendElement(counter);
}
void
FrameAnimator::CollectSizeOfCompositingSurfaces(
nsTArray<SurfaceMemoryCounter>& aCounters,
MallocSizeOf aMallocSizeOf) const
{
if (mCompositingFrame) {
n += mCompositingFrame->SizeOfExcludingThis(aLocation, aMallocSizeOf);
}
if (mCompositingPrevFrame) {
n += mCompositingPrevFrame->SizeOfExcludingThis(aLocation, aMallocSizeOf);
DoCollectSizeOfCompositingSurfaces(mCompositingFrame,
SurfaceMemoryCounterType::COMPOSITING,
aCounters,
aMallocSizeOf);
}
return n;
if (mCompositingPrevFrame) {
DoCollectSizeOfCompositingSurfaces(mCompositingPrevFrame,
SurfaceMemoryCounterType::COMPOSITING_PREV,
aCounters,
aMallocSizeOf);
}
}
RawAccessFrameRef

View File

@ -148,8 +148,14 @@ public:
void SetLoopCount(int32_t aLoopCount) { mLoopCount = aLoopCount; }
int32_t LoopCount() const { return mLoopCount; }
size_t SizeOfCompositingFrames(gfxMemoryLocation aLocation,
MallocSizeOf aMallocSizeOf) const;
/**
* Collect an accounting of the memory occupied by the compositing surfaces we
* use during animation playback. All of the actual animation frames are
* stored in the SurfaceCache, so we don't need to report them here.
*/
void CollectSizeOfCompositingSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
MallocSizeOf aMallocSizeOf) const;
private: // methods
/**
* Gets the length of a single loop of this image, in milliseconds.

View File

@ -12,6 +12,46 @@
namespace mozilla {
namespace image {
///////////////////////////////////////////////////////////////////////////////
// Memory Reporting
///////////////////////////////////////////////////////////////////////////////
ImageMemoryCounter::ImageMemoryCounter(Image* aImage,
MallocSizeOf aMallocSizeOf,
bool aIsUsed)
: mIsUsed(aIsUsed)
{
MOZ_ASSERT(aImage);
// Extract metadata about the image.
nsRefPtr<ImageURL> imageURL(aImage->GetURI());
if (imageURL) {
imageURL->GetSpec(mURI);
}
int32_t width = 0;
int32_t height = 0;
aImage->GetWidth(&width);
aImage->GetHeight(&height);
mIntrinsicSize.SizeTo(width, height);
mType = aImage->GetType();
// Populate memory counters for source and decoded data.
mValues.SetSource(aImage->SizeOfSourceWithComputedFallback(aMallocSizeOf));
aImage->CollectSizeOfSurfaces(mSurfaces, aMallocSizeOf);
// Compute totals.
for (const SurfaceMemoryCounter& surfaceCounter : mSurfaces) {
mValues += surfaceCounter.Values();
}
}
///////////////////////////////////////////////////////////////////////////////
// Image Base Types
///////////////////////////////////////////////////////////////////////////////
// Constructor
ImageResource::ImageResource(ImageURL* aURI) :
mURI(aURI),

View File

@ -10,9 +10,10 @@
#include "mozilla/TimeStamp.h"
#include "gfx2DGlue.h" // for gfxMemoryLocation
#include "imgIContainer.h"
#include "ProgressTracker.h"
#include "ImageURL.h"
#include "nsStringFwd.h"
#include "ProgressTracker.h"
#include "SurfaceCache.h"
class nsIRequest;
class nsIInputStream;
@ -20,6 +21,111 @@ class nsIInputStream;
namespace mozilla {
namespace image {
class Image;
///////////////////////////////////////////////////////////////////////////////
// Memory Reporting
///////////////////////////////////////////////////////////////////////////////
struct MemoryCounter
{
MemoryCounter()
: mSource(0)
, mDecodedHeap(0)
, mDecodedNonHeap(0)
{ }
void SetSource(size_t aCount) { mSource = aCount; }
size_t Source() const { return mSource; }
void SetDecodedHeap(size_t aCount) { mDecodedHeap = aCount; }
size_t DecodedHeap() const { return mDecodedHeap; }
void SetDecodedNonHeap(size_t aCount) { mDecodedNonHeap = aCount; }
size_t DecodedNonHeap() const { return mDecodedNonHeap; }
MemoryCounter& operator+=(const MemoryCounter& aOther)
{
mSource += aOther.mSource;
mDecodedHeap += aOther.mDecodedHeap;
mDecodedNonHeap += aOther.mDecodedNonHeap;
return *this;
}
private:
size_t mSource;
size_t mDecodedHeap;
size_t mDecodedNonHeap;
};
enum class SurfaceMemoryCounterType
{
NORMAL,
COMPOSITING,
COMPOSITING_PREV
};
struct SurfaceMemoryCounter
{
SurfaceMemoryCounter(const SurfaceKey& aKey,
bool aIsLocked,
SurfaceMemoryCounterType aType =
SurfaceMemoryCounterType::NORMAL)
: mKey(aKey)
, mType(aType)
, mIsLocked(aIsLocked)
{ }
const SurfaceKey& Key() const { return mKey; }
Maybe<gfx::IntSize>& SubframeSize() { return mSubframeSize; }
const Maybe<gfx::IntSize>& SubframeSize() const { return mSubframeSize; }
MemoryCounter& Values() { return mValues; }
const MemoryCounter& Values() const { return mValues; }
SurfaceMemoryCounterType Type() const { return mType; }
bool IsLocked() const { return mIsLocked; }
private:
const SurfaceKey mKey;
Maybe<gfx::IntSize> mSubframeSize;
MemoryCounter mValues;
const SurfaceMemoryCounterType mType;
const bool mIsLocked;
};
struct ImageMemoryCounter
{
ImageMemoryCounter(Image* aImage,
MallocSizeOf aMallocSizeOf,
bool aIsUsed);
nsCString& URI() { return mURI; }
const nsCString& URI() const { return mURI; }
const nsTArray<SurfaceMemoryCounter>& Surfaces() const { return mSurfaces; }
const gfx::IntSize IntrinsicSize() const { return mIntrinsicSize; }
const MemoryCounter& Values() const { return mValues; }
uint16_t Type() const { return mType; }
bool IsUsed() const { return mIsUsed; }
bool IsNotable() const
{
const size_t NotableThreshold = 16 * 1024;
size_t total = mValues.Source() + mValues.DecodedHeap()
+ mValues.DecodedNonHeap();
return total >= NotableThreshold;
}
private:
nsCString mURI;
nsTArray<SurfaceMemoryCounter> mSurfaces;
gfx::IntSize mIntrinsicSize;
MemoryCounter mValues;
uint16_t mType;
const bool mIsUsed;
};
///////////////////////////////////////////////////////////////////////////////
// Image Base Types
///////////////////////////////////////////////////////////////////////////////
class Image : public imgIContainer
{
public:
@ -84,14 +190,16 @@ public:
* If MallocSizeOf does not work on this platform, uses a fallback approach to
* ensure that something reasonable is always returned.
*/
virtual size_t SizeOfSourceWithComputedFallback(
MallocSizeOf aMallocSizeOf) const = 0;
virtual size_t
SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const = 0;
/**
* The size, in bytes, occupied by the image's decoded data.
* Collect an accounting of the memory occupied by the image's surfaces (which
* together make up its decoded data). Each surface is recorded as a separate
* SurfaceMemoryCounter, stored in @aCounters.
*/
virtual size_t SizeOfDecoded(gfxMemoryLocation aLocation,
MallocSizeOf aMallocSizeOf) const = 0;
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
MallocSizeOf aMallocSizeOf) const = 0;
virtual void IncrementAnimationConsumers() = 0;
virtual void DecrementAnimationConsumers() = 0;

View File

@ -39,11 +39,11 @@ ImageWrapper::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const
return mInnerImage->SizeOfSourceWithComputedFallback(aMallocSizeOf);
}
size_t
ImageWrapper::SizeOfDecoded(gfxMemoryLocation aLocation,
MallocSizeOf aMallocSizeOf) const
void
ImageWrapper::CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
MallocSizeOf aMallocSizeOf) const
{
return mInnerImage->SizeOfDecoded(aLocation, aMallocSizeOf);
mInnerImage->CollectSizeOfSurfaces(aCounters, aMallocSizeOf);
}
void

View File

@ -27,11 +27,9 @@ public:
virtual already_AddRefed<ProgressTracker> GetProgressTracker() override;
virtual size_t
SizeOfSourceWithComputedFallback( MallocSizeOf aMallocSizeOf) const
override;
virtual size_t
SizeOfDecoded(gfxMemoryLocation aLocation,
MallocSizeOf aMallocSizeOf) const override;
SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const override;
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
MallocSizeOf aMallocSizeOf) const override;
virtual void IncrementAnimationConsumers() override;
virtual void DecrementAnimationConsumers() override;

View File

@ -888,16 +888,14 @@ RasterImage::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const
return mSourceBuffer->SizeOfIncludingThisWithComputedFallback(aMallocSizeOf);
}
size_t
RasterImage::SizeOfDecoded(gfxMemoryLocation aLocation,
MallocSizeOf aMallocSizeOf) const
void
RasterImage::CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
MallocSizeOf aMallocSizeOf) const
{
size_t n = 0;
n += SurfaceCache::SizeOfSurfaces(ImageKey(this), aLocation, aMallocSizeOf);
SurfaceCache::CollectSizeOfSurfaces(ImageKey(this), aCounters, aMallocSizeOf);
if (mAnim) {
n += mAnim->SizeOfCompositingFrames(aLocation, aMallocSizeOf);
mAnim->CollectSizeOfCompositingSurfaces(aCounters, aMallocSizeOf);
}
return n;
}
class OnAddedFrameRunnable : public nsRunnable

View File

@ -182,8 +182,8 @@ public:
virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf)
const override;
virtual size_t SizeOfDecoded(gfxMemoryLocation aLocation,
MallocSizeOf aMallocSizeOf) const override;
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
MallocSizeOf aMallocSizeOf) const override;
/* Triggers discarding. */
void Discard();

View File

@ -164,33 +164,41 @@ public:
Lifetime GetLifetime() const { return mLifetime; }
bool IsDecoded() const { return mSurface->IsImageComplete(); }
// A helper type used by SurfaceCacheImpl::SizeOfSurfacesSum.
struct SizeOfSurfacesSum
// A helper type used by SurfaceCacheImpl::CollectSizeOfSurfaces.
struct MOZ_STACK_CLASS SurfaceMemoryReport
{
SizeOfSurfacesSum(gfxMemoryLocation aLocation,
MallocSizeOf aMallocSizeOf)
: mLocation(aLocation)
SurfaceMemoryReport(nsTArray<SurfaceMemoryCounter>& aCounters,
MallocSizeOf aMallocSizeOf)
: mCounters(aCounters)
, mMallocSizeOf(aMallocSizeOf)
, mSum(0)
{ }
void Add(CachedSurface* aCachedSurface)
{
MOZ_ASSERT(aCachedSurface, "Should have a CachedSurface");
if (!aCachedSurface->mSurface) {
return;
SurfaceMemoryCounter counter(aCachedSurface->GetSurfaceKey(),
aCachedSurface->IsLocked());
if (aCachedSurface->mSurface) {
counter.SubframeSize() = Some(aCachedSurface->mSurface->GetSize());
size_t heap = aCachedSurface->mSurface
->SizeOfExcludingThis(gfxMemoryLocation::IN_PROCESS_HEAP,
mMallocSizeOf);
counter.Values().SetDecodedHeap(heap);
size_t nonHeap = aCachedSurface->mSurface
->SizeOfExcludingThis(gfxMemoryLocation::IN_PROCESS_NONHEAP, nullptr);
counter.Values().SetDecodedNonHeap(nonHeap);
}
mSum += aCachedSurface->mSurface->SizeOfExcludingThis(mLocation,
mMallocSizeOf);
mCounters.AppendElement(counter);
}
size_t Result() const { return mSum; }
private:
gfxMemoryLocation mLocation;
MallocSizeOf mMallocSizeOf;
size_t mSum;
nsTArray<SurfaceMemoryCounter>& mCounters;
MallocSizeOf mMallocSizeOf;
};
private:
@ -789,28 +797,26 @@ public:
return NS_OK;
}
size_t SizeOfSurfaces(const ImageKey aImageKey,
gfxMemoryLocation aLocation,
MallocSizeOf aMallocSizeOf)
void CollectSizeOfSurfaces(const ImageKey aImageKey,
nsTArray<SurfaceMemoryCounter>& aCounters,
MallocSizeOf aMallocSizeOf)
{
nsRefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
if (!cache) {
return 0; // No surfaces for this image.
return; // No surfaces for this image.
}
// Sum the size of all surfaces in the per-image cache.
CachedSurface::SizeOfSurfacesSum sum(aLocation, aMallocSizeOf);
cache->ForEach(DoSizeOfSurfacesSum, &sum);
return sum.Result();
// Report all surfaces in the per-image cache.
CachedSurface::SurfaceMemoryReport report(aCounters, aMallocSizeOf);
cache->ForEach(DoCollectSizeOfSurface, &report);
}
static PLDHashOperator DoSizeOfSurfacesSum(const SurfaceKey&,
CachedSurface* aSurface,
void* aSum)
static PLDHashOperator DoCollectSizeOfSurface(const SurfaceKey&,
CachedSurface* aSurface,
void* aReport)
{
auto sum = static_cast<CachedSurface::SizeOfSurfacesSum*>(aSum);
sum->Add(aSurface);
auto report = static_cast<CachedSurface::SurfaceMemoryReport*>(aReport);
report->Add(aSurface);
return PL_DHASH_NEXT;
}
@ -1075,17 +1081,17 @@ SurfaceCache::DiscardAll()
}
}
/* static */ size_t
SurfaceCache::SizeOfSurfaces(const ImageKey aImageKey,
gfxMemoryLocation aLocation,
MallocSizeOf aMallocSizeOf)
/* static */ void
SurfaceCache::CollectSizeOfSurfaces(const ImageKey aImageKey,
nsTArray<SurfaceMemoryCounter>& aCounters,
MallocSizeOf aMallocSizeOf)
{
if (!sInstance) {
return 0;
return;
}
MutexAutoLock lock(sInstance->GetMutex());
return sInstance->SizeOfSurfaces(aImageKey, aLocation, aMallocSizeOf);
return sInstance->CollectSizeOfSurfaces(aImageKey, aCounters, aMallocSizeOf);
}
} // namespace image

View File

@ -27,6 +27,7 @@ namespace image {
class DrawableFrameRef;
class Image;
class imgFrame;
struct SurfaceMemoryCounter;
/*
* ImageKey contains the information we need to look up all cached surfaces for
@ -392,21 +393,19 @@ struct SurfaceCache
static void DiscardAll();
/**
* Computes the size of the surfaces stored for the given image at the given
* memory location.
* Collects an accounting of the surfaces contained in the SurfaceCache for
* the given image, along with their size and various other metadata.
*
* This is intended for use with memory reporting.
*
* @param aImageKey The image to report memory usage for.
* @param aLocation The location (heap, nonheap, etc.) of the memory to
* report on.
* @param aMallocSizeOf A fallback malloc memory reporting function. This
* should be null unless we're reporting on in-process
* heap memory.
* @param aCounters An array into which the report for each surface will
* be written.
* @param aMallocSizeOf A fallback malloc memory reporting function.
*/
static size_t SizeOfSurfaces(const ImageKey aImageKey,
gfxMemoryLocation aLocation,
MallocSizeOf aMallocSizeOf);
static void CollectSizeOfSurfaces(const ImageKey aImageKey,
nsTArray<SurfaceMemoryCounter>& aCounters,
MallocSizeOf aMallocSizeOf);
private:
virtual ~SurfaceCache() = 0; // Forbid instantiation.

View File

@ -397,11 +397,11 @@ VectorImage::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const
return windowSizes.getTotalSize();
}
size_t
VectorImage::SizeOfDecoded(gfxMemoryLocation aLocation,
MallocSizeOf aMallocSizeOf) const
void
VectorImage::CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
MallocSizeOf aMallocSizeOf) const
{
return SurfaceCache::SizeOfSurfaces(ImageKey(this), aLocation, aMallocSizeOf);
SurfaceCache::CollectSizeOfSurfaces(ImageKey(this), aCounters, aMallocSizeOf);
}
nsresult

View File

@ -39,8 +39,8 @@ public:
virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf)
const override;
virtual size_t SizeOfDecoded(gfxMemoryLocation aLocation,
MallocSizeOf aMallocSizeOf) const override;
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
MallocSizeOf aMallocSizeOf) const override;
virtual nsresult OnImageDataAvailable(nsIRequest* aRequest,
nsISupports* aContext,

View File

@ -236,7 +236,7 @@ public:
*/
void WaitUntilComplete() const;
IntSize GetImageSize() { return mImageSize; }
IntSize GetImageSize() const { return mImageSize; }
nsIntRect GetRect() const;
IntSize GetSize() const { return mSize; }
bool NeedsPadding() const { return mOffset != nsIntPoint(0, 0); }

View File

@ -117,67 +117,6 @@ public:
private:
nsTArray<imgLoader*> mKnownLoaders;
struct MemoryCounter
{
MemoryCounter()
: mSource(0)
, mDecodedHeap(0)
, mDecodedNonHeap(0)
{ }
void SetSource(size_t aCount) { mSource = aCount; }
size_t Source() const { return mSource; }
void SetDecodedHeap(size_t aCount) { mDecodedHeap = aCount; }
size_t DecodedHeap() const { return mDecodedHeap; }
void SetDecodedNonHeap(size_t aCount) { mDecodedNonHeap = aCount; }
size_t DecodedNonHeap() const { return mDecodedNonHeap; }
MemoryCounter& operator+=(const MemoryCounter& aOther)
{
mSource += aOther.mSource;
mDecodedHeap += aOther.mDecodedHeap;
mDecodedNonHeap += aOther.mDecodedNonHeap;
return *this;
}
private:
size_t mSource;
size_t mDecodedHeap;
size_t mDecodedNonHeap;
};
struct ImageMemoryCounter
{
ImageMemoryCounter(uint16_t aType, const nsACString& aURI, bool aIsUsed)
: mURI(aURI)
, mType(aType)
, mIsUsed(aIsUsed)
{
MOZ_ASSERT(!mURI.IsEmpty(), "Should have a URI for all images");
}
nsCString& URI() { return mURI; }
const nsCString& URI() const { return mURI; }
uint16_t Type() const { return mType; }
MemoryCounter& Values() { return mValues; }
const MemoryCounter& Values() const { return mValues; }
bool IsUsed() const { return mIsUsed; }
bool IsNotable() const
{
const size_t NotableThreshold = 16 * 1024;
size_t total = mValues.Source() + mValues.DecodedHeap()
+ mValues.DecodedNonHeap();
return total >= NotableThreshold;
}
private:
nsCString mURI;
uint16_t mType;
MemoryCounter mValues;
bool mIsUsed;
};
struct MemoryTotal
{
MemoryTotal& operator+=(const ImageMemoryCounter& aImageCounter)
@ -216,7 +155,7 @@ private:
// Reports all images of a single kind, e.g. all used chrome images.
nsresult ReportCounterArray(nsIHandleReportCallback* aHandleReport,
nsISupports* aData,
const nsTArray<ImageMemoryCounter>& aCounterArray,
nsTArray<ImageMemoryCounter>& aCounterArray,
const char* aPathPrefix,
bool aAnonymize = false)
{
@ -226,7 +165,7 @@ private:
// Report notable images, and compute total and non-notable aggregate sizes.
for (uint32_t i = 0; i < aCounterArray.Length(); i++) {
ImageMemoryCounter counter = aCounterArray[i];
ImageMemoryCounter& counter = aCounterArray[i];
if (aAnonymize) {
counter.URI().Truncate();
@ -244,7 +183,7 @@ private:
summaryTotal += counter;
if (counter.IsNotable()) {
rv = ReportCounter(aHandleReport, aData, aPathPrefix, counter);
rv = ReportImage(aHandleReport, aData, aPathPrefix, counter);
NS_ENSURE_SUCCESS(rv, rv);
} else {
nonNotableTotal += counter;
@ -264,10 +203,10 @@ private:
return NS_OK;
}
static nsresult ReportCounter(nsIHandleReportCallback* aHandleReport,
nsISupports* aData,
const char* aPathPrefix,
const ImageMemoryCounter& aCounter)
static nsresult ReportImage(nsIHandleReportCallback* aHandleReport,
nsISupports* aData,
const char* aPathPrefix,
const ImageMemoryCounter& aCounter)
{
nsAutoCString pathPrefix(NS_LITERAL_CSTRING("explicit/"));
pathPrefix.Append(aPathPrefix);
@ -276,14 +215,68 @@ private:
: "/vector/");
pathPrefix.Append(aCounter.IsUsed() ? "used/" : "unused/");
pathPrefix.Append("image(");
pathPrefix.AppendInt(aCounter.IntrinsicSize().width);
pathPrefix.Append("x");
pathPrefix.AppendInt(aCounter.IntrinsicSize().height);
pathPrefix.Append(", ");
if (aCounter.URI().IsEmpty()) {
pathPrefix.Append("<unknown URI>");
} else {
pathPrefix.Append(aCounter.URI());
}
pathPrefix.Append(")/");
return ReportValues(aHandleReport, aData, pathPrefix, aCounter.Values());
return ReportSurfaces(aHandleReport, aData, pathPrefix, aCounter);
}
static nsresult ReportSurfaces(nsIHandleReportCallback* aHandleReport,
nsISupports* aData,
const nsACString& aPathPrefix,
const ImageMemoryCounter& aCounter)
{
for (const SurfaceMemoryCounter& counter : aCounter.Surfaces()) {
nsAutoCString surfacePathPrefix(aPathPrefix);
surfacePathPrefix.Append(counter.IsLocked() ? "locked/" : "unlocked/");
surfacePathPrefix.Append("surface(");
if (counter.SubframeSize() &&
*counter.SubframeSize() != counter.Key().Size()) {
surfacePathPrefix.AppendInt(counter.SubframeSize()->width);
surfacePathPrefix.Append("x");
surfacePathPrefix.AppendInt(counter.SubframeSize()->height);
surfacePathPrefix.Append(" subframe of ");
}
surfacePathPrefix.AppendInt(counter.Key().Size().width);
surfacePathPrefix.Append("x");
surfacePathPrefix.AppendInt(counter.Key().Size().height);
if (counter.Type() == SurfaceMemoryCounterType::NORMAL) {
surfacePathPrefix.Append("@");
surfacePathPrefix.AppendFloat(counter.Key().AnimationTime());
if (counter.Key().Flags() != imgIContainer::DECODE_FLAGS_DEFAULT) {
surfacePathPrefix.Append(", flags:");
surfacePathPrefix.AppendInt(counter.Key().Flags(), /* aRadix = */ 16);
}
} else if (counter.Type() == SurfaceMemoryCounterType::COMPOSITING) {
surfacePathPrefix.Append(", compositing frame");
} else if (counter.Type() == SurfaceMemoryCounterType::COMPOSITING_PREV) {
surfacePathPrefix.Append(", compositing prev frame");
} else {
MOZ_ASSERT_UNREACHABLE("Unknown counter type");
}
surfacePathPrefix.Append(")/");
nsresult rv = ReportValues(aHandleReport, aData, surfacePathPrefix,
counter.Values());
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
static nsresult ReportTotal(nsIHandleReportCallback* aHandleReport,
@ -410,20 +403,9 @@ private:
return;
}
nsRefPtr<ImageURL> imageURL(image->GetURI());
nsAutoCString spec;
imageURL->GetSpec(spec);
ImageMemoryCounter counter(image, ImagesMallocSizeOf, aIsUsed);
ImageMemoryCounter counter(image->GetType(), spec, aIsUsed);
counter.Values().SetSource(image->
SizeOfSourceWithComputedFallback(ImagesMallocSizeOf));
counter.Values().SetDecodedHeap(image->
SizeOfDecoded(gfxMemoryLocation::IN_PROCESS_HEAP, ImagesMallocSizeOf));
counter.Values().SetDecodedNonHeap(image->
SizeOfDecoded(gfxMemoryLocation::IN_PROCESS_NONHEAP, nullptr));
aArray->AppendElement(counter);
aArray->AppendElement(Move(counter));
}
static PLDHashOperator DoRecordCounterUsedDecoded(const ImageCacheKey&,
@ -444,10 +426,12 @@ private:
// memory. This function's measurement is secondary -- the result doesn't
// go in the "explicit" tree -- so we use moz_malloc_size_of instead of
// ImagesMallocSizeOf to prevent DMD from seeing it reported twice.
ImageMemoryCounter counter(image, moz_malloc_size_of, /* aIsUsed = */ true);
auto n = static_cast<size_t*>(aUserArg);
*n += image->SizeOfDecoded(gfxMemoryLocation::IN_PROCESS_HEAP,
moz_malloc_size_of);
*n += image->SizeOfDecoded(gfxMemoryLocation::IN_PROCESS_NONHEAP, nullptr);
*n += counter.Values().DecodedHeap();
*n += counter.Values().DecodedNonHeap();
return PL_DHASH_NEXT;
}
};