mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
Bug 707436 - nsSetSmartSizeEvent can cause a lot of IO on the main thread
This commit is contained in:
parent
867263367f
commit
610908a7b2
137
netwerk/cache/nsCacheService.cpp
vendored
137
netwerk/cache/nsCacheService.cpp
vendored
@ -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"
|
||||
|
||||
@ -152,6 +153,7 @@ public:
|
||||
, mDiskCacheEnabled(false)
|
||||
, mDiskCacheCapacity(0)
|
||||
, mDiskCacheMaxEntrySize(-1) // -1 means "no limit"
|
||||
, mSmartSizeEnabled(false)
|
||||
, mOfflineCacheEnabled(false)
|
||||
, mOfflineCacheCapacity(0)
|
||||
, mMemoryCacheEnabled(true)
|
||||
@ -175,6 +177,7 @@ public:
|
||||
void SetDiskCacheCapacity(PRInt32);
|
||||
PRInt32 DiskCacheMaxEntrySize() { return mDiskCacheMaxEntrySize; }
|
||||
nsILocalFile * DiskCacheParentDirectory() { return mDiskCacheParentDirectory; }
|
||||
bool SmartSizeEnabled() { return mSmartSizeEnabled; }
|
||||
|
||||
bool OfflineCacheEnabled();
|
||||
PRInt32 OfflineCacheCapacity() { return mOfflineCacheCapacity; }
|
||||
@ -199,6 +202,7 @@ private:
|
||||
PRInt32 mDiskCacheCapacity; // in kilobytes
|
||||
PRInt32 mDiskCacheMaxEntrySize; // in kilobytes
|
||||
nsCOMPtr<nsILocalFile> mDiskCacheParentDirectory;
|
||||
bool mSmartSizeEnabled;
|
||||
|
||||
bool mOfflineCacheEnabled;
|
||||
PRInt32 mOfflineCacheCapacity; // in kilobytes
|
||||
@ -218,6 +222,23 @@ private:
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsCacheProfilePrefObserver, nsIObserver)
|
||||
|
||||
class nsSetDiskSmartSizeCallback : public nsITimerCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD Notify(nsITimer* aTimer) {
|
||||
if (nsCacheService::gService) {
|
||||
nsCacheServiceAutoLock autoLock;
|
||||
nsCacheService::gService->SetDiskSmartSize_Locked();
|
||||
nsCacheService::gService->mSmartSizeTimer = nsnull;
|
||||
}
|
||||
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
|
||||
@ -228,32 +249,27 @@ public:
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsresult rv;
|
||||
NS_ASSERTION(NS_IsMainThread(),
|
||||
"Setting smart size data off the main thread");
|
||||
|
||||
// Main thread may have already called nsCacheService::Shutdown
|
||||
if (!nsCacheService::gService || !nsCacheService::gService->mObserver)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
bool smartSizeEnabled;
|
||||
nsCOMPtr<nsIPrefBranch2> branch = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
if (!branch) {
|
||||
NS_WARNING("Failed to get pref service!");
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
// ensure smart sizing wasn't switched off while event was pending
|
||||
rv = branch->GetBoolPref(DISK_CACHE_SMART_SIZE_ENABLED_PREF,
|
||||
&smartSizeEnabled);
|
||||
if (NS_FAILED(rv))
|
||||
smartSizeEnabled = false;
|
||||
if (smartSizeEnabled) {
|
||||
nsCacheService::SetDiskCacheCapacity(mSmartSize);
|
||||
rv = branch->SetIntPref(DISK_CACHE_SMART_SIZE_PREF, mSmartSize);
|
||||
if (NS_FAILED(rv))
|
||||
NS_WARNING("Failed to set smart size pref");
|
||||
}
|
||||
return rv;
|
||||
|
||||
// Ensure smart sizing wasn't switched off while event was pending.
|
||||
// It is safe to access the observer without the lock since we are
|
||||
// on the main thread and the value changes only on the main thread.
|
||||
if (!nsCacheService::gService->mObserver->SmartSizeEnabled())
|
||||
return NS_OK;
|
||||
|
||||
nsCacheService::SetDiskCacheCapacity(mSmartSize);
|
||||
|
||||
nsCOMPtr<nsIPrefBranch2> ps = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
if (!ps ||
|
||||
NS_FAILED(ps->SetIntPref(DISK_CACHE_SMART_SIZE_PREF, mSmartSize)))
|
||||
NS_WARNING("Failed to set smart size pref");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -445,13 +461,12 @@ nsCacheProfilePrefObserver::Observe(nsISupports * subject,
|
||||
// Update the cache capacity when smart sizing is turned on/off
|
||||
} else if (!strcmp(DISK_CACHE_SMART_SIZE_ENABLED_PREF, data.get())) {
|
||||
// Is the update because smartsizing was turned on, or off?
|
||||
bool smartSizeEnabled;
|
||||
rv = branch->GetBoolPref(DISK_CACHE_SMART_SIZE_ENABLED_PREF,
|
||||
&smartSizeEnabled);
|
||||
&mSmartSizeEnabled);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
PRInt32 newCapacity = 0;
|
||||
if (smartSizeEnabled) {
|
||||
if (mSmartSizeEnabled) {
|
||||
nsCacheService::SetDiskSmartSize();
|
||||
} else {
|
||||
// Smart sizing switched off: use user specified size
|
||||
@ -671,21 +686,22 @@ nsCacheProfilePrefObserver::PermittedToSmartSize(nsIPrefBranch* branch, bool
|
||||
// of 50 MB, then keep user's value. Otherwise use smart sizing.
|
||||
rv = branch->GetIntPref(DISK_CACHE_CAPACITY_PREF, &oldCapacity);
|
||||
if (oldCapacity < PRE_GECKO_2_0_DEFAULT_CACHE_SIZE) {
|
||||
branch->SetBoolPref(DISK_CACHE_SMART_SIZE_ENABLED_PREF,
|
||||
false);
|
||||
return false;
|
||||
mSmartSizeEnabled = false;
|
||||
branch->SetBoolPref(DISK_CACHE_SMART_SIZE_ENABLED_PREF,
|
||||
mSmartSizeEnabled);
|
||||
return mSmartSizeEnabled;
|
||||
}
|
||||
}
|
||||
// Set manual setting to MAX cache size as starting val for any
|
||||
// adjustment by user: (bug 559942 comment 65)
|
||||
branch->SetIntPref(DISK_CACHE_CAPACITY_PREF, MAX_CACHE_SIZE);
|
||||
}
|
||||
bool smartSizeEnabled;
|
||||
|
||||
rv = branch->GetBoolPref(DISK_CACHE_SMART_SIZE_ENABLED_PREF,
|
||||
&smartSizeEnabled);
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
return !!smartSizeEnabled;
|
||||
&mSmartSizeEnabled);
|
||||
if (NS_FAILED(rv))
|
||||
mSmartSizeEnabled = false;
|
||||
return mSmartSizeEnabled;
|
||||
}
|
||||
|
||||
|
||||
@ -758,20 +774,12 @@ nsCacheProfilePrefObserver::ReadPrefs(nsIPrefBranch* branch)
|
||||
if (PermittedToSmartSize(branch, firstSmartSizeRun)) {
|
||||
// Avoid evictions: use previous cache size until smart size event
|
||||
// updates mDiskCacheCapacity
|
||||
if (!firstSmartSizeRun) {
|
||||
PRInt32 oldSmartSize;
|
||||
rv = branch->GetIntPref(DISK_CACHE_SMART_SIZE_PREF,
|
||||
&oldSmartSize);
|
||||
mDiskCacheCapacity = oldSmartSize;
|
||||
} else {
|
||||
PRInt32 oldCapacity;
|
||||
rv = branch->GetIntPref(DISK_CACHE_CAPACITY_PREF, &oldCapacity);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mDiskCacheCapacity = oldCapacity;
|
||||
} else {
|
||||
mDiskCacheCapacity = DEFAULT_CACHE_SIZE;
|
||||
}
|
||||
}
|
||||
rv = branch->GetIntPref(firstSmartSizeRun ?
|
||||
DISK_CACHE_CAPACITY_PREF :
|
||||
DISK_CACHE_SMART_SIZE_PREF,
|
||||
&mDiskCacheCapacity);
|
||||
if (NS_FAILED(rv))
|
||||
mDiskCacheCapacity = DEFAULT_CACHE_SIZE;
|
||||
}
|
||||
|
||||
if (firstSmartSizeRun) {
|
||||
@ -1142,6 +1150,11 @@ nsCacheService::Shutdown()
|
||||
ClearDoomList();
|
||||
ClearActiveEntries();
|
||||
|
||||
if (mSmartSizeTimer) {
|
||||
mSmartSizeTimer->Cancel();
|
||||
mSmartSizeTimer = nsnull;
|
||||
}
|
||||
|
||||
// Make sure to wait for any pending cache-operations before
|
||||
// proceeding with destructive actions (bug #620660)
|
||||
(void) SyncWithCacheIOThread();
|
||||
@ -1447,7 +1460,22 @@ 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.
|
||||
if (!mSmartSizeTimer) {
|
||||
mSmartSizeTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = mSmartSizeTimer->InitWithCallback(new nsSetDiskSmartSizeCallback(),
|
||||
1000*60*3,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to post smart size timer");
|
||||
mSmartSizeTimer = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
@ -2652,11 +2680,11 @@ nsCacheService::SetDiskSmartSize()
|
||||
|
||||
if (!gService) return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
return gService->SetDiskSmartSize_Locked(false);
|
||||
return gService->SetDiskSmartSize_Locked();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCacheService::SetDiskSmartSize_Locked(bool checkPref)
|
||||
nsCacheService::SetDiskSmartSize_Locked()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
@ -2666,17 +2694,8 @@ nsCacheService::SetDiskSmartSize_Locked(bool checkPref)
|
||||
if (!mDiskDevice)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
if (checkPref) {
|
||||
nsCOMPtr<nsIPrefBranch2> branch = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
if (!branch) return NS_ERROR_FAILURE;
|
||||
|
||||
bool smartSizeEnabled;
|
||||
rv = branch->GetBoolPref(DISK_CACHE_SMART_SIZE_ENABLED_PREF,
|
||||
&smartSizeEnabled);
|
||||
|
||||
if (NS_FAILED(rv) || !smartSizeEnabled)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
if (!mObserver->SmartSizeEnabled())
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
nsAutoString cachePath;
|
||||
rv = mObserver->DiskCacheParentDirectory()->GetPath(cachePath);
|
||||
|
5
netwerk/cache/nsCacheService.h
vendored
5
netwerk/cache/nsCacheService.h
vendored
@ -63,6 +63,7 @@ class nsDiskCacheDevice;
|
||||
class nsMemoryCacheDevice;
|
||||
class nsOfflineCacheDevice;
|
||||
class nsCacheServiceAutoLock;
|
||||
class nsITimer;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
@ -196,6 +197,7 @@ private:
|
||||
friend class nsProcessRequestEvent;
|
||||
friend class nsSetSmartSizeEvent;
|
||||
friend class nsBlockOnCacheThreadEvent;
|
||||
friend class nsSetDiskSmartSizeCallback;
|
||||
|
||||
/**
|
||||
* Internal Methods
|
||||
@ -264,7 +266,7 @@ private:
|
||||
void LogCacheStatistics();
|
||||
#endif
|
||||
|
||||
nsresult SetDiskSmartSize_Locked(bool checkPref);
|
||||
nsresult SetDiskSmartSize_Locked();
|
||||
|
||||
/**
|
||||
* Data Members
|
||||
@ -280,6 +282,7 @@ private:
|
||||
nsCOMPtr<nsIThread> mCacheIOThread;
|
||||
|
||||
nsTArray<nsISupports*> mDoomedObjects;
|
||||
nsCOMPtr<nsITimer> mSmartSizeTimer;
|
||||
|
||||
bool mInitialized;
|
||||
|
||||
|
26
netwerk/cache/nsDiskCacheDevice.cpp
vendored
26
netwerk/cache/nsDiskCacheDevice.cpp
vendored
@ -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);
|
||||
|
1
netwerk/cache/nsDiskCacheDevice.h
vendored
1
netwerk/cache/nsDiskCacheDevice.h
vendored
@ -107,6 +107,7 @@ public:
|
||||
|
||||
private:
|
||||
friend class nsDiskCacheDeviceDeactivateEntryEvent;
|
||||
friend class nsEvictDiskCacheEntriesEvent;
|
||||
/**
|
||||
* Private methods
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user