зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1157954 - Report each surface in the ImageLib SurfaceCache individually in about:memory. r=dholbert
This commit is contained in:
Родитель
67aae95b57
Коммит
f3b0607ceb
|
@ -42,12 +42,12 @@ DynamicImage::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
DynamicImage::SizeOfDecoded(gfxMemoryLocation aLocation,
|
||||
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
|
||||
|
|
|
@ -36,7 +36,7 @@ public:
|
|||
virtual already_AddRefed<ProgressTracker> GetProgressTracker() override;
|
||||
virtual size_t SizeOfSourceWithComputedFallback(
|
||||
MallocSizeOf aMallocSizeOf) const override;
|
||||
virtual size_t SizeOfDecoded(gfxMemoryLocation aLocation,
|
||||
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||
MallocSizeOf aMallocSizeOf) const override;
|
||||
|
||||
virtual void IncrementAnimationConsumers() override;
|
||||
|
|
|
@ -317,20 +317,51 @@ FrameAnimator::GetTimeoutForFrame(uint32_t aFrameNum) const
|
|||
return data.mRawTimeout;
|
||||
}
|
||||
|
||||
size_t
|
||||
FrameAnimator::SizeOfCompositingFrames(gfxMemoryLocation aLocation,
|
||||
static void
|
||||
DoCollectSizeOfCompositingSurfaces(const RawAccessFrameRef& aSurface,
|
||||
SurfaceMemoryCounterType aType,
|
||||
nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||
MallocSizeOf aMallocSizeOf)
|
||||
{
|
||||
// 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
|
||||
{
|
||||
size_t n = 0;
|
||||
|
||||
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
|
||||
|
|
|
@ -148,8 +148,14 @@ public:
|
|||
void SetLoopCount(int32_t aLoopCount) { mLoopCount = aLoopCount; }
|
||||
int32_t LoopCount() const { return mLoopCount; }
|
||||
|
||||
size_t SizeOfCompositingFrames(gfxMemoryLocation aLocation,
|
||||
/**
|
||||
* 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.
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,13 +190,15 @@ 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,
|
||||
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||
MallocSizeOf aMallocSizeOf) const = 0;
|
||||
|
||||
virtual void IncrementAnimationConsumers() = 0;
|
||||
|
|
|
@ -39,11 +39,11 @@ ImageWrapper::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const
|
|||
return mInnerImage->SizeOfSourceWithComputedFallback(aMallocSizeOf);
|
||||
}
|
||||
|
||||
size_t
|
||||
ImageWrapper::SizeOfDecoded(gfxMemoryLocation aLocation,
|
||||
void
|
||||
ImageWrapper::CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||
MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
return mInnerImage->SizeOfDecoded(aLocation, aMallocSizeOf);
|
||||
mInnerImage->CollectSizeOfSurfaces(aCounters, aMallocSizeOf);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -27,10 +27,8 @@ public:
|
|||
virtual already_AddRefed<ProgressTracker> GetProgressTracker() override;
|
||||
|
||||
virtual size_t
|
||||
SizeOfSourceWithComputedFallback( MallocSizeOf aMallocSizeOf) const
|
||||
override;
|
||||
virtual size_t
|
||||
SizeOfDecoded(gfxMemoryLocation aLocation,
|
||||
SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const override;
|
||||
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||
MallocSizeOf aMallocSizeOf) const override;
|
||||
|
||||
virtual void IncrementAnimationConsumers() override;
|
||||
|
|
|
@ -888,16 +888,14 @@ RasterImage::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const
|
|||
return mSourceBuffer->SizeOfIncludingThisWithComputedFallback(aMallocSizeOf);
|
||||
}
|
||||
|
||||
size_t
|
||||
RasterImage::SizeOfDecoded(gfxMemoryLocation aLocation,
|
||||
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
|
||||
|
|
|
@ -182,7 +182,7 @@ public:
|
|||
|
||||
virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf)
|
||||
const override;
|
||||
virtual size_t SizeOfDecoded(gfxMemoryLocation aLocation,
|
||||
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||
MallocSizeOf aMallocSizeOf) const override;
|
||||
|
||||
/* Triggers discarding. */
|
||||
|
|
|
@ -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,
|
||||
SurfaceMemoryReport(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||
MallocSizeOf aMallocSizeOf)
|
||||
: mLocation(aLocation)
|
||||
: mCounters(aCounters)
|
||||
, mMallocSizeOf(aMallocSizeOf)
|
||||
, mSum(0)
|
||||
{ }
|
||||
|
||||
void Add(CachedSurface* aCachedSurface)
|
||||
{
|
||||
MOZ_ASSERT(aCachedSurface, "Should have a CachedSurface");
|
||||
|
||||
if (!aCachedSurface->mSurface) {
|
||||
return;
|
||||
}
|
||||
mSum += aCachedSurface->mSurface->SizeOfExcludingThis(mLocation,
|
||||
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);
|
||||
}
|
||||
|
||||
size_t Result() const { return mSum; }
|
||||
mCounters.AppendElement(counter);
|
||||
}
|
||||
|
||||
private:
|
||||
gfxMemoryLocation mLocation;
|
||||
nsTArray<SurfaceMemoryCounter>& mCounters;
|
||||
MallocSizeOf mMallocSizeOf;
|
||||
size_t mSum;
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -789,28 +797,26 @@ public:
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
size_t SizeOfSurfaces(const ImageKey aImageKey,
|
||||
gfxMemoryLocation aLocation,
|
||||
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&,
|
||||
static PLDHashOperator DoCollectSizeOfSurface(const SurfaceKey&,
|
||||
CachedSurface* aSurface,
|
||||
void* aSum)
|
||||
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,
|
||||
/* 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
|
||||
|
|
|
@ -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,20 +393,18 @@ 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,
|
||||
static void CollectSizeOfSurfaces(const ImageKey aImageKey,
|
||||
nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||
MallocSizeOf aMallocSizeOf);
|
||||
|
||||
private:
|
||||
|
|
|
@ -397,11 +397,11 @@ VectorImage::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const
|
|||
return windowSizes.getTotalSize();
|
||||
}
|
||||
|
||||
size_t
|
||||
VectorImage::SizeOfDecoded(gfxMemoryLocation aLocation,
|
||||
void
|
||||
VectorImage::CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||
MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
return SurfaceCache::SizeOfSurfaces(ImageKey(this), aLocation, aMallocSizeOf);
|
||||
SurfaceCache::CollectSizeOfSurfaces(ImageKey(this), aCounters, aMallocSizeOf);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -39,7 +39,7 @@ public:
|
|||
|
||||
virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf)
|
||||
const override;
|
||||
virtual size_t SizeOfDecoded(gfxMemoryLocation aLocation,
|
||||
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||
MallocSizeOf aMallocSizeOf) const override;
|
||||
|
||||
virtual nsresult OnImageDataAvailable(nsIRequest* aRequest,
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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,7 +203,7 @@ private:
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult ReportCounter(nsIHandleReportCallback* aHandleReport,
|
||||
static nsresult ReportImage(nsIHandleReportCallback* aHandleReport,
|
||||
nsISupports* aData,
|
||||
const char* aPathPrefix,
|
||||
const ImageMemoryCounter& aCounter)
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче