Make sure to always set the right capacity on the memory cache device. Bug

309729, patch by Alfred Kayser <alfredkayser@nl.ibm.com>, r=darin, sr=bzbarsky
This commit is contained in:
bzbarsky%mit.edu 2005-10-09 19:58:06 +00:00
Родитель 4989d9b958
Коммит 99ff4ebd94
2 изменённых файлов: 78 добавлений и 106 удалений

179
netwerk/cache/src/nsCacheService.cpp поставляемый
Просмотреть файл

@ -85,9 +85,6 @@
#define MEMORY_CACHE_ENABLE_PREF "browser.cache.memory.enable"
#define MEMORY_CACHE_CAPACITY_PREF "browser.cache.memory.capacity"
#define MEMORY_CACHE_MAX_ENTRY_SIZE_PREF "browser.cache.memory.max_entry_size"
#define MEMORY_CACHE_CAPACITY 4096
#define BROWSER_CACHE_MEMORY_CAPACITY 4096
class nsCacheProfilePrefObserver : public nsIObserver
@ -116,7 +113,7 @@ public:
nsILocalFile * DiskCacheParentDirectory() { return mDiskCacheParentDirectory; }
PRBool MemoryCacheEnabled();
PRInt32 MemoryCacheCapacity() { return mMemoryCacheCapacity; }
PRInt32 MemoryCacheCapacity();
private:
PRBool mHaveProfile;
@ -302,13 +299,13 @@ nsCacheProfilePrefObserver::Observe(nsISupports * subject,
rv = branch->GetBoolPref(MEMORY_CACHE_ENABLE_PREF,
&mMemoryCacheEnabled);
if (NS_FAILED(rv)) return rv;
nsCacheService::SetMemoryCacheEnabled(MemoryCacheEnabled());
nsCacheService::SetMemoryCache();
} else if (!strcmp(MEMORY_CACHE_CAPACITY_PREF, data.get())) {
(void) branch->GetIntPref(MEMORY_CACHE_CAPACITY_PREF,
&mMemoryCacheCapacity);
nsCacheService::SetMemoryCacheCapacity(mMemoryCacheCapacity);
nsCacheService::SetMemoryCache();
}
}
@ -401,6 +398,67 @@ nsCacheProfilePrefObserver::MemoryCacheEnabled()
}
/**
* MemoryCacheCapacity
*
* If the browser.cache.memory.capacity preference is positive, we use that
* value for the amount of memory available for the cache.
*
* If browser.cache.memory.capacity is zero, the memory cache is disabled.
*
* If browser.cache.memory.capacity is negative or not present, we use a
* formula that grows less than linearly with the amount of system memory.
*
* RAM Cache
* --- -----
* 32 Mb 2 Mb
* 64 Mb 4 Mb
* 128 Mb 8 Mb
* 256 Mb 14 Mb
* 512 Mb 22 Mb
* 1024 Mb 32 Mb
* 2048 Mb 44 Mb
* 4096 Mb 58 Mb
*
* The equation for this is (for cache size C and memory size K (kbytes)):
* x = log2(K) - 14
* C = x^2 - x + 2
*/
PRInt32
nsCacheProfilePrefObserver::MemoryCacheCapacity()
{
PRInt32 capacity = mMemoryCacheCapacity;
if (capacity >= 0)
return capacity;
PRUint64 bytes = PR_GetPhysicalMemorySize();
if (LL_CMP(bytes, ==, LL_ZERO))
return 0;
// Conversion from unsigned int64 to double doesn't work on all platforms.
// We need to truncate the value at LL_MAXINT to make sure we don't
// overflow.
if (LL_CMP(bytes, >, LL_MAXINT))
bytes = LL_MAXINT;
PRUint64 kbytes;
LL_SHR(kbytes, bytes, 10);
double kBytesD;
LL_L2D(kBytesD, (PRInt64) kbytes);
double x = log(kBytesD)/log(2.0) - 14;
if (x > 0) {
capacity = (PRInt32)(x * x - x + 2.001); // add .001 for rounding
capacity *= 1024;
} else {
capacity = 0;
}
return capacity;
}
/******************************************************************************
* nsCacheService
@ -481,10 +539,6 @@ nsCacheService::Init()
mObserver->Install();
mEnableDiskDevice = mObserver->DiskCacheEnabled();
mEnableMemoryDevice = mObserver->MemoryCacheEnabled();
rv = CreateMemoryDevice();
if (NS_FAILED(rv) && (rv != NS_ERROR_NOT_AVAILABLE))
return rv;
mInitialized = PR_TRUE;
return NS_OK;
@ -751,7 +805,7 @@ nsCacheService::CreateMemoryDevice()
if (!mMemoryDevice) return NS_ERROR_OUT_OF_MEMORY;
// set preference
mMemoryDevice->SetCapacity(CacheMemoryAvailable());
mMemoryDevice->SetCapacity(mObserver->MemoryCacheCapacity());
nsresult rv = mMemoryDevice->Init();
if (NS_FAILED(rv)) {
@ -1189,12 +1243,7 @@ nsCacheService::OnProfileChanged()
nsAutoLock lock(gService->mCacheServiceLock);
gService->mEnableDiskDevice = gService->mObserver->DiskCacheEnabled();
gService->mEnableMemoryDevice = gService->mObserver->MemoryCacheEnabled();
if (gService->mEnableMemoryDevice && !gService->mMemoryDevice) {
(void) gService->CreateMemoryDevice();
}
#ifdef NECKO_DISK_CACHE
if (gService->mDiskDevice) {
gService->mDiskDevice->SetCacheParentDirectory(gService->mObserver->DiskCacheParentDirectory());
@ -1210,8 +1259,11 @@ nsCacheService::OnProfileChanged()
}
#endif // !NECKO_DISK_CACHE
gService->SetMemoryCache();
if (gService->mMemoryDevice) {
gService->mMemoryDevice->SetCapacity(gService->CacheMemoryAvailable());
// Clean contents from memory cache
// Is using Init the right thing? Why not just 'EvictEntries(nsnull)'?
rv = gService->mMemoryDevice->Init();
if (NS_FAILED(rv) && (rv != NS_ERROR_ALREADY_INITIALIZED)) {
NS_ERROR("nsCacheService::OnProfileChanged: Re-initializing memory device failed");
@ -1248,105 +1300,28 @@ nsCacheService::SetDiskCacheCapacity(PRInt32 capacity)
void
nsCacheService::SetMemoryCacheEnabled(PRBool enabled)
nsCacheService::SetMemoryCache()
{
if (!gService) return;
nsAutoLock lock(gService->mCacheServiceLock);
gService->mEnableMemoryDevice = enabled;
if (enabled) {
if (!gService->mMemoryDevice) {
// allocate memory device, if necessary
(void) gService->CreateMemoryDevice();
gService->mEnableMemoryDevice = gService->mObserver->MemoryCacheEnabled();
if (gService->mEnableMemoryDevice) {
if (gService->mMemoryDevice) {
// make sure that capacity is reset to the right value
gService->mMemoryDevice->SetCapacity(gService->mObserver->MemoryCacheCapacity());
}
} else {
if (gService->mMemoryDevice) {
// tell memory device to evict everything
gService->mMemoryDevice->SetCapacity(0);
// Don't delete memory device, because some entries may be active still...
}
}
}
void
nsCacheService::SetMemoryCacheCapacity(PRInt32 capacity)
{
if (!gService) return;
nsAutoLock lock(gService->mCacheServiceLock);
gService->mEnableMemoryDevice = gService->mObserver->MemoryCacheEnabled();
if (gService->mEnableMemoryDevice && !gService->mMemoryDevice) {
(void) gService->CreateMemoryDevice();
}
if (gService->mMemoryDevice) {
gService->mMemoryDevice->SetCapacity(gService->CacheMemoryAvailable());
}
}
/**
* CacheMemoryAvailable
*
* If the browser.cache.memory.capacity preference is positive, we use that
* value for the amount of memory available for the cache.
*
* If browser.cache.memory.capacity is zero, the memory cache is disabled.
*
* If browser.cache.memory.capacity is negative or not present, we use a
* formula that grows less than linearly with the amount of system memory.
*
* RAM Cache
* --- -----
* 32 Mb 2 Mb
* 64 Mb 4 Mb
* 128 Mb 8 Mb
* 256 Mb 14 Mb
* 512 Mb 22 Mb
* 1024 Mb 32 Mb
* 2048 Mb 44 Mb
* 4096 Mb 58 Mb
*
* The equation for this is (for cache size C and memory size K (kbytes)):
* x = log2(K) - 14
* C = x^2 - x + 2
*/
PRInt32
nsCacheService::CacheMemoryAvailable()
{
PRInt32 capacity = mObserver->MemoryCacheCapacity();
if (capacity >= 0)
return capacity;
PRUint64 bytes = PR_GetPhysicalMemorySize();
if (LL_CMP(bytes, ==, LL_ZERO))
return 0;
// Conversion from unsigned int64 to double doesn't work on all platforms.
// We need to truncate the value at LL_MAXINT to make sure we don't
// overflow.
if (LL_CMP(bytes, >, LL_MAXINT))
bytes = LL_MAXINT;
PRUint64 kbytes;
LL_SHR(kbytes, bytes, 10);
double kBytesD;
LL_L2D(kBytesD, (PRInt64) kbytes);
double x = log(kBytesD)/log(2.0) - 14;
if (x > 0) {
capacity = (PRInt32)(x * x - x + 2.001); // add .001 for rounding
capacity *= 1024;
} else {
capacity = 0;
}
return capacity;
}
/******************************************************************************
* static methods for nsCacheEntryDescriptor
*****************************************************************************/

5
netwerk/cache/src/nsCacheService.h поставляемый
Просмотреть файл

@ -144,8 +144,7 @@ public:
static void SetDiskCacheEnabled(PRBool enabled);
static void SetDiskCacheCapacity(PRInt32 capacity);
static void SetMemoryCacheEnabled(PRBool enabled);
static void SetMemoryCacheCapacity(PRInt32 capacity);
static void SetMemoryCache();
nsresult Init();
void Shutdown();
@ -194,8 +193,6 @@ private:
void ClearActiveEntries(void);
void DoomActiveEntries(void);
PRInt32 CacheMemoryAvailable();
static
PLDHashOperator PR_CALLBACK DeactivateAndClearEntry(PLDHashTable * table,
PLDHashEntryHdr * hdr,