Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1890)

Unified Diff: chrome/browser/predictors/resource_prefetch_predictor.cc

Issue 10817004: Adds speculative prefetching of resources. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/predictors/resource_prefetch_predictor.cc
diff --git a/chrome/browser/predictors/resource_prefetch_predictor.cc b/chrome/browser/predictors/resource_prefetch_predictor.cc
index 5f247e0151d04ad6f3cc1ed8c07f0dfe897ad7d6..bd6b3b3860479c6c68e6a959e7ce61b823a7fd33 100644
--- a/chrome/browser/predictors/resource_prefetch_predictor.cc
+++ b/chrome/browser/predictors/resource_prefetch_predictor.cc
@@ -68,15 +68,6 @@ enum ResourceStatus {
namespace predictors {
-ResourcePrefetchPredictor::Config::Config()
- : max_navigation_lifetime_seconds(60),
- max_urls_to_track(500),
- min_url_visit_count(3),
- max_resources_per_entry(50),
- max_consecutive_misses(3),
- num_resources_assumed_prefetched(25) {
-}
-
ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary()
: resource_type(ResourceType::LAST_TYPE),
was_cached(false) {
@@ -101,7 +92,7 @@ ResourcePrefetchPredictor::UrlTableCacheValue::~UrlTableCacheValue() {
}
ResourcePrefetchPredictor::ResourcePrefetchPredictor(
- const Config& config,
+ const ResourcePrefetchPredictorConfig& config,
Profile* profile)
: profile_(profile),
config_(config),
@@ -112,11 +103,8 @@ ResourcePrefetchPredictor::ResourcePrefetchPredictor(
}
ResourcePrefetchPredictor::~ResourcePrefetchPredictor() {
-}
-
-// static
-bool ResourcePrefetchPredictor::IsEnabled(Profile* profile) {
- return prerender::IsSpeculativeResourcePrefetchingLearningEnabled(profile);
+ prefetch_manager_->ShutdownOnUIThread();
+ prefetch_manager_ = NULL;
}
void ResourcePrefetchPredictor::LazilyInitialize() {
@@ -293,7 +281,6 @@ void ResourcePrefetchPredictor::RecordURLRequest(
} else if (initialization_state_ != INITIALIZED) {
return;
}
- DCHECK_EQ(INITIALIZED, initialization_state_);
CHECK_EQ(request.resource_type, ResourceType::MAIN_FRAME);
OnMainFrameRequest(request);
@@ -340,13 +327,54 @@ void ResourcePrefetchPredictor::OnMainFrameRequest(
// New empty navigation entry.
inflight_navigations_.insert(std::make_pair(
request.navigation_id, std::vector<URLRequestSummary>()));
+
+ const GURL& main_frame_url = request.navigation_id.main_frame_url;
+
+ // If prefetching is enabled, and we can prefetch something, start
+ // prefetching.
+ if (prefetch_manager_.get() &&
dominich 2012/07/23 16:04:41 simpler: if (!prefetch_manager_.get()) return;
Shishir 2012/08/01 22:35:24 Done.
+ url_table_cache_.find(main_frame_url) != url_table_cache_.end()) {
+ const UrlTableCacheValue& value = url_table_cache_[main_frame_url];
+
+ scoped_ptr<ResourcePrefetcher::RequestVector> requests(
+ new ResourcePrefetcher::RequestVector);
+ for (UrlTableRowVector::const_iterator it = value.rows.begin();
+ it != value.rows.end(); ++it) {
+ double confidence = static_cast<double>(it->number_of_hits) /
+ (it->number_of_hits + it->number_of_misses);
+ if (confidence < config_.min_resource_confidence_to_trigger_prefetch ||
dominich 2012/07/23 16:04:41 warning: comparing double to float. Use double thr
Shishir 2012/08/01 22:35:24 Everything is float now.
+ it->number_of_hits < config_.min_resource_hits_to_trigger_prefetch) {
dominich 2012/07/23 16:04:41 maybe histogram this failure case
Shishir 2012/08/01 22:35:24 We indirectly measure this.
+ continue;
+ }
+
+ ResourcePrefetcher::Request* req = new ResourcePrefetcher::Request(
+ it->resource_url);
+ requests->push_back(make_linked_ptr(req));
dominich 2012/07/23 16:04:41 why is this a linked_ptr?
Shishir 2012/08/01 22:35:24 Changed to scoped vector.
+ }
+
+ if (requests->empty())
+ return;
+
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&ResourcePrefetcherManager::MaybeAddPrefetch,
+ prefetch_manager_,
+ request.navigation_id,
+ base::Passed(requests.Pass())));
+ }
}
void ResourcePrefetchPredictor::OnMainFrameResponse(
const URLRequestSummary& response) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (initialization_state_ != INITIALIZED)
+ return;
- // TODO(shishir): The prefreshing will be stopped here.
+ if (prefetch_manager_.get())
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&ResourcePrefetcherManager::MaybeRemovePrefetch,
+ prefetch_manager_,
+ response.navigation_id));
}
void ResourcePrefetchPredictor::OnMainFrameRedirect(
@@ -403,6 +431,15 @@ void ResourcePrefetchPredictor::CleanupAbandonedNavigations(
++it;
}
}
+ for (ResultsMap::iterator it = results_map_.begin();
+ it != results_map_.end();) {
+ if (it->first.IsSameRenderer(navigation_id) ||
+ (time_now - it->first.creation_time > max_navigation_age)) {
+ results_map_.erase(it++);
+ } else {
+ ++it;
+ }
+ }
}
void ResourcePrefetchPredictor::Observe(
@@ -462,6 +499,17 @@ void ResourcePrefetchPredictor::Observe(
}
}
+void ResourcePrefetchPredictor::FinishedPrefetchForNavigation(
+ const NavigationID& navigation_id,
+ scoped_ptr<ResourcePrefetcher::RequestVector> requests) {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ DCHECK(results_map_.find(navigation_id) == results_map_.end());
dominich 2012/07/23 16:04:41 again here you're doing a double lookup (in DEBUG)
Shishir 2012/08/01 22:35:24 Done.
+
+ // Add the results to the results map.
+ results_map_[navigation_id].reset(requests.release());
dominich 2012/07/23 16:04:41 ah, so you're using linked_ptr to have the vector
Shishir 2012/08/01 22:35:24 Done.
+}
+
void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK_EQ(initialization_state_, INITIALIZING);
@@ -504,6 +552,12 @@ void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() {
// TODO(shishir): Maybe listen for notifications for navigation being
// abandoned and cleanup the inflight_navigations_.
+ // Initialize the prefetch manager only if prefetching is enabled.
+ if (prerender::IsSpeculativeResourcePrefetchingEnabled(profile_)) {
+ prefetch_manager_ = new ResourcePrefetcherManager(
+ this, config_, profile_->GetRequestContext());
+ }
+
initialization_state_ = INITIALIZED;
}
@@ -540,7 +594,11 @@ void ResourcePrefetchPredictor::OnNavigationComplete(
NAVIGATION_STATUS_COUNT);
// Report any stats.
- MaybeReportAccuracyStats(navigation_id);
+ if (prefetch_manager_.get()) {
+ MaybeReportAccuracyStats(navigation_id);
+ } else {
+ MaybeReportSimulatedAccuracyStats(navigation_id);
+ }
// Update the URL table.
const GURL& main_frame_url = navigation_id.main_frame_url;
@@ -549,6 +607,7 @@ void ResourcePrefetchPredictor::OnNavigationComplete(
// Remove the navigation.
inflight_navigations_.erase(navigation_id);
+ results_map_.erase(navigation_id);
}
void ResourcePrefetchPredictor::LearnUrlNavigation(
@@ -685,7 +744,7 @@ void ResourcePrefetchPredictor::RemoveAnEntryFromUrlDB() {
urls_to_delete));
}
-void ResourcePrefetchPredictor::MaybeReportAccuracyStats(
+void ResourcePrefetchPredictor::MaybeReportSimulatedAccuracyStats(
const NavigationID& navigation_id) const {
const GURL& main_frame_url = navigation_id.main_frame_url;
DCHECK(inflight_navigations_.find(navigation_id) !=
@@ -735,6 +794,124 @@ void ResourcePrefetchPredictor::MaybeReportAccuracyStats(
prefetch_network * 100.0 / num_assumed_prefetched);
}
+void ResourcePrefetchPredictor::MaybeReportAccuracyStats(
+ const NavigationID& navigation_id) {
+ DCHECK(inflight_navigations_.find(navigation_id) !=
+ inflight_navigations_.end());
+
+ bool have_prefetch_results = results_map_.find(navigation_id) !=
+ results_map_.end();
+ UMA_HISTOGRAM_BOOLEAN("ResourcePrefetchPredictor.HavePrefetchResults",
+ have_prefetch_results);
+ if (!have_prefetch_results)
+ return;
+
+ // Annotate the results.
+ const std::vector<URLRequestSummary>& actual =
+ inflight_navigations_.find(navigation_id)->second;
dominich 2012/07/23 16:04:41 you're doing this find twice - do it once and use
Shishir 2012/08/01 22:35:24 Done.
+ ResourcePrefetcher::RequestVector* prefetched =
+ results_map_.find(navigation_id)->second.get();
dominich 2012/07/23 16:04:41 you're doing this find twice. do it once and cache
Shishir 2012/08/01 22:35:24 Done.
+
+ std::map<GURL, bool> actual_resources;
+ for (std::vector<URLRequestSummary>::const_iterator it = actual.begin();
+ it != actual.end(); ++it) {
+ actual_resources[it->resource_url] = it->was_cached;
+ }
+ for (ResourcePrefetcher::RequestVector::iterator it = prefetched->begin();
+ it != prefetched->end(); ++it) {
+ ResourcePrefetcher::Request* req = it->get();
+ if (actual_resources.find(req->resource_url) != actual_resources.end()) {
+ if (actual_resources[req->resource_url]) {
dominich 2012/07/23 16:04:41 You just did the find to get the iterator - you sh
Shishir 2012/08/01 22:35:24 Done.
+ req->usage_status =
+ ResourcePrefetcher::Request::USAGE_STATUS_FROM_CACHE;
+ } else {
+ req->usage_status =
+ ResourcePrefetcher::Request::USAGE_STATUS_FROM_NETWORK;
+ }
+ }
+ }
+
+ int prefetch_cancelled = 0, prefetch_failed = 0, prefetch_not_started = 0;
+ int p_cache_a_cache = 0, p_cache_a_network = 0, p_cache_a_notused = 0,
dominich 2012/07/23 16:04:41 what is p_? don't use abbreviations.
Shishir 2012/08/01 22:35:24 p_ is for predicted and a_ is actual. Added commen
+ p_network_a_cache = 0, p_network_a_network = 0, p_network_a_notused = 0;
+
+ for (ResourcePrefetcher::RequestVector::iterator it = prefetched->begin();
+ it != prefetched->end(); ++it) {
+ ResourcePrefetcher::Request* req = it->get();
dominich 2012/07/23 16:04:41 You can combine this loop with the one above that
Shishir 2012/08/01 22:35:24 Done.
+ switch (req->prefetch_status) {
+ case ResourcePrefetcher::Request::PREFETCH_STATUS_CANCELLED:
+ ++prefetch_cancelled;
+ break;
+
+ case ResourcePrefetcher::Request::PREFETCH_STATUS_FAILED:
+ ++prefetch_failed;
+ break;
+
+ case ResourcePrefetcher::Request::PREFETCH_STATUS_FROM_CACHE:
+ if (req->usage_status ==
+ ResourcePrefetcher::Request::USAGE_STATUS_FROM_CACHE)
+ ++p_cache_a_cache;
+ else if (req->usage_status ==
+ ResourcePrefetcher::Request::USAGE_STATUS_FROM_NETWORK)
+ ++p_cache_a_network;
+ else
+ ++p_cache_a_notused;
+ break;
+
+ case ResourcePrefetcher::Request::PREFETCH_STATUS_FROM_NETWORK:
+ if (req->usage_status ==
+ ResourcePrefetcher::Request::USAGE_STATUS_FROM_CACHE)
+ ++p_network_a_cache;
+ else if (req->usage_status ==
+ ResourcePrefetcher::Request::USAGE_STATUS_FROM_NETWORK)
+ ++p_network_a_network;
+ else
+ ++p_network_a_notused;
+ break;
+
+ case ResourcePrefetcher::Request::PREFETCH_STATUS_NOT_STARTED:
+ ++prefetch_not_started;
+ break;
+
+ case ResourcePrefetcher::Request::PREFETCH_STATUS_STARTED:
+ DLOG(FATAL) << "Invalid prefetch status";
+
+ }
+ }
+
+ int total_prefetched = p_cache_a_cache + p_cache_a_network + p_cache_a_notused
+ + p_network_a_cache + p_network_a_network + p_network_a_notused;
+
+ UMA_HISTOGRAM_PERCENTAGE(
+ "ResourcePrefetchPredictor.PrefetchCancelled",
+ prefetch_cancelled * 100.0 / total_prefetched);
+ UMA_HISTOGRAM_PERCENTAGE(
+ "ResourcePrefetchPredictor.PrefetchFailed",
+ prefetch_failed * 100.0 / total_prefetched);
+ UMA_HISTOGRAM_PERCENTAGE(
+ "ResourcePrefetchPredictor.PrefetchFromCacheUsedFromCache",
+ p_cache_a_cache * 100.0 / total_prefetched);
+ UMA_HISTOGRAM_PERCENTAGE(
+ "ResourcePrefetchPredictor.PrefetchFromCacheUsedFromNetwork",
+ p_cache_a_network * 100.0 / total_prefetched);
+ UMA_HISTOGRAM_PERCENTAGE(
+ "ResourcePrefetchPredictor.PrefetchFromCacheNotUsed",
+ p_cache_a_notused * 100.0 / total_prefetched);
+ UMA_HISTOGRAM_PERCENTAGE(
+ "ResourcePrefetchPredictor.PrefetchFromNetworkUsedFromCache",
+ p_network_a_cache * 100.0 / total_prefetched);
+ UMA_HISTOGRAM_PERCENTAGE(
+ "ResourcePrefetchPredictor.PrefetchFromNetworkUsedFromNetwork",
+ p_network_a_network * 100.0 / total_prefetched);
+ UMA_HISTOGRAM_PERCENTAGE(
+ "ResourcePrefetchPredictor.PrefetchFromNetworkNotUsed",
+ p_network_a_notused * 100.0 / total_prefetched);
+
+ UMA_HISTOGRAM_PERCENTAGE(
+ "ResourcePrefetchPredictor.PrefetchNotStarted",
+ prefetch_not_started * 100.0 / (prefetch_not_started + total_prefetched));
+}
+
void ResourcePrefetchPredictor::DeleteAllUrls() {
inflight_navigations_.clear();
url_table_cache_.clear();

Powered by Google App Engine
This is Rietveld 408576698