Bug 610417 - Optimize eviction in bfcache. r=smaug a=blocking-fennec

This commit is contained in:
Alon Zakai 2011-01-19 11:57:36 -08:00
Родитель b3a5be1b97
Коммит 41f8df6ed0
6 изменённых файлов: 66 добавлений и 5 удалений

Просмотреть файл

@ -907,6 +907,8 @@ pref("browser.shell.checkDefaultBrowser", false);
// disable bfcache for memory
pref("browser.sessionhistory.max_total_viewers", 0);
pref("browser.sessionhistory.optimize_eviction", false);
// tweak default content sink prefs
pref("content.sink.interactive_deflect_count", 10); /* default 0 */
pref("content.sink.perf_deflect_count", 50); /* default 200 */

Просмотреть файл

@ -250,11 +250,16 @@ interface nsISHEntry : nsIHistoryEntry
attribute unsigned long long docshellID;
};
[scriptable, uuid(e0b0ac6d-cb29-4be2-b685-1755d6301a69)]
[scriptable, uuid(bb66ac35-253b-471f-a317-3ece940f04c5)]
interface nsISHEntryInternal : nsISupports
{
[notxpcom] void RemoveFromBFCacheAsync();
[notxpcom] void RemoveFromBFCacheSync();
/**
* A number that is assigned by the sHistory when the entry is activated
*/
attribute unsigned long lastTouched;
};
%{ C++

Просмотреть файл

@ -117,6 +117,7 @@ nsSHEntry::nsSHEntry()
, mParent(nsnull)
, mViewerBounds(0, 0, 0, 0)
, mDocShellID(0)
, mLastTouched(0)
{
}
@ -998,3 +999,18 @@ nsSHEntry::SetDocshellID(PRUint64 aID)
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetLastTouched(unsigned int *aLastTouched)
{
*aLastTouched = mLastTouched;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetLastTouched(unsigned int aLastTouched)
{
mLastTouched = aLastTouched;
return NS_OK;
}

Просмотреть файл

@ -120,6 +120,7 @@ private:
nsAutoPtr<nsDocShellEditorData> mEditorData;
nsString mStateData;
PRUint64 mDocShellID;
PRUint32 mLastTouched;
};
#endif /* nsSHEntry_h */

Просмотреть файл

@ -70,6 +70,7 @@
#define PREF_SHISTORY_SIZE "browser.sessionhistory.max_entries"
#define PREF_SHISTORY_MAX_TOTAL_VIEWERS "browser.sessionhistory.max_total_viewers"
#define PREF_SHISTORY_OPTIMIZE_EVICTION "browser.sessionhistory.optimize_eviction"
static PRInt32 gHistoryMaxSize = 50;
// Max viewers allowed per SHistory objects
@ -80,6 +81,16 @@ static PRCList gSHistoryList;
// means we will calculate how many viewers to cache based on total memory
PRInt32 nsSHistory::sHistoryMaxTotalViewers = -1;
// Whether we should optimize the search for which entry to evict,
// by evicting older entries first. See entryLastTouched in
// nsSHistory::EvictGlobalContentViewer().
// NB: After 4.0, we should remove this option and the corresponding
// pref - optimization should always be used
static PRBool gOptimizeEviction = PR_FALSE;
// A counter that is used to be able to know the order in which
// entries were touched, so that we can evict older entries first.
static PRUint32 gTouchCounter = 0;
enum HistCmd{
HIST_CMD_BACK,
HIST_CMD_FORWARD,
@ -222,6 +233,8 @@ nsSHistory::UpdatePrefs(nsIPrefBranch *aPrefBranch)
aPrefBranch->GetIntPref(PREF_SHISTORY_SIZE, &gHistoryMaxSize);
aPrefBranch->GetIntPref(PREF_SHISTORY_MAX_TOTAL_VIEWERS,
&sHistoryMaxTotalViewers);
aPrefBranch->GetBoolPref(PREF_SHISTORY_OPTIMIZE_EVICTION,
&gOptimizeEviction);
// If the pref is negative, that means we calculate how many viewers
// we think we should cache, based on total memory
if (sHistoryMaxTotalViewers < 0) {
@ -265,6 +278,8 @@ nsSHistory::Startup()
branch->AddObserver(PREF_SHISTORY_SIZE, obs, PR_FALSE);
branch->AddObserver(PREF_SHISTORY_MAX_TOTAL_VIEWERS,
obs, PR_FALSE);
branch->AddObserver(PREF_SHISTORY_OPTIMIZE_EVICTION,
obs, PR_FALSE);
nsCOMPtr<nsIObserverService> obsSvc =
mozilla::services::GetObserverService();
@ -937,6 +952,7 @@ nsSHistory::EvictGlobalContentViewer()
// farthest from the current focus in any SHistory object. The
// ContentViewer associated with that SHEntry will be evicted
PRInt32 distanceFromFocus = 0;
PRUint32 candidateLastTouched = 0;
nsCOMPtr<nsISHEntry> evictFromSHE;
nsCOMPtr<nsIContentViewer> evictViewer;
PRInt32 totalContentViewers = 0;
@ -961,6 +977,15 @@ nsSHistory::EvictGlobalContentViewer()
entry->GetAnyContentViewer(getter_AddRefs(ownerEntry),
getter_AddRefs(viewer));
PRUint32 entryLastTouched = 0;
if (gOptimizeEviction) {
nsCOMPtr<nsISHEntryInternal> entryInternal = do_QueryInterface(entry);
if (entryInternal) {
// Find when this entry was last activated
entryInternal->GetLastTouched(&entryLastTouched);
}
}
#ifdef DEBUG_PAGE_CACHE
nsCOMPtr<nsIURI> uri;
if (ownerEntry) {
@ -985,12 +1010,16 @@ nsSHistory::EvictGlobalContentViewer()
printf("mIndex: %d i: %d\n", shist->mIndex, i);
#endif
totalContentViewers++;
if (distance > distanceFromFocus) {
// If this entry is further away from focus than any previously found
// or at the same distance but it is longer time since it was activated
// then take this entry as the new candiate for eviction
if (distance > distanceFromFocus || (distance == distanceFromFocus && candidateLastTouched > entryLastTouched)) {
#ifdef DEBUG_PAGE_CACHE
printf("Choosing as new eviction candidate: %s\n", spec.get());
#endif
candidateLastTouched = entryLastTouched;
distanceFromFocus = distance;
evictFromSHE = ownerEntry;
evictViewer = viewer;
@ -1404,7 +1433,6 @@ NS_IMETHODIMP
nsSHistory::LoadEntry(PRInt32 aIndex, long aLoadType, PRUint32 aHistCmd)
{
nsCOMPtr<nsIDocShell> docShell;
nsCOMPtr<nsISHEntry> shEntry;
// Keep note of requested history index in mRequestedIndex.
mRequestedIndex = aIndex;
@ -1419,6 +1447,13 @@ nsSHistory::LoadEntry(PRInt32 aIndex, long aLoadType, PRUint32 aHistCmd)
return NS_ERROR_FAILURE;
}
// Remember that this entry is getting loaded at this point in the sequence
nsCOMPtr<nsISHEntryInternal> entryInternal = do_QueryInterface(nextEntry);
if (entryInternal) {
entryInternal->SetLastTouched(++gTouchCounter);
}
// Send appropriate listener notifications
PRBool canNavigate = PR_TRUE;
// Get the uri for the entry we are about to visit

Просмотреть файл

@ -105,6 +105,8 @@ pref("dom.indexedDB.warningQuota", 50);
// of content viewers to cache based on the amount of available memory.
pref("browser.sessionhistory.max_total_viewers", -1);
pref("browser.sessionhistory.optimize_eviction", false);
pref("ui.use_native_colors", true);
pref("ui.use_native_popup_windows", false);
pref("ui.click_hold_context_menus", false);