mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1157954 - Report each surface in the ImageLib SurfaceCache individually in about:memory. r=dholbert
This commit is contained in:
parent
fb9d0727c1
commit
8e4a491d49
@ -42,12 +42,12 @@ DynamicImage::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
void
|
||||||
DynamicImage::SizeOfDecoded(gfxMemoryLocation aLocation,
|
DynamicImage::CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||||
MallocSizeOf aMallocSizeOf) const
|
MallocSizeOf aMallocSizeOf) const
|
||||||
{
|
{
|
||||||
// We don't know the answer since gfxDrawable doesn't expose this information.
|
// We can't report anything useful because gfxDrawable doesn't expose this
|
||||||
return 0;
|
// information.
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -36,8 +36,8 @@ public:
|
|||||||
virtual already_AddRefed<ProgressTracker> GetProgressTracker() override;
|
virtual already_AddRefed<ProgressTracker> GetProgressTracker() override;
|
||||||
virtual size_t SizeOfSourceWithComputedFallback(
|
virtual size_t SizeOfSourceWithComputedFallback(
|
||||||
MallocSizeOf aMallocSizeOf) const override;
|
MallocSizeOf aMallocSizeOf) const override;
|
||||||
virtual size_t SizeOfDecoded(gfxMemoryLocation aLocation,
|
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||||
MallocSizeOf aMallocSizeOf) const override;
|
MallocSizeOf aMallocSizeOf) const override;
|
||||||
|
|
||||||
virtual void IncrementAnimationConsumers() override;
|
virtual void IncrementAnimationConsumers() override;
|
||||||
virtual void DecrementAnimationConsumers() override;
|
virtual void DecrementAnimationConsumers() override;
|
||||||
|
@ -317,20 +317,51 @@ FrameAnimator::GetTimeoutForFrame(uint32_t aFrameNum) const
|
|||||||
return data.mRawTimeout;
|
return data.mRawTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
static void
|
||||||
FrameAnimator::SizeOfCompositingFrames(gfxMemoryLocation aLocation,
|
DoCollectSizeOfCompositingSurfaces(const RawAccessFrameRef& aSurface,
|
||||||
MallocSizeOf aMallocSizeOf) const
|
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) {
|
if (mCompositingFrame) {
|
||||||
n += mCompositingFrame->SizeOfExcludingThis(aLocation, aMallocSizeOf);
|
DoCollectSizeOfCompositingSurfaces(mCompositingFrame,
|
||||||
}
|
SurfaceMemoryCounterType::COMPOSITING,
|
||||||
if (mCompositingPrevFrame) {
|
aCounters,
|
||||||
n += mCompositingPrevFrame->SizeOfExcludingThis(aLocation, aMallocSizeOf);
|
aMallocSizeOf);
|
||||||
}
|
}
|
||||||
|
|
||||||
return n;
|
if (mCompositingPrevFrame) {
|
||||||
|
DoCollectSizeOfCompositingSurfaces(mCompositingPrevFrame,
|
||||||
|
SurfaceMemoryCounterType::COMPOSITING_PREV,
|
||||||
|
aCounters,
|
||||||
|
aMallocSizeOf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RawAccessFrameRef
|
RawAccessFrameRef
|
||||||
|
@ -148,8 +148,14 @@ public:
|
|||||||
void SetLoopCount(int32_t aLoopCount) { mLoopCount = aLoopCount; }
|
void SetLoopCount(int32_t aLoopCount) { mLoopCount = aLoopCount; }
|
||||||
int32_t LoopCount() const { return mLoopCount; }
|
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
|
private: // methods
|
||||||
/**
|
/**
|
||||||
* Gets the length of a single loop of this image, in milliseconds.
|
* Gets the length of a single loop of this image, in milliseconds.
|
||||||
|
@ -12,6 +12,46 @@
|
|||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace image {
|
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
|
// Constructor
|
||||||
ImageResource::ImageResource(ImageURL* aURI) :
|
ImageResource::ImageResource(ImageURL* aURI) :
|
||||||
mURI(aURI),
|
mURI(aURI),
|
||||||
|
@ -10,9 +10,10 @@
|
|||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
#include "gfx2DGlue.h" // for gfxMemoryLocation
|
#include "gfx2DGlue.h" // for gfxMemoryLocation
|
||||||
#include "imgIContainer.h"
|
#include "imgIContainer.h"
|
||||||
#include "ProgressTracker.h"
|
|
||||||
#include "ImageURL.h"
|
#include "ImageURL.h"
|
||||||
#include "nsStringFwd.h"
|
#include "nsStringFwd.h"
|
||||||
|
#include "ProgressTracker.h"
|
||||||
|
#include "SurfaceCache.h"
|
||||||
|
|
||||||
class nsIRequest;
|
class nsIRequest;
|
||||||
class nsIInputStream;
|
class nsIInputStream;
|
||||||
@ -20,6 +21,111 @@ class nsIInputStream;
|
|||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace image {
|
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
|
class Image : public imgIContainer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -84,14 +190,16 @@ public:
|
|||||||
* If MallocSizeOf does not work on this platform, uses a fallback approach to
|
* If MallocSizeOf does not work on this platform, uses a fallback approach to
|
||||||
* ensure that something reasonable is always returned.
|
* ensure that something reasonable is always returned.
|
||||||
*/
|
*/
|
||||||
virtual size_t SizeOfSourceWithComputedFallback(
|
virtual size_t
|
||||||
MallocSizeOf aMallocSizeOf) const = 0;
|
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,
|
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||||
MallocSizeOf aMallocSizeOf) const = 0;
|
MallocSizeOf aMallocSizeOf) const = 0;
|
||||||
|
|
||||||
virtual void IncrementAnimationConsumers() = 0;
|
virtual void IncrementAnimationConsumers() = 0;
|
||||||
virtual void DecrementAnimationConsumers() = 0;
|
virtual void DecrementAnimationConsumers() = 0;
|
||||||
|
@ -39,11 +39,11 @@ ImageWrapper::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const
|
|||||||
return mInnerImage->SizeOfSourceWithComputedFallback(aMallocSizeOf);
|
return mInnerImage->SizeOfSourceWithComputedFallback(aMallocSizeOf);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
void
|
||||||
ImageWrapper::SizeOfDecoded(gfxMemoryLocation aLocation,
|
ImageWrapper::CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||||
MallocSizeOf aMallocSizeOf) const
|
MallocSizeOf aMallocSizeOf) const
|
||||||
{
|
{
|
||||||
return mInnerImage->SizeOfDecoded(aLocation, aMallocSizeOf);
|
mInnerImage->CollectSizeOfSurfaces(aCounters, aMallocSizeOf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -27,11 +27,9 @@ public:
|
|||||||
virtual already_AddRefed<ProgressTracker> GetProgressTracker() override;
|
virtual already_AddRefed<ProgressTracker> GetProgressTracker() override;
|
||||||
|
|
||||||
virtual size_t
|
virtual size_t
|
||||||
SizeOfSourceWithComputedFallback( MallocSizeOf aMallocSizeOf) const
|
SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const override;
|
||||||
override;
|
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||||
virtual size_t
|
MallocSizeOf aMallocSizeOf) const override;
|
||||||
SizeOfDecoded(gfxMemoryLocation aLocation,
|
|
||||||
MallocSizeOf aMallocSizeOf) const override;
|
|
||||||
|
|
||||||
virtual void IncrementAnimationConsumers() override;
|
virtual void IncrementAnimationConsumers() override;
|
||||||
virtual void DecrementAnimationConsumers() override;
|
virtual void DecrementAnimationConsumers() override;
|
||||||
|
@ -888,16 +888,14 @@ RasterImage::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const
|
|||||||
return mSourceBuffer->SizeOfIncludingThisWithComputedFallback(aMallocSizeOf);
|
return mSourceBuffer->SizeOfIncludingThisWithComputedFallback(aMallocSizeOf);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
void
|
||||||
RasterImage::SizeOfDecoded(gfxMemoryLocation aLocation,
|
RasterImage::CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||||
MallocSizeOf aMallocSizeOf) const
|
MallocSizeOf aMallocSizeOf) const
|
||||||
{
|
{
|
||||||
size_t n = 0;
|
SurfaceCache::CollectSizeOfSurfaces(ImageKey(this), aCounters, aMallocSizeOf);
|
||||||
n += SurfaceCache::SizeOfSurfaces(ImageKey(this), aLocation, aMallocSizeOf);
|
|
||||||
if (mAnim) {
|
if (mAnim) {
|
||||||
n += mAnim->SizeOfCompositingFrames(aLocation, aMallocSizeOf);
|
mAnim->CollectSizeOfCompositingSurfaces(aCounters, aMallocSizeOf);
|
||||||
}
|
}
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class OnAddedFrameRunnable : public nsRunnable
|
class OnAddedFrameRunnable : public nsRunnable
|
||||||
|
@ -182,8 +182,8 @@ public:
|
|||||||
|
|
||||||
virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf)
|
virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf)
|
||||||
const override;
|
const override;
|
||||||
virtual size_t SizeOfDecoded(gfxMemoryLocation aLocation,
|
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||||
MallocSizeOf aMallocSizeOf) const override;
|
MallocSizeOf aMallocSizeOf) const override;
|
||||||
|
|
||||||
/* Triggers discarding. */
|
/* Triggers discarding. */
|
||||||
void Discard();
|
void Discard();
|
||||||
|
@ -164,33 +164,41 @@ public:
|
|||||||
Lifetime GetLifetime() const { return mLifetime; }
|
Lifetime GetLifetime() const { return mLifetime; }
|
||||||
bool IsDecoded() const { return mSurface->IsImageComplete(); }
|
bool IsDecoded() const { return mSurface->IsImageComplete(); }
|
||||||
|
|
||||||
// A helper type used by SurfaceCacheImpl::SizeOfSurfacesSum.
|
// A helper type used by SurfaceCacheImpl::CollectSizeOfSurfaces.
|
||||||
struct SizeOfSurfacesSum
|
struct MOZ_STACK_CLASS SurfaceMemoryReport
|
||||||
{
|
{
|
||||||
SizeOfSurfacesSum(gfxMemoryLocation aLocation,
|
SurfaceMemoryReport(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||||
MallocSizeOf aMallocSizeOf)
|
MallocSizeOf aMallocSizeOf)
|
||||||
: mLocation(aLocation)
|
: mCounters(aCounters)
|
||||||
, mMallocSizeOf(aMallocSizeOf)
|
, mMallocSizeOf(aMallocSizeOf)
|
||||||
, mSum(0)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void Add(CachedSurface* aCachedSurface)
|
void Add(CachedSurface* aCachedSurface)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aCachedSurface, "Should have a CachedSurface");
|
MOZ_ASSERT(aCachedSurface, "Should have a CachedSurface");
|
||||||
|
|
||||||
if (!aCachedSurface->mSurface) {
|
SurfaceMemoryCounter counter(aCachedSurface->GetSurfaceKey(),
|
||||||
return;
|
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:
|
private:
|
||||||
gfxMemoryLocation mLocation;
|
nsTArray<SurfaceMemoryCounter>& mCounters;
|
||||||
MallocSizeOf mMallocSizeOf;
|
MallocSizeOf mMallocSizeOf;
|
||||||
size_t mSum;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -789,28 +797,26 @@ public:
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t SizeOfSurfaces(const ImageKey aImageKey,
|
void CollectSizeOfSurfaces(const ImageKey aImageKey,
|
||||||
gfxMemoryLocation aLocation,
|
nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||||
MallocSizeOf aMallocSizeOf)
|
MallocSizeOf aMallocSizeOf)
|
||||||
{
|
{
|
||||||
nsRefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
|
nsRefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
|
||||||
if (!cache) {
|
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.
|
// Report all surfaces in the per-image cache.
|
||||||
CachedSurface::SizeOfSurfacesSum sum(aLocation, aMallocSizeOf);
|
CachedSurface::SurfaceMemoryReport report(aCounters, aMallocSizeOf);
|
||||||
cache->ForEach(DoSizeOfSurfacesSum, &sum);
|
cache->ForEach(DoCollectSizeOfSurface, &report);
|
||||||
|
|
||||||
return sum.Result();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PLDHashOperator DoSizeOfSurfacesSum(const SurfaceKey&,
|
static PLDHashOperator DoCollectSizeOfSurface(const SurfaceKey&,
|
||||||
CachedSurface* aSurface,
|
CachedSurface* aSurface,
|
||||||
void* aSum)
|
void* aReport)
|
||||||
{
|
{
|
||||||
auto sum = static_cast<CachedSurface::SizeOfSurfacesSum*>(aSum);
|
auto report = static_cast<CachedSurface::SurfaceMemoryReport*>(aReport);
|
||||||
sum->Add(aSurface);
|
report->Add(aSurface);
|
||||||
return PL_DHASH_NEXT;
|
return PL_DHASH_NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1075,17 +1081,17 @@ SurfaceCache::DiscardAll()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ size_t
|
/* static */ void
|
||||||
SurfaceCache::SizeOfSurfaces(const ImageKey aImageKey,
|
SurfaceCache::CollectSizeOfSurfaces(const ImageKey aImageKey,
|
||||||
gfxMemoryLocation aLocation,
|
nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||||
MallocSizeOf aMallocSizeOf)
|
MallocSizeOf aMallocSizeOf)
|
||||||
{
|
{
|
||||||
if (!sInstance) {
|
if (!sInstance) {
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MutexAutoLock lock(sInstance->GetMutex());
|
MutexAutoLock lock(sInstance->GetMutex());
|
||||||
return sInstance->SizeOfSurfaces(aImageKey, aLocation, aMallocSizeOf);
|
return sInstance->CollectSizeOfSurfaces(aImageKey, aCounters, aMallocSizeOf);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace image
|
} // namespace image
|
||||||
|
@ -27,6 +27,7 @@ namespace image {
|
|||||||
class DrawableFrameRef;
|
class DrawableFrameRef;
|
||||||
class Image;
|
class Image;
|
||||||
class imgFrame;
|
class imgFrame;
|
||||||
|
struct SurfaceMemoryCounter;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ImageKey contains the information we need to look up all cached surfaces for
|
* ImageKey contains the information we need to look up all cached surfaces for
|
||||||
@ -392,21 +393,19 @@ struct SurfaceCache
|
|||||||
static void DiscardAll();
|
static void DiscardAll();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the size of the surfaces stored for the given image at the given
|
* Collects an accounting of the surfaces contained in the SurfaceCache for
|
||||||
* memory location.
|
* the given image, along with their size and various other metadata.
|
||||||
*
|
*
|
||||||
* This is intended for use with memory reporting.
|
* This is intended for use with memory reporting.
|
||||||
*
|
*
|
||||||
* @param aImageKey The image to report memory usage for.
|
* @param aImageKey The image to report memory usage for.
|
||||||
* @param aLocation The location (heap, nonheap, etc.) of the memory to
|
* @param aCounters An array into which the report for each surface will
|
||||||
* report on.
|
* be written.
|
||||||
* @param aMallocSizeOf A fallback malloc memory reporting function. This
|
* @param aMallocSizeOf A fallback malloc memory reporting function.
|
||||||
* should be null unless we're reporting on in-process
|
|
||||||
* heap memory.
|
|
||||||
*/
|
*/
|
||||||
static size_t SizeOfSurfaces(const ImageKey aImageKey,
|
static void CollectSizeOfSurfaces(const ImageKey aImageKey,
|
||||||
gfxMemoryLocation aLocation,
|
nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||||
MallocSizeOf aMallocSizeOf);
|
MallocSizeOf aMallocSizeOf);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ~SurfaceCache() = 0; // Forbid instantiation.
|
virtual ~SurfaceCache() = 0; // Forbid instantiation.
|
||||||
|
@ -397,11 +397,11 @@ VectorImage::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const
|
|||||||
return windowSizes.getTotalSize();
|
return windowSizes.getTotalSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
void
|
||||||
VectorImage::SizeOfDecoded(gfxMemoryLocation aLocation,
|
VectorImage::CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||||
MallocSizeOf aMallocSizeOf) const
|
MallocSizeOf aMallocSizeOf) const
|
||||||
{
|
{
|
||||||
return SurfaceCache::SizeOfSurfaces(ImageKey(this), aLocation, aMallocSizeOf);
|
SurfaceCache::CollectSizeOfSurfaces(ImageKey(this), aCounters, aMallocSizeOf);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
@ -39,8 +39,8 @@ public:
|
|||||||
|
|
||||||
virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf)
|
virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf)
|
||||||
const override;
|
const override;
|
||||||
virtual size_t SizeOfDecoded(gfxMemoryLocation aLocation,
|
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||||
MallocSizeOf aMallocSizeOf) const override;
|
MallocSizeOf aMallocSizeOf) const override;
|
||||||
|
|
||||||
virtual nsresult OnImageDataAvailable(nsIRequest* aRequest,
|
virtual nsresult OnImageDataAvailable(nsIRequest* aRequest,
|
||||||
nsISupports* aContext,
|
nsISupports* aContext,
|
||||||
|
@ -236,7 +236,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
void WaitUntilComplete() const;
|
void WaitUntilComplete() const;
|
||||||
|
|
||||||
IntSize GetImageSize() { return mImageSize; }
|
IntSize GetImageSize() const { return mImageSize; }
|
||||||
nsIntRect GetRect() const;
|
nsIntRect GetRect() const;
|
||||||
IntSize GetSize() const { return mSize; }
|
IntSize GetSize() const { return mSize; }
|
||||||
bool NeedsPadding() const { return mOffset != nsIntPoint(0, 0); }
|
bool NeedsPadding() const { return mOffset != nsIntPoint(0, 0); }
|
||||||
|
@ -117,67 +117,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
nsTArray<imgLoader*> mKnownLoaders;
|
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
|
struct MemoryTotal
|
||||||
{
|
{
|
||||||
MemoryTotal& operator+=(const ImageMemoryCounter& aImageCounter)
|
MemoryTotal& operator+=(const ImageMemoryCounter& aImageCounter)
|
||||||
@ -216,7 +155,7 @@ private:
|
|||||||
// Reports all images of a single kind, e.g. all used chrome images.
|
// Reports all images of a single kind, e.g. all used chrome images.
|
||||||
nsresult ReportCounterArray(nsIHandleReportCallback* aHandleReport,
|
nsresult ReportCounterArray(nsIHandleReportCallback* aHandleReport,
|
||||||
nsISupports* aData,
|
nsISupports* aData,
|
||||||
const nsTArray<ImageMemoryCounter>& aCounterArray,
|
nsTArray<ImageMemoryCounter>& aCounterArray,
|
||||||
const char* aPathPrefix,
|
const char* aPathPrefix,
|
||||||
bool aAnonymize = false)
|
bool aAnonymize = false)
|
||||||
{
|
{
|
||||||
@ -226,7 +165,7 @@ private:
|
|||||||
|
|
||||||
// Report notable images, and compute total and non-notable aggregate sizes.
|
// Report notable images, and compute total and non-notable aggregate sizes.
|
||||||
for (uint32_t i = 0; i < aCounterArray.Length(); i++) {
|
for (uint32_t i = 0; i < aCounterArray.Length(); i++) {
|
||||||
ImageMemoryCounter counter = aCounterArray[i];
|
ImageMemoryCounter& counter = aCounterArray[i];
|
||||||
|
|
||||||
if (aAnonymize) {
|
if (aAnonymize) {
|
||||||
counter.URI().Truncate();
|
counter.URI().Truncate();
|
||||||
@ -244,7 +183,7 @@ private:
|
|||||||
summaryTotal += counter;
|
summaryTotal += counter;
|
||||||
|
|
||||||
if (counter.IsNotable()) {
|
if (counter.IsNotable()) {
|
||||||
rv = ReportCounter(aHandleReport, aData, aPathPrefix, counter);
|
rv = ReportImage(aHandleReport, aData, aPathPrefix, counter);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
} else {
|
} else {
|
||||||
nonNotableTotal += counter;
|
nonNotableTotal += counter;
|
||||||
@ -264,10 +203,10 @@ private:
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static nsresult ReportCounter(nsIHandleReportCallback* aHandleReport,
|
static nsresult ReportImage(nsIHandleReportCallback* aHandleReport,
|
||||||
nsISupports* aData,
|
nsISupports* aData,
|
||||||
const char* aPathPrefix,
|
const char* aPathPrefix,
|
||||||
const ImageMemoryCounter& aCounter)
|
const ImageMemoryCounter& aCounter)
|
||||||
{
|
{
|
||||||
nsAutoCString pathPrefix(NS_LITERAL_CSTRING("explicit/"));
|
nsAutoCString pathPrefix(NS_LITERAL_CSTRING("explicit/"));
|
||||||
pathPrefix.Append(aPathPrefix);
|
pathPrefix.Append(aPathPrefix);
|
||||||
@ -276,14 +215,68 @@ private:
|
|||||||
: "/vector/");
|
: "/vector/");
|
||||||
pathPrefix.Append(aCounter.IsUsed() ? "used/" : "unused/");
|
pathPrefix.Append(aCounter.IsUsed() ? "used/" : "unused/");
|
||||||
pathPrefix.Append("image(");
|
pathPrefix.Append("image(");
|
||||||
|
pathPrefix.AppendInt(aCounter.IntrinsicSize().width);
|
||||||
|
pathPrefix.Append("x");
|
||||||
|
pathPrefix.AppendInt(aCounter.IntrinsicSize().height);
|
||||||
|
pathPrefix.Append(", ");
|
||||||
|
|
||||||
if (aCounter.URI().IsEmpty()) {
|
if (aCounter.URI().IsEmpty()) {
|
||||||
pathPrefix.Append("<unknown URI>");
|
pathPrefix.Append("<unknown URI>");
|
||||||
} else {
|
} else {
|
||||||
pathPrefix.Append(aCounter.URI());
|
pathPrefix.Append(aCounter.URI());
|
||||||
}
|
}
|
||||||
|
|
||||||
pathPrefix.Append(")/");
|
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,
|
static nsresult ReportTotal(nsIHandleReportCallback* aHandleReport,
|
||||||
@ -410,20 +403,9 @@ private:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRefPtr<ImageURL> imageURL(image->GetURI());
|
ImageMemoryCounter counter(image, ImagesMallocSizeOf, aIsUsed);
|
||||||
nsAutoCString spec;
|
|
||||||
imageURL->GetSpec(spec);
|
|
||||||
|
|
||||||
ImageMemoryCounter counter(image->GetType(), spec, aIsUsed);
|
aArray->AppendElement(Move(counter));
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PLDHashOperator DoRecordCounterUsedDecoded(const ImageCacheKey&,
|
static PLDHashOperator DoRecordCounterUsedDecoded(const ImageCacheKey&,
|
||||||
@ -444,10 +426,12 @@ private:
|
|||||||
// memory. This function's measurement is secondary -- the result doesn't
|
// 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
|
// go in the "explicit" tree -- so we use moz_malloc_size_of instead of
|
||||||
// ImagesMallocSizeOf to prevent DMD from seeing it reported twice.
|
// 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);
|
auto n = static_cast<size_t*>(aUserArg);
|
||||||
*n += image->SizeOfDecoded(gfxMemoryLocation::IN_PROCESS_HEAP,
|
*n += counter.Values().DecodedHeap();
|
||||||
moz_malloc_size_of);
|
*n += counter.Values().DecodedNonHeap();
|
||||||
*n += image->SizeOfDecoded(gfxMemoryLocation::IN_PROCESS_NONHEAP, nullptr);
|
|
||||||
return PL_DHASH_NEXT;
|
return PL_DHASH_NEXT;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user