diff options
author | tburkard@chromium.org <tburkard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-14 17:53:01 +0000 |
---|---|---|
committer | tburkard@chromium.org <tburkard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-14 17:53:01 +0000 |
commit | db6c4ea2099370eed9c4f910b847d5bf9df50691 (patch) | |
tree | ca444b2bd7e370b5432be4347ad246f0a533d85e | |
parent | 129781364dbc2e34b2cd191de368900558a61cc8 (diff) | |
download | chromium_src-db6c4ea2099370eed9c4f910b847d5bf9df50691.zip chromium_src-db6c4ea2099370eed9c4f910b847d5bf9df50691.tar.gz chromium_src-db6c4ea2099370eed9c4f910b847d5bf9df50691.tar.bz2 |
Allow multiple local predictor prerenders and make parameters more configurable via Finch trials.
Duplicate of https://codereview.chromium.org/16969003, bug fixed.
TBR=gavinp@chromium.org
Review URL: https://codereview.chromium.org/17060007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@206437 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/prerender/prerender_contents.cc | 6 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_field_trial.cc | 122 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_field_trial.h | 19 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_handle.cc | 6 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_handle.h | 4 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_local_predictor.cc | 173 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_local_predictor.h | 22 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_manager.cc | 2 |
8 files changed, 250 insertions, 104 deletions
diff --git a/chrome/browser/prerender/prerender_contents.cc b/chrome/browser/prerender/prerender_contents.cc index ed97704..de1ec58 100644 --- a/chrome/browser/prerender/prerender_contents.cc +++ b/chrome/browser/prerender/prerender_contents.cc @@ -12,6 +12,7 @@ #include "chrome/browser/favicon/favicon_tab_helper.h" #include "chrome/browser/history/history_tab_helper.h" #include "chrome/browser/history/history_types.h" +#include "chrome/browser/prerender/prerender_field_trial.h" #include "chrome/browser/prerender/prerender_final_status.h" #include "chrome/browser/prerender/prerender_handle.h" #include "chrome/browser/prerender/prerender_manager.h" @@ -267,6 +268,11 @@ void PrerenderContents::StartPrerendering( if (prerender_manager_->IsControlGroup(experiment_id())) return; + if (origin_ == ORIGIN_LOCAL_PREDICTOR && + IsLocalPredictorPrerenderAlwaysControlEnabled()) { + return; + } + prerendering_has_started_ = true; prerender_contents_.reset(CreateWebContents(session_storage_namespace)); diff --git a/chrome/browser/prerender/prerender_field_trial.cc b/chrome/browser/prerender/prerender_field_trial.cc index ea65d49..ca12522 100644 --- a/chrome/browser/prerender/prerender_field_trial.cc +++ b/chrome/browser/prerender/prerender_field_trial.cc @@ -9,6 +9,7 @@ #include "base/metrics/field_trial.h" #include "base/metrics/histogram.h" #include "base/prefs/pref_service.h" +#include "base/strings/string_number_conversions.h" #include "chrome/browser/metrics/metrics_service.h" #include "chrome/browser/predictors/autocomplete_action_predictor.h" #include "chrome/browser/prerender/prerender_manager.h" @@ -26,17 +27,22 @@ namespace { const char kOmniboxTrialName[] = "PrerenderFromOmnibox"; int g_omnibox_trial_default_group_number = kint32min; -const char kLocalPredictorTrialName[] = "PrerenderLocalPredictor"; -const char kLocalPredictorEnabledGroup[] = "Enabled"; -const char kLocalPredictorDisabledGroup[] = "Disabled"; - -const char kLoggedInPredictorTrialName[] = "PrerenderLoggedInPredictor"; -const char kLoggedInPredictorEnabledGroup[] = "Enabled"; -const char kLoggedInPredictorDisabledGroup[] = "Disabled"; +const char kDisabledGroup[] = "Disabled"; +const char kEnabledGroup[] = "Enabled"; -const char kSideEffectFreeWhitelistTrialName[] = "SideEffectFreeWhitelist"; -const char kSideEffectFreeWhitelistEnabledGroup[] = "Enabled"; -const char kSideEffectFreeWhitelistDisabledGroup[] = "Disabled"; +const char kLocalPredictorTrialName[] = "PrerenderLocalPredictor"; +const char kSideEffectFreeWhitelistTrialName[] = + "PrerenderSideEffectFreeWhitelist"; +const char kLocalPredictorPrerenderLaunchTrialName[] = + "PrerenderLocalPredictorPrerenderLanch"; +const char kLocalPredictorPrerenderAlwaysControlTrialName[] = + "PrerenderLocalPredictorPrerenderAlwaysControl"; +const char kLocalPredictorPrerenderTTLTrialName[] = + "PrerenderLocalPredictorPrerenderTTLSeconds"; +const char kLocalPredictorPrerenderPriorityHalfLifeTimeTrialName[] = + "PrerenderLocalPredictorPrerenderPriorityHalfLifeTimeSeconds"; +const char kLocalPredictorMaxConcurrentPrerenderTrialName[] = + "PrerenderLocalPredictorMaxConcurrentPrerenders"; void SetupPrefetchFieldTrial() { chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); @@ -151,8 +157,6 @@ void SetupPrerenderFieldTrial() { void ConfigureOmniboxPrerender(); void ConfigureLocalPredictor(); -void ConfigureLoggedInPredictor(); -void ConfigureSideEffectFreeWhitelist(); void ConfigurePrefetchAndPrerender(const CommandLine& command_line) { enum PrerenderOption { @@ -210,8 +214,6 @@ void ConfigurePrefetchAndPrerender(const CommandLine& command_line) { ConfigureOmniboxPrerender(); ConfigureLocalPredictor(); - ConfigureLoggedInPredictor(); - ConfigureSideEffectFreeWhitelist(); } void ConfigureOmniboxPrerender() { @@ -240,36 +242,8 @@ void ConfigureLocalPredictor() { } scoped_refptr<FieldTrial> local_predictor_trial( FieldTrialList::FactoryGetFieldTrial( - kLocalPredictorTrialName, 100, - kLocalPredictorDisabledGroup, 2013, 12, 31, NULL)); - local_predictor_trial->AppendGroup(kLocalPredictorEnabledGroup, 100); -} - -void ConfigureLoggedInPredictor() { - chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); - if (channel == chrome::VersionInfo::CHANNEL_STABLE || - channel == chrome::VersionInfo::CHANNEL_BETA) { - return; - } - scoped_refptr<FieldTrial> logged_in_predictor_trial( - FieldTrialList::FactoryGetFieldTrial( - kLoggedInPredictorTrialName, 100, - kLoggedInPredictorDisabledGroup, 2013, 12, 31, NULL)); - logged_in_predictor_trial->AppendGroup(kLoggedInPredictorEnabledGroup, 100); -} - -void ConfigureSideEffectFreeWhitelist() { - scoped_refptr<FieldTrial> side_effect_free_whitelist_trial( - FieldTrialList::FactoryGetFieldTrial( - kSideEffectFreeWhitelistTrialName, 100, - kSideEffectFreeWhitelistDisabledGroup, 2013, 12, 31, NULL)); - chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); - if (channel == chrome::VersionInfo::CHANNEL_STABLE || - channel == chrome::VersionInfo::CHANNEL_BETA) { - return; - } - side_effect_free_whitelist_trial->AppendGroup( - kSideEffectFreeWhitelistEnabledGroup, 100); + kLocalPredictorTrialName, 100, kDisabledGroup, 2013, 12, 31, NULL)); + local_predictor_trial->AppendGroup(kEnabledGroup, 100); } bool IsOmniboxEnabled(Profile* profile) { @@ -309,17 +283,67 @@ bool IsLocalPredictorEnabled() { return false; } return base::FieldTrialList::FindFullName(kLocalPredictorTrialName) == - kLocalPredictorEnabledGroup; + kEnabledGroup; } bool IsLoggedInPredictorEnabled() { - return base::FieldTrialList::FindFullName(kLoggedInPredictorTrialName) == - kLoggedInPredictorEnabledGroup; + return IsLocalPredictorEnabled(); } bool IsSideEffectFreeWhitelistEnabled() { - return base::FieldTrialList::FindFullName(kSideEffectFreeWhitelistTrialName) - == kSideEffectFreeWhitelistEnabledGroup; + return IsLocalPredictorEnabled() && + base::FieldTrialList::FindFullName(kSideEffectFreeWhitelistTrialName) != + kDisabledGroup; +} + +bool IsLocalPredictorPrerenderLaunchEnabled() { + return base::FieldTrialList::FindFullName( + kLocalPredictorPrerenderLaunchTrialName) != + kDisabledGroup; } +bool IsLocalPredictorPrerenderAlwaysControlEnabled() { + return base::FieldTrialList::FindFullName( + kLocalPredictorPrerenderAlwaysControlTrialName) == + kEnabledGroup; +} + +int GetLocalPredictorTTLSeconds() { + int ttl; + base::StringToInt( + base::FieldTrialList::FindFullName(kLocalPredictorPrerenderTTLTrialName), + &ttl); + // If the value is outside of 10s or 600s, use a default value of 180s. + if (ttl < 10 || ttl > 600) + ttl = 180; + return ttl; +} + +int GetLocalPredictorPrerenderPriorityHalfLifeTimeSeconds() { + int half_life_time; + base::StringToInt( + base::FieldTrialList::FindFullName( + kLocalPredictorPrerenderPriorityHalfLifeTimeTrialName), + &half_life_time); + // Sanity check: Ensure the half life time is non-negative. + if (half_life_time < 0) + half_life_time = 0; + return half_life_time; +} + +int GetLocalPredictorMaxConcurrentPrerenders() { + int num_prerenders; + base::StringToInt( + base::FieldTrialList::FindFullName( + kLocalPredictorMaxConcurrentPrerenderTrialName), + &num_prerenders); + // Sanity check: Ensure the number of prerenders is at least 1. + if (num_prerenders < 1) + num_prerenders = 1; + // Sanity check: Ensure the number of prerenders is at most 10. + if (num_prerenders > 10) + num_prerenders = 10; + return num_prerenders; +}; + } // namespace prerender diff --git a/chrome/browser/prerender/prerender_field_trial.h b/chrome/browser/prerender/prerender_field_trial.h index 5e80a01..e8ef3aa 100644 --- a/chrome/browser/prerender/prerender_field_trial.h +++ b/chrome/browser/prerender/prerender_field_trial.h @@ -30,6 +30,25 @@ bool IsLoggedInPredictorEnabled(); // Returns true iff the side-effect free whitelist is enabled. bool IsSideEffectFreeWhitelistEnabled(); +// Returns true if the local predictor should actually launch prerenders. +bool IsLocalPredictorPrerenderLaunchEnabled(); + +// Returns true if the local predictor should prerender, but only as control +// group. If the local predictor never launches prerenders, then this setting +// is irrelevant. +bool IsLocalPredictorPrerenderAlwaysControlEnabled(); + +// Returns the TTL to be used for the local predictor. +int GetLocalPredictorTTLSeconds(); + +// Returns the half-life time to use to decay local predictor prerender +// priorities. +int GetLocalPredictorPrerenderPriorityHalfLifeTimeSeconds(); + +// Returns the maximum number of concurrent prerenders the local predictor +// may maintain. +int GetLocalPredictorMaxConcurrentPrerenders(); + } // namespace prerender #endif // CHROME_BROWSER_PRERENDER_PRERENDER_FIELD_TRIAL_H_ diff --git a/chrome/browser/prerender/prerender_handle.cc b/chrome/browser/prerender/prerender_handle.cc index 1b50ecb..dc4f651 100644 --- a/chrome/browser/prerender/prerender_handle.cc +++ b/chrome/browser/prerender/prerender_handle.cc @@ -129,4 +129,10 @@ void PrerenderHandle::OnPrerenderCreatedMatchCompleteReplacement( replacement->AddObserver(this); } +bool PrerenderHandle::RepresentingSamePrerenderAs( + PrerenderHandle* other) const { + return other && other->prerender_data_.get() && prerender_data_.get() + && prerender_data_.get() == other->prerender_data_.get(); +} + } // namespace prerender diff --git a/chrome/browser/prerender/prerender_handle.h b/chrome/browser/prerender/prerender_handle.h index 3e2e946..0a2fae6 100644 --- a/chrome/browser/prerender/prerender_handle.h +++ b/chrome/browser/prerender/prerender_handle.h @@ -74,6 +74,10 @@ class PrerenderHandle : public base::NonThreadSafe, const GURL& url, const content::SessionStorageNamespace* session_storage_namespace) const; + // Returns whether this PrerenderHandle represents the same prerender as + // the other PrerenderHandle object specified. + bool RepresentingSamePrerenderAs(PrerenderHandle* other) const; + private: friend class PrerenderManager; diff --git a/chrome/browser/prerender/prerender_local_predictor.cc b/chrome/browser/prerender/prerender_local_predictor.cc index 2284237..34f1500 100644 --- a/chrome/browser/prerender/prerender_local_predictor.cc +++ b/chrome/browser/prerender/prerender_local_predictor.cc @@ -20,6 +20,7 @@ #include "chrome/browser/history/history_db_task.h" #include "chrome/browser/history/history_service.h" #include "chrome/browser/history/history_service_factory.h" +#include "chrome/browser/prerender/prerender_field_trial.h" #include "chrome/browser/prerender/prerender_handle.h" #include "chrome/browser/prerender/prerender_histograms.h" #include "chrome/browser/prerender/prerender_manager.h" @@ -179,9 +180,12 @@ const int kMaxVisitHistory = 100 * 1000; const int kVisitHistoryPruneThreshold = 120 * 1000; const int kVisitHistoryPruneAmount = 20 * 1000; -const int kMaxLocalPredictionTimeMs = 180 * 1000; const int kMinLocalPredictionTimeMs = 500; +int GetMaxLocalPredictionTimeMs() { + return GetLocalPredictorTTLSeconds() * 1000; +} + bool IsBackForward(PageTransition transition) { return (transition & content::PAGE_TRANSITION_FORWARD_BACK) != 0; } @@ -288,6 +292,27 @@ struct PrerenderLocalPredictor::PrerenderProperties { start_time(start_time) { } + // Default constructor for dummy element + PrerenderProperties() + : priority(0.0) { + } + + double GetCurrentDecayedPriority() { + // If we are no longer prerendering, the priority is 0. + if (!prerender_handle || !prerender_handle->IsPrerendering()) + return 0.0; + int half_life_time_seconds = + GetLocalPredictorPrerenderPriorityHalfLifeTimeSeconds(); + if (half_life_time_seconds < 1) + return priority; + double multiple_elapsed = + (GetCurrentTime() - actual_start_time).InMillisecondsF() / + base::TimeDelta::FromSeconds(half_life_time_seconds).InMillisecondsF(); + // Decay factor: 2 ^ (-multiple_elapsed) + double decay_factor = exp(- multiple_elapsed * log(2.0)); + return priority * decay_factor; + } + URLID url_id; GURL url; double priority; @@ -300,17 +325,17 @@ struct PrerenderLocalPredictor::PrerenderProperties { base::Time start_time; // The actual time this page was last requested for prerendering. base::Time actual_start_time; - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(PrerenderProperties); + scoped_ptr<PrerenderHandle> prerender_handle; + // Indicates whether this prerender would have matched a URL navigated to, + // but was not swapped in for some reason. + bool would_have_matched; }; PrerenderLocalPredictor::PrerenderLocalPredictor( PrerenderManager* prerender_manager) : prerender_manager_(prerender_manager), is_visit_database_observer_(false), - weak_factory_(this), - current_prerender_would_have_matched_(false) { + weak_factory_(this) { RecordEvent(EVENT_CONSTRUCTED); if (base::MessageLoop::current()) { timer_.Start(FROM_HERE, @@ -350,8 +375,12 @@ PrerenderLocalPredictor::PrerenderLocalPredictor( PrerenderLocalPredictor::~PrerenderLocalPredictor() { Shutdown(); - if (prerender_handle_.get()) - prerender_handle_->OnCancel(); + for (int i = 0; i < static_cast<int>(issued_prerenders_.size()); i++) { + PrerenderProperties* p = issued_prerenders_[i]; + DCHECK(p != NULL); + if (p->prerender_handle) + p->prerender_handle->OnCancel(); + } } void PrerenderLocalPredictor::Shutdown() { @@ -382,7 +411,7 @@ void PrerenderLocalPredictor::OnAddVisit(const history::BriefVisitInfo& info) { "Prerender.LocalPredictorTimeUntilUsed", GetCurrentTime() - current_prerender_->actual_start_time, base::TimeDelta::FromMilliseconds(10), - base::TimeDelta::FromMilliseconds(kMaxLocalPredictionTimeMs), + base::TimeDelta::FromMilliseconds(GetMaxLocalPredictionTimeMs()), 50); last_swapped_in_prerender_.reset(current_prerender_.release()); RecordEvent(EVENT_ADD_VISIT_PRERENDER_IDENTIFIED); @@ -391,7 +420,7 @@ void PrerenderLocalPredictor::OnAddVisit(const history::BriefVisitInfo& info) { return; RecordEvent(EVENT_ADD_VISIT_RELEVANT_TRANSITION); base::TimeDelta max_age = - base::TimeDelta::FromMilliseconds(kMaxLocalPredictionTimeMs); + base::TimeDelta::FromMilliseconds(GetMaxLocalPredictionTimeMs()); base::TimeDelta min_age = base::TimeDelta::FromMilliseconds(kMinLocalPredictionTimeMs); std::set<URLID> next_urls_currently_found; @@ -629,7 +658,7 @@ bool PrerenderLocalPredictor::IsPrerenderStillValid( PrerenderLocalPredictor::PrerenderProperties* prerender) const { return (prerender && (prerender->start_time + - base::TimeDelta::FromMilliseconds(kMaxLocalPredictionTimeMs)) + base::TimeDelta::FromMilliseconds(GetMaxLocalPredictionTimeMs())) > GetCurrentTime()); } @@ -652,11 +681,27 @@ bool PrerenderLocalPredictor::DoesPrerenderMatchPLTRecord( } } -bool PrerenderLocalPredictor::ShouldReplaceCurrentPrerender( - double priority) const { - return (!prerender_handle_.get() || - !prerender_handle_->IsPrerendering() || - current_prerender_priority_ < priority); +PrerenderLocalPredictor::PrerenderProperties* +PrerenderLocalPredictor::GetIssuedPrerenderSlotForPriority(double priority) { + int num_prerenders = GetLocalPredictorMaxConcurrentPrerenders(); + while (static_cast<int>(issued_prerenders_.size()) < num_prerenders) + issued_prerenders_.push_back(new PrerenderProperties()); + PrerenderProperties* lowest_priority_prerender = NULL; + for (int i = 0; i < static_cast<int>(issued_prerenders_.size()); i++) { + PrerenderProperties* p = issued_prerenders_[i]; + DCHECK(p != NULL); + if (!p->prerender_handle || !p->prerender_handle->IsPrerendering()) + return p; + double decayed_priority = p->GetCurrentDecayedPriority(); + if (decayed_priority > priority) + continue; + if (lowest_priority_prerender == NULL || + lowest_priority_prerender->GetCurrentDecayedPriority() > + decayed_priority) { + lowest_priority_prerender = p; + } + } + return lowest_priority_prerender; } void PrerenderLocalPredictor::ContinuePrerenderCheck( @@ -667,6 +712,7 @@ void PrerenderLocalPredictor::ContinuePrerenderCheck( scoped_ptr<LocalPredictorURLInfo> url_info; scoped_refptr<SafeBrowsingDatabaseManager> sb_db_manager = g_browser_process->safe_browsing_service()->database_manager(); + PrerenderProperties* prerender_properties = NULL; for (int i = 0; i < static_cast<int>(info->candidate_urls_.size()); i++) { url_info.reset(new LocalPredictorURLInfo(info->candidate_urls_[i])); @@ -684,7 +730,9 @@ void PrerenderLocalPredictor::ContinuePrerenderCheck( url_info.reset(NULL); continue; } - if (!ShouldReplaceCurrentPrerender(url_info->priority)) { + prerender_properties = + GetIssuedPrerenderSlotForPriority(url_info->priority); + if (!prerender_properties) { RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_PRIORITY_TOO_LOW); url_info.reset(NULL); continue; @@ -732,28 +780,58 @@ void PrerenderLocalPredictor::ContinuePrerenderCheck( if (!url_info.get()) return; RecordEvent(EVENT_CONTINUE_PRERENDER_CHECK_ISSUING_PRERENDER); - IssuePrerender(session_storage_namespace, size.Pass(), - url_info.Pass()); + DCHECK(prerender_properties != NULL); + if (IsLocalPredictorPrerenderLaunchEnabled()) { + IssuePrerender(session_storage_namespace, size.Pass(), + url_info.Pass(), prerender_properties); + } } void PrerenderLocalPredictor::IssuePrerender( scoped_refptr<SessionStorageNamespace> session_storage_namespace, scoped_ptr<gfx::Size> size, - scoped_ptr<LocalPredictorURLInfo> info) { + scoped_ptr<LocalPredictorURLInfo> info, + PrerenderProperties* prerender_properties) { URLID url_id = info->id; const GURL& url = info->url; double priority = info->priority; base::Time current_time = GetCurrentTime(); RecordEvent(EVENT_ISSUING_PRERENDER); - current_prerender_priority_ = priority; - scoped_ptr<prerender::PrerenderHandle> old_prerender_handle( - prerender_handle_.release()); - prerender_handle_.reset(prerender_manager_->AddPrerenderFromLocalPredictor( - url, session_storage_namespace.get(), *size)); - current_prerender_would_have_matched_ = false; - if (old_prerender_handle) - old_prerender_handle->OnCancel(); + // Issue the prerender and obtain a new handle. + scoped_ptr<prerender::PrerenderHandle> new_prerender_handle( + prerender_manager_->AddPrerenderFromLocalPredictor( + url, session_storage_namespace.get(), *size)); + + // Check if this is a duplicate of an existing prerender. If yes, clean up + // the new handle. + for (int i = 0; i < static_cast<int>(issued_prerenders_.size()); i++) { + PrerenderProperties* p = issued_prerenders_[i]; + DCHECK(p != NULL); + if (new_prerender_handle && + new_prerender_handle->RepresentingSamePrerenderAs( + p->prerender_handle.get())) { + new_prerender_handle->OnCancel(); + new_prerender_handle.reset(NULL); + break; + } + } + + if (new_prerender_handle.get()) { + // The new prerender does not match any existing prerenders. Update + // prerender_properties so that it reflects the new entry. + prerender_properties->url_id = url_id; + prerender_properties->url = url; + prerender_properties->priority = priority; + prerender_properties->start_time = current_time; + prerender_properties->actual_start_time = current_time; + prerender_properties->would_have_matched = false; + prerender_properties->prerender_handle.swap(new_prerender_handle); + // new_prerender_handle now represents the old previou prerender that we + // are replacing. So we need to cancel it. + if (new_prerender_handle) + new_prerender_handle->OnCancel(); + } RecordEvent(EVENT_ADD_VISIT_PRERENDERING); if (current_prerender_.get() && current_prerender_->url_id == url_id) { @@ -781,24 +859,39 @@ void PrerenderLocalPredictor::IssuePrerender( void PrerenderLocalPredictor::OnTabHelperURLSeen( const GURL& url, WebContents* web_contents) { RecordEvent(EVENT_TAB_HELPER_URL_SEEN); - if (current_prerender_would_have_matched_ || - !prerender_handle_.get() || - !prerender_handle_->Matches(url, NULL)) { - return; - } - RecordEvent(EVENT_TAB_HELPER_URL_SEEN_MATCH); - if (prerender_handle_->Matches( - url, - web_contents->GetController().GetDefaultSessionStorageNamespace())) { - RecordEvent(EVENT_TAB_HELPER_URL_SEEN_NAMESPACE_MATCH); - } + // If the namespace matches and the URL matches, we might be able to swap // in. However, the actual code initating the swapin is in the renderer // and is checking for other criteria (such as POSTs). There may // also be conditions when a swapin should happen but does not. By recording // the two previous events, we can keep an eye on the magnitude of the // discrepancy. - current_prerender_would_have_matched_ = true; + + PrerenderProperties* best_matched_prerender = NULL; + bool session_storage_namespace_matches = false; + for (int i = 0; i < static_cast<int>(issued_prerenders_.size()); i++) { + PrerenderProperties* p = issued_prerenders_[i]; + DCHECK(p != NULL); + if (!p->prerender_handle.get() || + !p->prerender_handle->Matches(url, NULL) || + p->would_have_matched) { + continue; + } + if (!best_matched_prerender || !session_storage_namespace_matches) { + best_matched_prerender = p; + session_storage_namespace_matches = + p->prerender_handle->Matches( + url, + web_contents->GetController(). + GetDefaultSessionStorageNamespace()); + } + } + if (best_matched_prerender) { + RecordEvent(EVENT_TAB_HELPER_URL_SEEN_MATCH); + best_matched_prerender->would_have_matched = true; + if (session_storage_namespace_matches) + RecordEvent(EVENT_TAB_HELPER_URL_SEEN_NAMESPACE_MATCH); + } } } // namespace prerender diff --git a/chrome/browser/prerender/prerender_local_predictor.h b/chrome/browser/prerender/prerender_local_predictor.h index b4098bb..590eeb8 100644 --- a/chrome/browser/prerender/prerender_local_predictor.h +++ b/chrome/browser/prerender/prerender_local_predictor.h @@ -8,6 +8,7 @@ #include <vector> #include "base/containers/hash_tables.h" +#include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" #include "base/timer.h" #include "chrome/browser/common/cancelable_request.h" @@ -123,10 +124,10 @@ class PrerenderLocalPredictor : public history::VisitDatabaseObserver { void OnLookupURL(scoped_ptr<LocalPredictorURLLookupInfo> info); - // Returns whether a new prerender of the specified priority should replace - // the current prerender (based on whether it exists, whether it has expired, - // and based on what its priority is). - bool ShouldReplaceCurrentPrerender(double priority) const; + // Returns an element of issued_prerenders_, which should be replaced + // by a new prerender of the priority indicated, or NULL, if the priority + // is too low. + PrerenderProperties* GetIssuedPrerenderSlotForPriority(double priority); void ContinuePrerenderCheck( scoped_refptr<content::SessionStorageNamespace> session_storage_namespace, @@ -136,8 +137,8 @@ class PrerenderLocalPredictor : public history::VisitDatabaseObserver { void IssuePrerender(scoped_refptr<content::SessionStorageNamespace> session_storage_namespace, scoped_ptr<gfx::Size> size, - scoped_ptr<LocalPredictorURLInfo> info); - + scoped_ptr<LocalPredictorURLInfo> info, + PrerenderProperties* prerender_properties); PrerenderManager* prerender_manager_; base::OneShotTimer<PrerenderLocalPredictor> timer_; @@ -156,19 +157,12 @@ class PrerenderLocalPredictor : public history::VisitDatabaseObserver { scoped_ptr<PrerenderProperties> current_prerender_; scoped_ptr<PrerenderProperties> last_swapped_in_prerender_; - scoped_ptr<PrerenderHandle> prerender_handle_; - double current_prerender_priority_; + ScopedVector<PrerenderProperties> issued_prerenders_; base::hash_set<int64> url_whitelist_; base::WeakPtrFactory<PrerenderLocalPredictor> weak_factory_; - // Indicates whether the current prerender represented by prerender_handle_ - // matched a load in some tab contents, to shed light on how many prerenders - // that could have possibily been swapped in were not swapped in. For - // measurement purposes only. - bool current_prerender_would_have_matched_; - DISALLOW_COPY_AND_ASSIGN(PrerenderLocalPredictor); }; diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc index 8626461..40fc8e2 100644 --- a/chrome/browser/prerender/prerender_manager.cc +++ b/chrome/browser/prerender/prerender_manager.cc @@ -1205,7 +1205,7 @@ base::TimeTicks PrerenderManager::GetExpiryTimeForNewPrerender( Origin origin) const { base::TimeDelta ttl = config_.time_to_live; if (origin == ORIGIN_LOCAL_PREDICTOR) - ttl = base::TimeDelta::FromSeconds(180); + ttl = base::TimeDelta::FromSeconds(GetLocalPredictorTTLSeconds()); return GetCurrentTimeTicks() + ttl; } |