Bug 707436 - nsSetSmartSizeEvent can cause a lot of IO on the main thread

This commit is contained in:
Michal Novotny 2011-12-24 02:51:25 +01:00
parent d23cdc52f0
commit 1875c5ce30
4 changed files with 57 additions and 7 deletions

View File

@ -75,6 +75,7 @@
#include "mozilla/Util.h" // for DebugOnly
#include "mozilla/Services.h"
#include "mozilla/Telemetry.h"
#include "nsITimer.h"
#include "mozilla/FunctionTimer.h"
@ -218,6 +219,20 @@ private:
NS_IMPL_THREADSAFE_ISUPPORTS1(nsCacheProfilePrefObserver, nsIObserver)
class nsSetDiskSmartSizeCallback : public nsITimerCallback
{
public:
NS_DECL_ISUPPORTS
NS_IMETHOD Notify(nsITimer* aTimer) {
nsCacheService::gService->SetDiskSmartSize(true);
NS_RELEASE(aTimer);
return NS_OK;
}
};
NS_IMPL_THREADSAFE_ISUPPORTS1(nsSetDiskSmartSizeCallback, nsITimerCallback)
// Runnable sent to main thread after the cache IO thread calculates available
// disk space, so that there is no race in setting mDiskCacheCapacity.
class nsSetSmartSizeEvent: public nsRunnable
@ -452,7 +467,7 @@ nsCacheProfilePrefObserver::Observe(nsISupports * subject,
return rv;
PRInt32 newCapacity = 0;
if (smartSizeEnabled) {
nsCacheService::SetDiskSmartSize();
nsCacheService::SetDiskSmartSize(false);
} else {
// Smart sizing switched off: use user specified size
rv = branch->GetIntPref(DISK_CACHE_CAPACITY_PREF, &newCapacity);
@ -1447,8 +1462,19 @@ nsCacheService::CreateDiskDevice()
mDiskDevice = nsnull;
}
SetDiskSmartSize_Locked(true);
// Disk device is usually created during the startup. Delay smart size
// calculation to avoid possible massive IO caused by eviction of entries
// in case the new smart size is smaller than current cache usage.
nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1", &rv);
if (NS_FAILED(rv))
return rv;
rv = timer->InitWithCallback(new nsSetDiskSmartSizeCallback(), 1000*60*3,
nsITimer::TYPE_ONE_SHOT);
if (NS_FAILED(rv))
return rv;
timer.forget();
return rv;
}
@ -2646,13 +2672,13 @@ nsCacheService::OnEnterExitPrivateBrowsing()
}
nsresult
nsCacheService::SetDiskSmartSize()
nsCacheService::SetDiskSmartSize(bool checkPref)
{
nsCacheServiceAutoLock lock;
if (!gService) return NS_ERROR_NOT_AVAILABLE;
return gService->SetDiskSmartSize_Locked(false);
return gService->SetDiskSmartSize_Locked(checkPref);
}
nsresult

View File

@ -182,7 +182,7 @@ public:
static void OnEnterExitPrivateBrowsing();
// Starts smart cache size computation if disk device is available
static nsresult SetDiskSmartSize();
static nsresult SetDiskSmartSize(bool checkPref);
nsresult Init();
void Shutdown();
@ -196,6 +196,7 @@ private:
friend class nsProcessRequestEvent;
friend class nsSetSmartSizeEvent;
friend class nsBlockOnCacheThreadEvent;
friend class nsSetDiskSmartSizeCallback;
/**
* Internal Methods

View File

@ -118,6 +118,22 @@ private:
nsDiskCacheBinding *mBinding;
};
class nsEvictDiskCacheEntriesEvent : public nsRunnable {
public:
nsEvictDiskCacheEntriesEvent(nsDiskCacheDevice *device)
: mDevice(device) {}
NS_IMETHOD Run()
{
nsCacheServiceAutoLock lock;
mDevice->EvictDiskCacheEntries(mDevice->mCacheCapacity);
return NS_OK;
}
private:
nsDiskCacheDevice *mDevice;
};
/******************************************************************************
* nsDiskCacheEvictor
*
@ -1120,8 +1136,14 @@ nsDiskCacheDevice::SetCapacity(PRUint32 capacity)
// Units are KiB's
mCacheCapacity = capacity;
if (Initialized()) {
// start evicting entries if the new size is smaller!
EvictDiskCacheEntries(mCacheCapacity);
if (NS_IsMainThread()) {
// Do not evict entries on the main thread
nsCacheService::DispatchToCacheIOThread(
new nsEvictDiskCacheEntriesEvent(this));
} else {
// start evicting entries if the new size is smaller!
EvictDiskCacheEntries(mCacheCapacity);
}
}
// Let cache map know of the new capacity
mCacheMap.NotifyCapacityChange(capacity);

View File

@ -107,6 +107,7 @@ public:
private:
friend class nsDiskCacheDeviceDeactivateEntryEvent;
friend class nsEvictDiskCacheEntriesEvent;
/**
* Private methods
*/