Chromium Code Reviews

Side by Side 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: Adding Unittest. Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/predictors/resource_prefetch_predictor.h" 5 #include "chrome/browser/predictors/resource_prefetch_predictor.h"
6 6
7 #include <map> 7 #include <map>
8 #include <set> 8 #include <set>
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "base/stl_util.h" 13 #include "base/stl_util.h"
14 #include "base/string_number_conversions.h" 14 #include "base/string_number_conversions.h"
15 #include "base/stringprintf.h" 15 #include "base/stringprintf.h"
16 #include "base/time.h" 16 #include "base/time.h"
17 #include "chrome/browser/history/history.h" 17 #include "chrome/browser/history/history.h"
18 #include "chrome/browser/history/history_notifications.h" 18 #include "chrome/browser/history/history_notifications.h"
19 #include "chrome/browser/history/history_service_factory.h" 19 #include "chrome/browser/history/history_service_factory.h"
20 #include "chrome/browser/history/in_memory_database.h" 20 #include "chrome/browser/history/in_memory_database.h"
21 #include "chrome/browser/history/url_database.h" 21 #include "chrome/browser/history/url_database.h"
22 #include "chrome/browser/predictors/predictor_database.h" 22 #include "chrome/browser/predictors/predictor_database.h"
23 #include "chrome/browser/predictors/predictor_database_factory.h" 23 #include "chrome/browser/predictors/predictor_database_factory.h"
24 #include "chrome/browser/predictors/resource_prefetcher_manager.h"
24 #include "chrome/browser/prerender/prerender_field_trial.h" 25 #include "chrome/browser/prerender/prerender_field_trial.h"
25 #include "chrome/browser/profiles/profile.h" 26 #include "chrome/browser/profiles/profile.h"
26 #include "chrome/common/chrome_notification_types.h" 27 #include "chrome/common/chrome_notification_types.h"
27 #include "chrome/common/chrome_switches.h" 28 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/url_constants.h" 29 #include "chrome/common/url_constants.h"
29 #include "content/public/browser/browser_thread.h" 30 #include "content/public/browser/browser_thread.h"
30 #include "content/public/browser/load_from_memory_cache_details.h" 31 #include "content/public/browser/load_from_memory_cache_details.h"
31 #include "content/public/browser/navigation_controller.h" 32 #include "content/public/browser/navigation_controller.h"
32 #include "content/public/browser/notification_service.h" 33 #include "content/public/browser/notification_service.h"
33 #include "content/public/browser/notification_source.h" 34 #include "content/public/browser/notification_source.h"
(...skipping 48 matching lines...)
82 void RecordNavigationEvent(NavigationEvent event) { 83 void RecordNavigationEvent(NavigationEvent event) {
83 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationEvent", 84 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.NavigationEvent",
84 event, 85 event,
85 NAVIGATION_EVENT_COUNT); 86 NAVIGATION_EVENT_COUNT);
86 } 87 }
87 88
88 } // namespace 89 } // namespace
89 90
90 namespace predictors { 91 namespace predictors {
91 92
92 ResourcePrefetchPredictor::Config::Config()
93 : max_navigation_lifetime_seconds(60),
94 max_urls_to_track(500),
95 min_url_visit_count(3),
96 max_resources_per_entry(50),
97 max_consecutive_misses(3) {
98 }
99
100 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary() 93 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary()
101 : resource_type(ResourceType::LAST_TYPE), 94 : resource_type(ResourceType::LAST_TYPE),
102 was_cached(false) { 95 was_cached(false) {
103 } 96 }
104 97
105 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary( 98 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary(
106 const URLRequestSummary& other) 99 const URLRequestSummary& other)
107 : navigation_id(other.navigation_id), 100 : navigation_id(other.navigation_id),
108 resource_url(other.resource_url), 101 resource_url(other.resource_url),
109 resource_type(other.resource_type), 102 resource_type(other.resource_type),
110 mime_type(other.mime_type), 103 mime_type(other.mime_type),
111 was_cached(other.was_cached), 104 was_cached(other.was_cached),
112 redirect_url(other.redirect_url) { 105 redirect_url(other.redirect_url) {
113 } 106 }
114 107
115 ResourcePrefetchPredictor::URLRequestSummary::~URLRequestSummary() { 108 ResourcePrefetchPredictor::URLRequestSummary::~URLRequestSummary() {
116 } 109 }
117 110
118 ResourcePrefetchPredictor::UrlTableCacheValue::UrlTableCacheValue() { 111 ResourcePrefetchPredictor::UrlTableCacheValue::UrlTableCacheValue() {
119 } 112 }
120 113
121 ResourcePrefetchPredictor::UrlTableCacheValue::~UrlTableCacheValue() { 114 ResourcePrefetchPredictor::UrlTableCacheValue::~UrlTableCacheValue() {
122 } 115 }
123 116
124 ResourcePrefetchPredictor::ResourcePrefetchPredictor( 117 ResourcePrefetchPredictor::ResourcePrefetchPredictor(
125 const Config& config, 118 const ResourcePrefetchPredictorConfig& config,
126 Profile* profile) 119 Profile* profile)
127 : profile_(profile), 120 : profile_(profile),
128 config_(config), 121 config_(config),
129 initialization_state_(NOT_INITIALIZED), 122 initialization_state_(NOT_INITIALIZED),
130 tables_(PredictorDatabaseFactory::GetForProfile( 123 tables_(PredictorDatabaseFactory::GetForProfile(
131 profile)->resource_prefetch_tables()) { 124 profile)->resource_prefetch_tables()),
125 results_map_deleter_(&results_map_) {
132 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 126 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
133 127
134 notification_registrar_.Add(this, 128 notification_registrar_.Add(this,
135 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, 129 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
136 content::NotificationService::AllSources()); 130 content::NotificationService::AllSources());
137 } 131 }
138 132
139 ResourcePrefetchPredictor::~ResourcePrefetchPredictor() { 133 ResourcePrefetchPredictor::~ResourcePrefetchPredictor() {
140 } 134 prefetch_manager_->ShutdownOnUIThread();
dominich 2012/09/11 17:40:11 As this is a ProfileKeyedService this might belong
Shishir 2012/09/11 18:18:08 Done.
141 135 prefetch_manager_ = NULL;
142 // static
143 bool ResourcePrefetchPredictor::IsEnabled(Profile* profile) {
144 return prerender::IsSpeculativeResourcePrefetchingLearningEnabled(profile);
145 } 136 }
146 137
147 void ResourcePrefetchPredictor::LazilyInitialize() { 138 void ResourcePrefetchPredictor::LazilyInitialize() {
148 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 139 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
149 140
150 DCHECK_EQ(initialization_state_, NOT_INITIALIZED); 141 DCHECK_EQ(initialization_state_, NOT_INITIALIZED);
151 initialization_state_ = INITIALIZING; 142 initialization_state_ = INITIALIZING;
152 143
153 // Request the in-memory database from the history to force it to load so it's 144 // Request the in-memory database from the history to force it to load so it's
154 // available as soon as possible. 145 // available as soon as possible.
(...skipping 196 matching lines...)
351 DCHECK_EQ(INITIALIZED, initialization_state_); 342 DCHECK_EQ(INITIALIZED, initialization_state_);
352 343
353 RecordNavigationEvent(NAVIGATION_EVENT_REQUEST_STARTED); 344 RecordNavigationEvent(NAVIGATION_EVENT_REQUEST_STARTED);
354 345
355 // Cleanup older navigations. 346 // Cleanup older navigations.
356 CleanupAbandonedNavigations(request.navigation_id); 347 CleanupAbandonedNavigations(request.navigation_id);
357 348
358 // New empty navigation entry. 349 // New empty navigation entry.
359 inflight_navigations_.insert(std::make_pair( 350 inflight_navigations_.insert(std::make_pair(
360 request.navigation_id, std::vector<URLRequestSummary>())); 351 request.navigation_id, std::vector<URLRequestSummary>()));
352
353 // If prefetching is enabled, and we can prefetch something, start
354 // prefetching.
355 if (!prefetch_manager_.get())
356 return;
357
358 const GURL& main_frame_url = request.navigation_id.main_frame_url;
359 const UrlTableCacheMap::const_iterator value_iter = url_table_cache_.find(
360 main_frame_url);
361 if (value_iter == url_table_cache_.end())
362 return;
363
364 const UrlTableCacheValue& value = value_iter->second;
365
366 scoped_ptr<ResourcePrefetcher::RequestVector> requests(
367 new ResourcePrefetcher::RequestVector);
368 for (UrlTableRowVector::const_iterator it = value.rows.begin();
369 it != value.rows.end(); ++it) {
370 float confidence = static_cast<float>(it->number_of_hits) /
371 (it->number_of_hits + it->number_of_misses);
372 if (confidence < config_.min_resource_confidence_to_trigger_prefetch ||
373 it->number_of_hits < config_.min_resource_hits_to_trigger_prefetch) {
374 continue;
375 }
376
377 ResourcePrefetcher::Request* req = new ResourcePrefetcher::Request(
378 it->resource_url);
379 requests->push_back(req);
380 }
381
382 if (requests->empty())
383 return;
384
385 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
386 base::Bind(&ResourcePrefetcherManager::MaybeAddPrefetch,
387 prefetch_manager_,
388 request.navigation_id,
389 base::Passed(&requests)));
361 } 390 }
362 391
363 void ResourcePrefetchPredictor::OnMainFrameResponse( 392 void ResourcePrefetchPredictor::OnMainFrameResponse(
364 const URLRequestSummary& response) { 393 const URLRequestSummary& response) {
365 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 394 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
395 if (initialization_state_ != INITIALIZED)
396 return;
366 397
367 RecordNavigationEvent(NAVIGATION_EVENT_RESPONSE_STARTED); 398 RecordNavigationEvent(NAVIGATION_EVENT_RESPONSE_STARTED);
368 399
369 // TODO(shishir): The prefreshing will be stopped here. 400 if (prefetch_manager_.get())
401 BrowserThread::PostTask(
402 BrowserThread::IO, FROM_HERE,
403 base::Bind(&ResourcePrefetcherManager::MaybeRemovePrefetch,
404 prefetch_manager_,
405 response.navigation_id));
370 } 406 }
371 407
372 void ResourcePrefetchPredictor::OnMainFrameRedirect( 408 void ResourcePrefetchPredictor::OnMainFrameRedirect(
373 const URLRequestSummary& response) { 409 const URLRequestSummary& response) {
374 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 410 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
375 411
376 RecordNavigationEvent(NAVIGATION_EVENT_REQUEST_REDIRECTED); 412 RecordNavigationEvent(NAVIGATION_EVENT_REQUEST_REDIRECTED);
377 413
378 // Remove the older navigation. 414 // Remove the older navigation.
379 inflight_navigations_.erase(response.navigation_id); 415 inflight_navigations_.erase(response.navigation_id);
(...skipping 51 matching lines...)
431 for (NavigationMap::iterator it = inflight_navigations_.begin(); 467 for (NavigationMap::iterator it = inflight_navigations_.begin();
432 it != inflight_navigations_.end();) { 468 it != inflight_navigations_.end();) {
433 if (it->first.IsSameRenderer(navigation_id) || 469 if (it->first.IsSameRenderer(navigation_id) ||
434 (time_now - it->first.creation_time > max_navigation_age)) { 470 (time_now - it->first.creation_time > max_navigation_age)) {
435 inflight_navigations_.erase(it++); 471 inflight_navigations_.erase(it++);
436 RecordNavigationEvent(NAVIGATION_EVENT_REQUEST_EXPIRED); 472 RecordNavigationEvent(NAVIGATION_EVENT_REQUEST_EXPIRED);
437 } else { 473 } else {
438 ++it; 474 ++it;
439 } 475 }
440 } 476 }
477 for (ResultsMap::iterator it = results_map_.begin();
478 it != results_map_.end();) {
479 if (it->first.IsSameRenderer(navigation_id) ||
480 (time_now - it->first.creation_time > max_navigation_age)) {
481 delete it->second;
482 results_map_.erase(it++);
483 } else {
484 ++it;
485 }
486 }
441 } 487 }
442 488
443 void ResourcePrefetchPredictor::Observe( 489 void ResourcePrefetchPredictor::Observe(
444 int type, 490 int type,
445 const content::NotificationSource& source, 491 const content::NotificationSource& source,
446 const content::NotificationDetails& details) { 492 const content::NotificationDetails& details) {
447 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 493 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
448 494
449 switch (type) { 495 switch (type) {
450 case content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME: { 496 case content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME: {
(...skipping 58 matching lines...)
509 DeleteUrls(urls_deleted_details->rows); 555 DeleteUrls(urls_deleted_details->rows);
510 break; 556 break;
511 } 557 }
512 558
513 default: 559 default:
514 NOTREACHED() << "Unexpected notification observed."; 560 NOTREACHED() << "Unexpected notification observed.";
515 break; 561 break;
516 } 562 }
517 } 563 }
518 564
565 void ResourcePrefetchPredictor::FinishedPrefetchForNavigation(
566 const NavigationID& navigation_id,
567 scoped_ptr<ResourcePrefetcher::RequestVector> requests) {
568 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
569
570 // Add the results to the results map.
571 ResourcePrefetcher::RequestVector* req = requests.release();
572 if (!results_map_.insert(std::make_pair(navigation_id, req)).second) {
573 DLOG(FATAL) << "Returning results for existing navigation.";
574 delete req;
575 }
576 }
577
519 void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() { 578 void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() {
520 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 579 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
521 DCHECK_EQ(initialization_state_, INITIALIZING); 580 DCHECK_EQ(initialization_state_, INITIALIZING);
522 581
523 // Update the data with last visit info from in memory history db. 582 // Update the data with last visit info from in memory history db.
524 HistoryService* history_service = HistoryServiceFactory::GetForProfile( 583 HistoryService* history_service = HistoryServiceFactory::GetForProfile(
525 profile_, Profile::EXPLICIT_ACCESS); 584 profile_, Profile::EXPLICIT_ACCESS);
526 DCHECK(history_service); 585 DCHECK(history_service);
527 history::URLDatabase* url_db = history_service->InMemoryDatabase(); 586 history::URLDatabase* url_db = history_service->InMemoryDatabase();
528 if (url_db) { 587 if (url_db) {
(...skipping 29 matching lines...)
558 notification_registrar_.Add(this, 617 notification_registrar_.Add(this,
559 content::NOTIFICATION_LOAD_FROM_MEMORY_CACHE, 618 content::NOTIFICATION_LOAD_FROM_MEMORY_CACHE,
560 content::NotificationService::AllSources()); 619 content::NotificationService::AllSources());
561 notification_registrar_.Add(this, 620 notification_registrar_.Add(this,
562 chrome::NOTIFICATION_HISTORY_URLS_DELETED, 621 chrome::NOTIFICATION_HISTORY_URLS_DELETED,
563 content::Source<Profile>(profile_)); 622 content::Source<Profile>(profile_));
564 623
565 // TODO(shishir): Maybe listen for notifications for navigation being 624 // TODO(shishir): Maybe listen for notifications for navigation being
566 // abandoned and cleanup the inflight_navigations_. 625 // abandoned and cleanup the inflight_navigations_.
567 626
627 // Initialize the prefetch manager only if prefetching is enabled.
628 if (prerender::IsSpeculativeResourcePrefetchingEnabled(profile_)) {
629 prefetch_manager_ = new ResourcePrefetcherManager(
630 this, config_, profile_->GetRequestContext());
631 }
632
568 initialization_state_ = INITIALIZED; 633 initialization_state_ = INITIALIZED;
569 } 634 }
570 635
571 bool ResourcePrefetchPredictor::ShouldTrackUrl(const GURL& url) { 636 bool ResourcePrefetchPredictor::ShouldTrackUrl(const GURL& url) {
572 if (url_table_cache_.find(url) != url_table_cache_.end()) 637 if (url_table_cache_.find(url) != url_table_cache_.end())
573 return true; 638 return true;
574 639
575 HistoryService* history_service = HistoryServiceFactory::GetForProfile( 640 HistoryService* history_service = HistoryServiceFactory::GetForProfile(
576 profile_, Profile::EXPLICIT_ACCESS); 641 profile_, Profile::EXPLICIT_ACCESS);
577 DCHECK(history_service); 642 DCHECK(history_service);
(...skipping 18 matching lines...)
596 661
597 if (inflight_navigations_.find(navigation_id) == 662 if (inflight_navigations_.find(navigation_id) ==
598 inflight_navigations_.end()) { 663 inflight_navigations_.end()) {
599 RecordNavigationEvent(NAVIGATION_EVENT_ONLOAD_UNTRACKED_URL); 664 RecordNavigationEvent(NAVIGATION_EVENT_ONLOAD_UNTRACKED_URL);
600 return; 665 return;
601 } 666 }
602 667
603 RecordNavigationEvent(NAVIGATION_EVENT_ONLOAD_TRACKED_URL); 668 RecordNavigationEvent(NAVIGATION_EVENT_ONLOAD_TRACKED_URL);
604 669
605 // Report any stats. 670 // Report any stats.
606 MaybeReportAccuracyStats(navigation_id); 671 if (prefetch_manager_.get()) {
672 MaybeReportAccuracyStats(navigation_id);
673 } else {
674 MaybeReportSimulatedAccuracyStats(navigation_id);
675 }
607 676
608 // Update the URL table. 677 // Update the URL table.
609 const GURL& main_frame_url = navigation_id.main_frame_url; 678 const GURL& main_frame_url = navigation_id.main_frame_url;
610 if (ShouldTrackUrl(main_frame_url)) { 679 if (ShouldTrackUrl(main_frame_url)) {
611 RecordNavigationEvent(NAVIGATION_EVENT_SHOULD_TRACK_URL); 680 RecordNavigationEvent(NAVIGATION_EVENT_SHOULD_TRACK_URL);
612 LearnUrlNavigation(main_frame_url, inflight_navigations_[navigation_id]); 681 LearnUrlNavigation(main_frame_url, inflight_navigations_[navigation_id]);
613 } else { 682 } else {
614 RecordNavigationEvent(NAVIGATION_EVENT_SHOULD_NOT_TRACK_URL); 683 RecordNavigationEvent(NAVIGATION_EVENT_SHOULD_NOT_TRACK_URL);
615 } 684 }
616 685
617 // Remove the navigation. 686 // Remove the navigation.
618 inflight_navigations_.erase(navigation_id); 687 inflight_navigations_.erase(navigation_id);
688 delete results_map_[navigation_id];
689 results_map_.erase(navigation_id);
619 } 690 }
620 691
621 void ResourcePrefetchPredictor::LearnUrlNavigation( 692 void ResourcePrefetchPredictor::LearnUrlNavigation(
622 const GURL& main_frame_url, 693 const GURL& main_frame_url,
623 const std::vector<URLRequestSummary>& new_resources) { 694 const std::vector<URLRequestSummary>& new_resources) {
624 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 695 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
625 696
626 if (url_table_cache_.find(main_frame_url) == url_table_cache_.end()) { 697 if (url_table_cache_.find(main_frame_url) == url_table_cache_.end()) {
627 if (url_table_cache_.size() >= config_.max_urls_to_track) 698 if (static_cast<int>(url_table_cache_.size()) >= config_.max_urls_to_track)
628 RemoveAnEntryFromUrlDB(); 699 RemoveAnEntryFromUrlDB();
629 700
630 url_table_cache_[main_frame_url].last_visit = base::Time::Now(); 701 url_table_cache_[main_frame_url].last_visit = base::Time::Now();
631 int new_resources_size = static_cast<int>(new_resources.size()); 702 int new_resources_size = static_cast<int>(new_resources.size());
632 std::set<GURL> resources_seen; 703 std::set<GURL> resources_seen;
633 for (int i = 0; i < new_resources_size; ++i) { 704 for (int i = 0; i < new_resources_size; ++i) {
634 if (resources_seen.find(new_resources[i].resource_url) != 705 if (resources_seen.find(new_resources[i].resource_url) !=
635 resources_seen.end()) { 706 resources_seen.end()) {
636 continue; 707 continue;
637 } 708 }
(...skipping 109 matching lines...)
747 } 818 }
748 url_table_cache_.erase(url_to_erase); 819 url_table_cache_.erase(url_to_erase);
749 820
750 std::vector<GURL> urls_to_delete(1, url_to_erase); 821 std::vector<GURL> urls_to_delete(1, url_to_erase);
751 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, 822 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
752 base::Bind(&ResourcePrefetchPredictorTables::DeleteRowsForUrls, 823 base::Bind(&ResourcePrefetchPredictorTables::DeleteRowsForUrls,
753 tables_, 824 tables_,
754 urls_to_delete)); 825 urls_to_delete));
755 } 826 }
756 827
757 void ResourcePrefetchPredictor::MaybeReportAccuracyStats( 828 void ResourcePrefetchPredictor::MaybeReportSimulatedAccuracyStats(
758 const NavigationID& navigation_id) const { 829 const NavigationID& navigation_id) const {
759 const GURL& main_frame_url = navigation_id.main_frame_url; 830 const GURL& main_frame_url = navigation_id.main_frame_url;
760 DCHECK(inflight_navigations_.find(navigation_id) != 831 DCHECK(inflight_navigations_.find(navigation_id) !=
761 inflight_navigations_.end()); 832 inflight_navigations_.end());
762 833
763 bool have_predictions_for_url = 834 bool have_predictions_for_url =
764 url_table_cache_.find(main_frame_url) != url_table_cache_.end(); 835 url_table_cache_.find(main_frame_url) != url_table_cache_.end();
765 if (have_predictions_for_url) { 836 if (have_predictions_for_url) {
766 RecordNavigationEvent(NAVIGATION_EVENT_HAVE_PREDICTIONS_FOR_URL); 837 RecordNavigationEvent(NAVIGATION_EVENT_HAVE_PREDICTIONS_FOR_URL);
767 } else { 838 } else {
(...skipping 81 matching lines...)
849 // Measure the ratio of total number of resources prefetched from network vs 920 // Measure the ratio of total number of resources prefetched from network vs
850 // the total number of resources fetched by the page from the network. 921 // the total number of resources fetched by the page from the network.
851 RPP_PREDICTED_HISTOGRAM_PERCENTAGE( 922 RPP_PREDICTED_HISTOGRAM_PERCENTAGE(
852 "PrefetchFromNetworkPercentOfTotalFromNetwork", 923 "PrefetchFromNetworkPercentOfTotalFromNetwork",
853 prefetch_network * 100.0 / total_resources_fetched_from_network); 924 prefetch_network * 100.0 / total_resources_fetched_from_network);
854 925
855 #undef RPP_PREDICTED_HISTOGRAM_PERCENTAGE 926 #undef RPP_PREDICTED_HISTOGRAM_PERCENTAGE
856 #undef RPP_PREDICTED_HISTOGRAM_COUNTS 927 #undef RPP_PREDICTED_HISTOGRAM_COUNTS
857 } 928 }
858 929
930 void ResourcePrefetchPredictor::MaybeReportAccuracyStats(
931 const NavigationID& navigation_id) {
932 NavigationMap::iterator nav_it = inflight_navigations_.find(navigation_id);
933 DCHECK(nav_it != inflight_navigations_.end());
934
935 ResultsMap::iterator results_it = results_map_.find(navigation_id);
936 bool have_prefetch_results = results_it != results_map_.end();
937 UMA_HISTOGRAM_BOOLEAN("ResourcePrefetchPredictor.HavePrefetchResults",
938 have_prefetch_results);
939 if (!have_prefetch_results)
940 return;
941
942 // Annotate the results.
943 const std::vector<URLRequestSummary>& actual = nav_it->second;
944 ResourcePrefetcher::RequestVector* prefetched = results_it->second;
945
946 std::map<GURL, bool> actual_resources;
947 for (std::vector<URLRequestSummary>::const_iterator it = actual.begin();
948 it != actual.end(); ++it) {
949 actual_resources[it->resource_url] = it->was_cached;
950 }
951
952 int prefetch_cancelled = 0, prefetch_failed = 0, prefetch_not_started = 0;
953 // 'a_' -> actual, 'p_' -> predicted.
954 int p_cache_a_cache = 0, p_cache_a_network = 0, p_cache_a_notused = 0,
955 p_network_a_cache = 0, p_network_a_network = 0, p_network_a_notused = 0;
956
957 for (ResourcePrefetcher::RequestVector::iterator it = prefetched->begin();
958 it != prefetched->end(); ++it) {
959 ResourcePrefetcher::Request* req = *it;
960
961 // Set the usage states if the resource was actually used.
962 std::map<GURL, bool>::iterator actual_it = actual_resources.find(
963 req->resource_url);
964 if (actual_it != actual_resources.end()) {
965 if (actual_it->second) {
966 req->usage_status =
967 ResourcePrefetcher::Request::USAGE_STATUS_FROM_CACHE;
968 } else {
969 req->usage_status =
970 ResourcePrefetcher::Request::USAGE_STATUS_FROM_NETWORK;
971 }
972 }
973
974 switch (req->prefetch_status) {
975
976 // TODO(shishir): Add histogram for each cancellation reason.
977 case ResourcePrefetcher::Request::PREFETCH_STATUS_REDIRECTED:
978 case ResourcePrefetcher::Request::PREFETCH_STATUS_AUTH_REQUIRED:
979 case ResourcePrefetcher::Request::PREFETCH_STATUS_CERT_REQUIRED:
980 case ResourcePrefetcher::Request::PREFETCH_STATUS_CERT_ERROR:
981 case ResourcePrefetcher::Request::PREFETCH_STATUS_CANCELLED:
982 ++prefetch_cancelled;
983 break;
984
985 case ResourcePrefetcher::Request::PREFETCH_STATUS_FAILED:
986 ++prefetch_failed;
987 break;
988
989 case ResourcePrefetcher::Request::PREFETCH_STATUS_FROM_CACHE:
990 if (req->usage_status ==
991 ResourcePrefetcher::Request::USAGE_STATUS_FROM_CACHE)
992 ++p_cache_a_cache;
993 else if (req->usage_status ==
994 ResourcePrefetcher::Request::USAGE_STATUS_FROM_NETWORK)
995 ++p_cache_a_network;
996 else
997 ++p_cache_a_notused;
998 break;
999
1000 case ResourcePrefetcher::Request::PREFETCH_STATUS_FROM_NETWORK:
1001 if (req->usage_status ==
1002 ResourcePrefetcher::Request::USAGE_STATUS_FROM_CACHE)
1003 ++p_network_a_cache;
1004 else if (req->usage_status ==
1005 ResourcePrefetcher::Request::USAGE_STATUS_FROM_NETWORK)
1006 ++p_network_a_network;
1007 else
1008 ++p_network_a_notused;
1009 break;
1010
1011 case ResourcePrefetcher::Request::PREFETCH_STATUS_NOT_STARTED:
1012 ++prefetch_not_started;
1013 break;
1014
1015 case ResourcePrefetcher::Request::PREFETCH_STATUS_STARTED:
1016 DLOG(FATAL) << "Invalid prefetch status";
1017 break;
1018 }
1019 }
1020
1021 int total_prefetched = p_cache_a_cache + p_cache_a_network + p_cache_a_notused
1022 + p_network_a_cache + p_network_a_network + p_network_a_notused;
1023
1024 UMA_HISTOGRAM_PERCENTAGE(
1025 "ResourcePrefetchPredictor.PrefetchCancelled",
1026 prefetch_cancelled * 100.0 / total_prefetched);
1027 UMA_HISTOGRAM_PERCENTAGE(
1028 "ResourcePrefetchPredictor.PrefetchFailed",
1029 prefetch_failed * 100.0 / total_prefetched);
1030 UMA_HISTOGRAM_PERCENTAGE(
1031 "ResourcePrefetchPredictor.PrefetchFromCacheUsedFromCache",
1032 p_cache_a_cache * 100.0 / total_prefetched);
1033 UMA_HISTOGRAM_PERCENTAGE(
1034 "ResourcePrefetchPredictor.PrefetchFromCacheUsedFromNetwork",
1035 p_cache_a_network * 100.0 / total_prefetched);
1036 UMA_HISTOGRAM_PERCENTAGE(
1037 "ResourcePrefetchPredictor.PrefetchFromCacheNotUsed",
1038 p_cache_a_notused * 100.0 / total_prefetched);
1039 UMA_HISTOGRAM_PERCENTAGE(
1040 "ResourcePrefetchPredictor.PrefetchFromNetworkUsedFromCache",
1041 p_network_a_cache * 100.0 / total_prefetched);
1042 UMA_HISTOGRAM_PERCENTAGE(
1043 "ResourcePrefetchPredictor.PrefetchFromNetworkUsedFromNetwork",
1044 p_network_a_network * 100.0 / total_prefetched);
1045 UMA_HISTOGRAM_PERCENTAGE(
1046 "ResourcePrefetchPredictor.PrefetchFromNetworkNotUsed",
1047 p_network_a_notused * 100.0 / total_prefetched);
1048
1049 UMA_HISTOGRAM_PERCENTAGE(
1050 "ResourcePrefetchPredictor.PrefetchNotStarted",
1051 prefetch_not_started * 100.0 / (prefetch_not_started + total_prefetched));
1052 }
1053
859 void ResourcePrefetchPredictor::DeleteAllUrls() { 1054 void ResourcePrefetchPredictor::DeleteAllUrls() {
860 inflight_navigations_.clear(); 1055 inflight_navigations_.clear();
861 url_table_cache_.clear(); 1056 url_table_cache_.clear();
862 1057
863 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, 1058 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
864 base::Bind(&ResourcePrefetchPredictorTables::DeleteAllRows, tables_)); 1059 base::Bind(&ResourcePrefetchPredictorTables::DeleteAllRows, tables_));
865 } 1060 }
866 1061
867 void ResourcePrefetchPredictor::DeleteUrls(const history::URLRows& urls) { 1062 void ResourcePrefetchPredictor::DeleteUrls(const history::URLRows& urls) {
868 std::vector<GURL> urls_to_delete; 1063 std::vector<GURL> urls_to_delete;
(...skipping 14 matching lines...)
883 tables_, 1078 tables_,
884 urls_to_delete)); 1079 urls_to_delete));
885 } 1080 }
886 1081
887 void ResourcePrefetchPredictor::SetTablesForTesting( 1082 void ResourcePrefetchPredictor::SetTablesForTesting(
888 scoped_refptr<ResourcePrefetchPredictorTables> tables) { 1083 scoped_refptr<ResourcePrefetchPredictorTables> tables) {
889 tables_ = tables; 1084 tables_ = tables;
890 } 1085 }
891 1086
892 } // namespace predictors 1087 } // namespace predictors
OLDNEW

Powered by Google App Engine