Bug 764299 (Part 3) - Add memory reporting to the surface cache. r=njn

This commit is contained in:
Seth Fowler 2013-10-21 18:10:45 +02:00
Родитель 4076d6db32
Коммит 9c00cfe937
1 изменённых файлов: 81 добавлений и 12 удалений

Просмотреть файл

@ -61,13 +61,21 @@ private:
namespace mozilla { namespace mozilla {
namespace image { namespace image {
class CachedSurface;
class SurfaceCacheImpl;
///////////////////////////////////////////////////////////////////////////////
// Static Data
///////////////////////////////////////////////////////////////////////////////
// The single surface cache instance.
static SurfaceCacheImpl* sInstance = nullptr;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// SurfaceCache Implementation // SurfaceCache Implementation
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class CachedSurface;
class SurfaceCacheImpl;
/* /*
* Cost models the cost of storing a surface in the cache. Right now, this is * Cost models the cost of storing a surface in the cache. Right now, this is
* simply an estimate of the size of the surface in bytes, but in the future it * simply an estimate of the size of the surface in bytes, but in the future it
@ -224,9 +232,26 @@ public:
uint32_t aSurfaceCacheSize) uint32_t aSurfaceCacheSize)
: mExpirationTracker(MOZ_THIS_IN_INITIALIZER_LIST(), : mExpirationTracker(MOZ_THIS_IN_INITIALIZER_LIST(),
aSurfaceCacheExpirationTimeMS) aSurfaceCacheExpirationTimeMS)
, mReporter(new SurfaceCacheReporter)
, mMemoryPressureObserver(new MemoryPressureObserver)
, mMaxCost(aSurfaceCacheSize) , mMaxCost(aSurfaceCacheSize)
, mAvailableCost(aSurfaceCacheSize) , mAvailableCost(aSurfaceCacheSize)
{ } {
NS_RegisterMemoryReporter(mReporter);
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (os)
os->AddObserver(mMemoryPressureObserver, "memory-pressure", false);
}
~SurfaceCacheImpl()
{
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (os)
os->RemoveObserver(mMemoryPressureObserver, "memory-pressure");
NS_UnregisterMemoryReporter(mReporter);
}
void Insert(DrawTarget* aTarget, void Insert(DrawTarget* aTarget,
nsIntSize aTargetSize, nsIntSize aTargetSize,
@ -342,6 +367,15 @@ public:
mImageCaches.Remove(aImageKey); mImageCaches.Remove(aImageKey);
} }
void DiscardAll()
{
// Remove in order of cost because mCosts is an array and the other data
// structures are all hash tables.
while (!mCosts.IsEmpty()) {
Remove(mCosts.LastElement().GetSurface());
}
}
static PLDHashOperator DoStopTracking(const SurfaceKey&, static PLDHashOperator DoStopTracking(const SurfaceKey&,
CachedSurface* aSurface, CachedSurface* aSurface,
void* aCache) void* aCache)
@ -350,6 +384,11 @@ public:
return PL_DHASH_NEXT; return PL_DHASH_NEXT;
} }
int64_t SizeOfSurfacesEstimate() const
{
return int64_t(mMaxCost - mAvailableCost);
}
private: private:
already_AddRefed<ImageSurfaceCache> GetImageCache(const ImageKey aImageKey) already_AddRefed<ImageSurfaceCache> GetImageCache(const ImageKey aImageKey)
{ {
@ -377,21 +416,51 @@ private:
SurfaceCacheImpl* const mCache; // Weak pointer to owner. SurfaceCacheImpl* const mCache; // Weak pointer to owner.
}; };
// XXX(seth): This is currently only an estimate and, since we don't know which
// surfaces are in GPU memory and which aren't, it's reported as KIND_OTHER and
// will also show up in heap-unclassified. Bug 923302 will make this nicer.
struct SurfaceCacheReporter : public MemoryUniReporter
{
SurfaceCacheReporter()
: MemoryUniReporter("imagelib-surface-cache",
KIND_OTHER,
UNITS_BYTES,
"Memory used by the imagelib temporary surface cache.")
{ }
protected:
int64_t Amount() MOZ_OVERRIDE
{
return sInstance ? sInstance->SizeOfSurfacesEstimate() : 0;
}
};
struct MemoryPressureObserver : public nsIObserver
{
NS_DECL_ISUPPORTS
virtual ~MemoryPressureObserver() { }
NS_IMETHOD Observe(nsISupports*, const char* aTopic, const PRUnichar*)
{
if (sInstance && strcmp(aTopic, "memory-pressure") == 0) {
sInstance->DiscardAll();
}
return NS_OK;
}
};
nsTArray<CostEntry> mCosts; nsTArray<CostEntry> mCosts;
nsRefPtrHashtable<nsPtrHashKey<Image>, ImageSurfaceCache> mImageCaches; nsRefPtrHashtable<nsPtrHashKey<Image>, ImageSurfaceCache> mImageCaches;
SurfaceTracker mExpirationTracker; SurfaceTracker mExpirationTracker;
nsRefPtr<SurfaceCacheReporter> mReporter;
nsRefPtr<MemoryPressureObserver> mMemoryPressureObserver;
const Cost mMaxCost; const Cost mMaxCost;
Cost mAvailableCost; Cost mAvailableCost;
}; };
NS_IMPL_ISUPPORTS1(SurfaceCacheImpl::MemoryPressureObserver, nsIObserver)
///////////////////////////////////////////////////////////////////////////////
// Static Data
///////////////////////////////////////////////////////////////////////////////
// The single surface cache instance.
static SurfaceCacheImpl* sInstance = nullptr;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Public API // Public API