Chromium Code Reviews| 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(); |