diff --git a/netwerk/cache2/CacheIndex.cpp b/netwerk/cache2/CacheIndex.cpp index e88b9a1d3..977e3785f 100644 --- a/netwerk/cache2/CacheIndex.cpp +++ b/netwerk/cache2/CacheIndex.cpp @@ -69,6 +69,7 @@ public: CacheIndexEntryAutoManage(const SHA1Sum::Hash *aHash, CacheIndex *aIndex) : mIndex(aIndex) , mOldRecord(nullptr) + , mOldFrecency(0) , mDoNotSearchInIndex(false) , mDoNotSearchInUpdates(false) { @@ -79,6 +80,7 @@ public: mIndex->mIndexStats.BeforeChange(entry); if (entry && entry->IsInitialized() && !entry->IsRemoved()) { mOldRecord = entry->mRec; + mOldFrecency = entry->mRec->mFrecency; } } @@ -104,6 +106,8 @@ public: mIndex->ReplaceRecordInIterators(mOldRecord, entry->mRec); mIndex->RemoveRecordFromFrecencyArray(mOldRecord); mIndex->InsertRecordToFrecencyArray(entry->mRec); + } else if (entry->mRec->mFrecency != mOldFrecency) { + mIndex->mFrecencyArraySorted = false; } } else { // both entries were removed or not initialized, do nothing @@ -147,6 +151,7 @@ private: const SHA1Sum::Hash *mHash; RefPtr mIndex; CacheIndexRecord *mOldRecord; + uint32_t mOldFrecency; bool mDoNotSearchInIndex; bool mDoNotSearchInUpdates; }; @@ -246,6 +251,7 @@ CacheIndex::CacheIndex() , mRWBufSize(0) , mRWBufPos(0) , mJournalReadSuccessfully(false) + , mFrecencyArraySorted(false) { sLock.AssertCurrentThreadOwns(); LOG(("CacheIndex::CacheIndex [this=%p]", this)); @@ -1187,7 +1193,11 @@ CacheIndex::GetEntryForEviction(bool aIgnoreEmptyEntries, SHA1Sum::Hash *aHash, uint32_t i; // find first non-forced valid and unpinned entry with the lowest frecency - index->mFrecencyArray.Sort(FrecencyComparator()); + if (!index->mFrecencyArraySorted) { + index->mFrecencyArray.Sort(FrecencyComparator()); + index->mFrecencyArraySorted = true; + } + for (i = 0; i < index->mFrecencyArray.Length(); ++i) { memcpy(&hash, &index->mFrecencyArray[i]->mHash, sizeof(SHA1Sum::Hash)); @@ -1385,7 +1395,11 @@ CacheIndex::GetIterator(nsILoadContextInfo *aInfo, bool aAddNew, iter = new CacheIndexIterator(index, aAddNew); } - index->mFrecencyArray.Sort(FrecencyComparator()); + if (!index->mFrecencyArraySorted) { + index->mFrecencyArray.Sort(FrecencyComparator()); + index->mFrecencyArraySorted = true; + } + iter->AddRecords(index->mFrecencyArray); index->mIterators.AppendElement(iter); @@ -3161,6 +3175,7 @@ CacheIndex::InsertRecordToFrecencyArray(CacheIndexRecord *aRecord) MOZ_ASSERT(!mFrecencyArray.Contains(aRecord)); mFrecencyArray.AppendElement(aRecord); + mFrecencyArraySorted = false; } void diff --git a/netwerk/cache2/CacheIndex.h b/netwerk/cache2/CacheIndex.h index 2a6ef9ae7..1a8779761 100644 --- a/netwerk/cache2/CacheIndex.h +++ b/netwerk/cache2/CacheIndex.h @@ -1020,6 +1020,7 @@ private: // and such entries are stored at the end of the array. Uninitialized entries // and entries marked as deleted are not present in this array. nsTArray mFrecencyArray; + bool mFrecencyArraySorted; nsTArray mIterators; diff --git a/netwerk/cache2/CacheStorageService.cpp b/netwerk/cache2/CacheStorageService.cpp index 913bd8aae..24dbd5186 100644 --- a/netwerk/cache2/CacheStorageService.cpp +++ b/netwerk/cache2/CacheStorageService.cpp @@ -1239,6 +1239,16 @@ CacheStorageService::PurgeOverMemoryLimit() LOG(("CacheStorageService::PurgeOverMemoryLimit")); + static TimeDuration const kFourSeconds = TimeDuration::FromSeconds(4); + TimeStamp now = TimeStamp::NowLoRes(); + + if (!mLastPurgeTime.IsNull() && now - mLastPurgeTime < kFourSeconds) { + LOG((" bypassed, too soon")); + return; + } + + mLastPurgeTime = now; + Pool(true).PurgeOverMemoryLimit(); Pool(false).PurgeOverMemoryLimit(); } diff --git a/netwerk/cache2/CacheStorageService.h b/netwerk/cache2/CacheStorageService.h index c1a6052bf..c699ac799 100644 --- a/netwerk/cache2/CacheStorageService.h +++ b/netwerk/cache2/CacheStorageService.h @@ -311,7 +311,7 @@ private: nsTArray > mFrecencyArray; nsTArray > mExpirationArray; - mozilla::Atomic mMemorySize; + Atomic mMemorySize; bool OnMemoryConsumptionChange(uint32_t aSavedMemorySize, uint32_t aCurrentMemoryConsumption); @@ -330,6 +330,7 @@ private: MemoryPool mDiskPool; MemoryPool mMemoryPool; + TimeStamp mLastPurgeTime; MemoryPool& Pool(bool aUsingDisk) { return aUsingDisk ? mDiskPool : mMemoryPool;