Bug 862970 - Don't lock images on the active page on B2G. r=jlebar,joe

This commit is contained in:
Andreas Gal 2013-04-25 18:36:53 -07:00
parent a75f4d6413
commit 943c3039a9
8 changed files with 68 additions and 24 deletions

View File

@ -271,9 +271,10 @@ pref("media.video-queue.default-size", 3);
// optimize images' memory usage
pref("image.mem.decodeondraw", true);
pref("content.image.allow_locking", true);
pref("image.mem.min_discard_timeout_ms", 10000);
pref("image.mem.max_decoded_image_kb", 5120); /* 5MB */
pref("content.image.allow_locking", false); /* don't allow image locking */
pref("image.mem.min_discard_timeout_ms", 86400000); /* 24h, we rely on the out of memory hook */
pref("image.mem.max_decoded_image_kb", 30000); /* 30MB seems reasonable */
pref("image.onload.decode.limit", 24); /* don't decode more than 24 images eagerly */
// XXX this isn't a good check for "are touch events supported", but
// we don't really have a better one at the moment.

View File

@ -1866,6 +1866,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
tmp->mInUnlinkOrDeletion = false;
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
static bool sPrefsInitialized = false;
static int32_t sOnloadDecodeLimit = 0;
nsresult
nsDocument::Init()
@ -1874,6 +1876,11 @@ nsDocument::Init()
return NS_ERROR_ALREADY_INITIALIZED;
}
if (!sPrefsInitialized) {
sPrefsInitialized = true;
Preferences::AddIntVarCache(&sOnloadDecodeLimit, "image.onload.decode.limit", 0);
}
mIdentifierMap.Init();
mStyledLinks.Init();
mRadioGroups.Init();
@ -8919,9 +8926,11 @@ nsDocument::AddImage(imgIRequest* aImage)
// If this is the first insertion and we're locking images, lock this image
// too.
if (oldCount == 0 && mLockingImages) {
rv = aImage->LockImage();
if (NS_SUCCEEDED(rv))
if (oldCount == 0) {
if (mLockingImages)
rv = aImage->LockImage();
if (NS_SUCCEEDED(rv) && (!sOnloadDecodeLimit ||
mImageTracker.Count() < sOnloadDecodeLimit))
rv = aImage->StartDecoding();
}

View File

@ -52,10 +52,7 @@ this.ConsoleAPIStorage = {
this.clearEvents(innerWindowID);
}
else if (aTopic == "memory-pressure") {
/* Handle both low-memory and low-memory-no-forward events */
if (aData.startsWith("low-memory")) {
this.clearEvents();
}
this.clearEvents();
}
},

View File

@ -240,6 +240,12 @@ nsJSEnvironmentObserver::Observe(nsISupports* aSubject, const char* aTopic,
const PRUnichar* aData)
{
if (sGCOnMemoryPressure && !nsCRT::strcmp(aTopic, "memory-pressure")) {
if(StringBeginsWith(nsDependentString(aData),
NS_LITERAL_STRING("low-memory-ongoing"))) {
// Don't GC/CC if we are in an ongoing low-memory state since its very
// slow and it likely won't help us anyway.
return NS_OK;
}
nsJSContext::GarbageCollectNow(JS::gcreason::MEM_PRESSURE,
nsJSContext::NonIncrementalGC,
nsJSContext::NonCompartmentGC,

View File

@ -1443,7 +1443,8 @@ ContentParent::Observe(nsISupports* aSubject,
// listening for memory pressure event
if (!strcmp(aTopic, "memory-pressure") &&
!NS_LITERAL_STRING("low-memory-no-forward").Equals(aData)) {
!StringEndsWith(nsDependentString(aData),
NS_LITERAL_STRING("-no-forward"))) {
unused << SendFlushMemory(nsDependentString(aData));
}
// listening for remotePrefs...

View File

@ -3936,6 +3936,9 @@ pref("image.multithreaded_decoding.limit", -1);
// cache.
pref("canvas.image.cache.limit", 0);
// How many images to eagerly decode on a given page. 0 means "no limit".
pref("image.onload.decode.limit", 0);
// WebGL prefs
pref("gl.msaa-level", 2);
pref("webgl.force-enabled", false);

View File

@ -26,7 +26,14 @@ namespace {
class MemoryPressureRunnable : public nsRunnable
{
const char *mTopic;
const PRUnichar *mData;
public:
MemoryPressureRunnable(const char *aTopic, const PRUnichar *aData) :
mTopic(aTopic), mData(aData)
{
}
NS_IMETHOD Run()
{
MOZ_ASSERT(NS_IsMainThread());
@ -34,15 +41,20 @@ public:
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
if (os) {
// We use low-memory-no-forward because each process has its own watcher
// and thus there is no need for the main process to forward this event.
os->NotifyObservers(nullptr, "memory-pressure",
NS_LITERAL_STRING("low-memory-no-forward").get());
os->NotifyObservers(nullptr, mTopic, mData);
}
return NS_OK;
}
};
static void
Dispatch(const char *aTopic, const PRUnichar *aData)
{
nsRefPtr<MemoryPressureRunnable> memoryPressureRunnable =
new MemoryPressureRunnable(aTopic, aData);
NS_DispatchToMainThread(memoryPressureRunnable);
}
/**
* MemoryPressureWatcher watches sysfs from its own thread to notice when the
* system is under memory pressure. When we observe memory pressure, we use
@ -172,13 +184,17 @@ public:
// sometimes completes after the memory-pressure event is over, so let's
// just believe the result of poll().
nsRefPtr<MemoryPressureRunnable> memoryPressureRunnable =
new MemoryPressureRunnable();
NS_DispatchToMainThread(memoryPressureRunnable);
// We use low-memory-no-forward because each process has its own watcher
// and thus there is no need for the main process to forward this event.
Dispatch("memory-pressure",
NS_LITERAL_STRING("low-memory-no-forward").get());
// Manually check lowMemFd until we observe that memory pressure is over.
// We won't fire any more memory-pressure events until we observe that
// we're no longer under pressure.
// We won't fire any more low-memory events until we observe that
// we're no longer under pressure. Instead, we fire low-memory-ongoing
// events, which cause processes to keep flushing caches but will not
// trigger expensive GCs and other attempts to save memory that are
// likely futile at this point.
bool memoryPressure;
do {
{
@ -201,7 +217,13 @@ public:
LOG("Checking to see if memory pressure is over.");
rv = CheckForMemoryPressure(lowMemFd, &memoryPressure);
NS_ENSURE_SUCCESS(rv, rv);
} while (memoryPressure);
if (memoryPressure) {
Dispatch("memory-pressure",
NS_LITERAL_STRING("low-memory-ongoing-no-forward").get());
continue;
}
} while (false);
LOG("Memory pressure is over.");
}

View File

@ -26,9 +26,14 @@
* This will be passed as the extra data when the pressure
* observer is being asked to flush for low-memory conditions.
*
* "low-memory-no-forward"
* This will be passed as the extra data when the pressure observer
* is being asked to flush for low-memory conditions but the resulting
* "low-memory-ongoing"
* This will be passed when we continue to be in a low-memory
* condition and we want to flush caches and do other cheap
* forms of memory minimization, but heavy handed approaches like
* a GC are unlikely to succeed.
*
* "-no-forward"
* This is appended to the above two parameters when the resulting
* notification should not be forwarded to the child processes.
*
* "heap-minimize"