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

Side by Side Diff: chrome/browser/predictors/resource_prefetch_predictor.cc

Issue 2321343002: Redirect handling in resource prefetch predictor (Closed)
Patch Set: Redirects database schema changed Created 4 years, 3 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 65
66 namespace predictors { 66 namespace predictors {
67 67
68 //////////////////////////////////////////////////////////////////////////////// 68 ////////////////////////////////////////////////////////////////////////////////
69 // History lookup task. 69 // History lookup task.
70 70
71 // Used to fetch the visit count for a URL from the History database. 71 // Used to fetch the visit count for a URL from the History database.
72 class GetUrlVisitCountTask : public history::HistoryDBTask { 72 class GetUrlVisitCountTask : public history::HistoryDBTask {
73 public: 73 public:
74 typedef ResourcePrefetchPredictor::URLRequestSummary URLRequestSummary; 74 typedef ResourcePrefetchPredictor::URLRequestSummary URLRequestSummary;
75 typedef base::Callback<void( 75 typedef ResourcePrefetchPredictor::Navigation Navigation;
76 size_t, // Visit count. 76 typedef base::Callback<void(size_t, // Visit count.
77 const NavigationID&, 77 const NavigationID&,
78 const std::vector<URLRequestSummary>&)> VisitInfoCallback; 78 const Navigation&)>
79 VisitInfoCallback;
79 80
80 GetUrlVisitCountTask( 81 GetUrlVisitCountTask(const NavigationID& navigation_id,
81 const NavigationID& navigation_id, 82 std::unique_ptr<Navigation> navigation,
82 std::vector<URLRequestSummary>* requests, 83 VisitInfoCallback callback)
83 VisitInfoCallback callback)
84 : visit_count_(0), 84 : visit_count_(0),
85 navigation_id_(navigation_id), 85 navigation_id_(navigation_id),
86 requests_(requests), 86 navigation_(std::move(navigation)),
87 callback_(callback) { 87 callback_(callback) {
88 DCHECK(requests_.get()); 88 DCHECK(navigation_.get());
89 } 89 }
90 90
91 bool RunOnDBThread(history::HistoryBackend* backend, 91 bool RunOnDBThread(history::HistoryBackend* backend,
92 history::HistoryDatabase* db) override { 92 history::HistoryDatabase* db) override {
93 history::URLRow url_row; 93 history::URLRow url_row;
94 if (db->GetRowForURL(navigation_id_.main_frame_url, &url_row)) 94 if (db->GetRowForURL(navigation_id_.main_frame_url, &url_row))
95 visit_count_ = url_row.visit_count(); 95 visit_count_ = url_row.visit_count();
96 return true; 96 return true;
97 } 97 }
98 98
99 void DoneRunOnMainThread() override { 99 void DoneRunOnMainThread() override {
100 callback_.Run(visit_count_, navigation_id_, *requests_); 100 callback_.Run(visit_count_, navigation_id_, *navigation_);
101 } 101 }
102 102
103 private: 103 private:
104 ~GetUrlVisitCountTask() override {} 104 ~GetUrlVisitCountTask() override {}
105 105
106 int visit_count_; 106 int visit_count_;
107 NavigationID navigation_id_; 107 NavigationID navigation_id_;
108 std::unique_ptr<std::vector<URLRequestSummary>> requests_; 108 std::unique_ptr<Navigation> navigation_;
109 VisitInfoCallback callback_; 109 VisitInfoCallback callback_;
110 110
111 DISALLOW_COPY_AND_ASSIGN(GetUrlVisitCountTask); 111 DISALLOW_COPY_AND_ASSIGN(GetUrlVisitCountTask);
112 }; 112 };
113 113
114 //////////////////////////////////////////////////////////////////////////////// 114 ////////////////////////////////////////////////////////////////////////////////
115 // ResourcePrefetchPredictor static functions. 115 // ResourcePrefetchPredictor static functions.
116 116
117 // static 117 // static
118 bool ResourcePrefetchPredictor::ShouldRecordRequest( 118 bool ResourcePrefetchPredictor::ShouldRecordRequest(
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 priority(other.priority), 274 priority(other.priority),
275 mime_type(other.mime_type), 275 mime_type(other.mime_type),
276 was_cached(other.was_cached), 276 was_cached(other.was_cached),
277 redirect_url(other.redirect_url), 277 redirect_url(other.redirect_url),
278 has_validators(other.has_validators), 278 has_validators(other.has_validators),
279 always_revalidate(other.always_revalidate) {} 279 always_revalidate(other.always_revalidate) {}
280 280
281 ResourcePrefetchPredictor::URLRequestSummary::~URLRequestSummary() { 281 ResourcePrefetchPredictor::URLRequestSummary::~URLRequestSummary() {
282 } 282 }
283 283
284 ResourcePrefetchPredictor::Navigation::Navigation(const GURL& i_initial_url)
285 : initial_url(i_initial_url) {}
286
287 ResourcePrefetchPredictor::Navigation::~Navigation() {}
288
284 // static 289 // static
285 bool ResourcePrefetchPredictor::URLRequestSummary::SummarizeResponse( 290 bool ResourcePrefetchPredictor::URLRequestSummary::SummarizeResponse(
286 const net::URLRequest& request, 291 const net::URLRequest& request,
287 URLRequestSummary* summary) { 292 URLRequestSummary* summary) {
288 const content::ResourceRequestInfo* info = 293 const content::ResourceRequestInfo* info =
289 content::ResourceRequestInfo::ForRequest(&request); 294 content::ResourceRequestInfo::ForRequest(&request);
290 if (!info) 295 if (!info)
291 return false; 296 return false;
292 297
293 int render_process_id, render_frame_id; 298 int render_process_id, render_frame_id;
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 const URLRequestSummary& request) { 435 const URLRequestSummary& request) {
431 DCHECK_CURRENTLY_ON(BrowserThread::UI); 436 DCHECK_CURRENTLY_ON(BrowserThread::UI);
432 DCHECK_EQ(INITIALIZED, initialization_state_); 437 DCHECK_EQ(INITIALIZED, initialization_state_);
433 438
434 StartPrefetching(request.navigation_id); 439 StartPrefetching(request.navigation_id);
435 440
436 // Cleanup older navigations. 441 // Cleanup older navigations.
437 CleanupAbandonedNavigations(request.navigation_id); 442 CleanupAbandonedNavigations(request.navigation_id);
438 443
439 // New empty navigation entry. 444 // New empty navigation entry.
440 inflight_navigations_.insert(std::make_pair( 445 const GURL& initial_url = request.navigation_id.main_frame_url;
441 request.navigation_id, 446 inflight_navigations_.insert(
442 make_linked_ptr(new std::vector<URLRequestSummary>()))); 447 std::make_pair(request.navigation_id,
448 std::unique_ptr<Navigation>(new Navigation(initial_url))));
Benoit L 2016/09/19 13:53:47 nit: MakeUnique is preferred to this. (it's like C
443 } 449 }
444 450
445 void ResourcePrefetchPredictor::OnMainFrameResponse( 451 void ResourcePrefetchPredictor::OnMainFrameResponse(
446 const URLRequestSummary& response) { 452 const URLRequestSummary& response) {
447 DCHECK_CURRENTLY_ON(BrowserThread::UI); 453 DCHECK_CURRENTLY_ON(BrowserThread::UI);
448 if (initialization_state_ != INITIALIZED) 454 if (initialization_state_ != INITIALIZED)
449 return; 455 return;
450 456
451 StopPrefetching(response.navigation_id); 457 StopPrefetching(response.navigation_id);
452 } 458 }
453 459
454 void ResourcePrefetchPredictor::OnMainFrameRedirect( 460 void ResourcePrefetchPredictor::OnMainFrameRedirect(
455 const URLRequestSummary& response) { 461 const URLRequestSummary& response) {
456 DCHECK_CURRENTLY_ON(BrowserThread::UI); 462 DCHECK_CURRENTLY_ON(BrowserThread::UI);
457 463
458 // TODO(shishir): There are significant gains to be had here if we can use the 464 // TODO(shishir): There are significant gains to be had here if we can use the
459 // start URL in a redirect chain as the key to start prefetching. We can save 465 // start URL in a redirect chain as the key to start prefetching. We can save
460 // of redirect times considerably assuming that the redirect chains do not 466 // of redirect times considerably assuming that the redirect chains do not
461 // change. 467 // change.
462 468
463 // Stop any inflight prefetching. Remove the older navigation. 469 // Stop any inflight prefetching. Remove the older navigation.
464 StopPrefetching(response.navigation_id); 470 StopPrefetching(response.navigation_id);
465 inflight_navigations_.erase(response.navigation_id); 471
472 std::unique_ptr<Navigation> navigation;
473 NavigationMap::iterator nav_it =
474 inflight_navigations_.find(response.navigation_id);
475 if (nav_it != inflight_navigations_.end()) {
476 navigation.reset(nav_it->second.release());
477 inflight_navigations_.erase(nav_it);
478 }
466 479
467 // A redirect will not lead to another OnMainFrameRequest call, so record the 480 // A redirect will not lead to another OnMainFrameRequest call, so record the
468 // redirect url as a new navigation. 481 // redirect url as a new navigation.
469 482
470 // The redirect url may be empty if the URL was invalid. 483 // The redirect url may be empty if the URL was invalid.
471 if (response.redirect_url.is_empty()) 484 if (response.redirect_url.is_empty())
472 return; 485 return;
473 486
487 if (!navigation) {
488 navigation.reset(new Navigation(response.navigation_id.main_frame_url));
Benoit L 2016/09/19 13:53:47 nit: no braces when it fits on a single line (per
489 }
490
474 NavigationID navigation_id(response.navigation_id); 491 NavigationID navigation_id(response.navigation_id);
475 navigation_id.main_frame_url = response.redirect_url; 492 navigation_id.main_frame_url = response.redirect_url;
476 inflight_navigations_.insert(std::make_pair( 493 inflight_navigations_.insert(
477 navigation_id, 494 std::make_pair(navigation_id, std::move(navigation)));
478 make_linked_ptr(new std::vector<URLRequestSummary>())));
479 } 495 }
480 496
481 void ResourcePrefetchPredictor::OnSubresourceResponse( 497 void ResourcePrefetchPredictor::OnSubresourceResponse(
482 const URLRequestSummary& response) { 498 const URLRequestSummary& response) {
483 DCHECK_CURRENTLY_ON(BrowserThread::UI); 499 DCHECK_CURRENTLY_ON(BrowserThread::UI);
484 500
485 NavigationMap::const_iterator nav_it = 501 NavigationMap::const_iterator nav_it =
486 inflight_navigations_.find(response.navigation_id); 502 inflight_navigations_.find(response.navigation_id);
487 if (nav_it == inflight_navigations_.end()) { 503 if (nav_it == inflight_navigations_.end()) {
488 return; 504 return;
489 } 505 }
490 506
491 nav_it->second->push_back(response); 507 nav_it->second->requests.push_back(response);
492 } 508 }
493 509
494 void ResourcePrefetchPredictor::OnNavigationComplete( 510 void ResourcePrefetchPredictor::OnNavigationComplete(
495 const NavigationID& nav_id_without_timing_info) { 511 const NavigationID& nav_id_without_timing_info) {
496 DCHECK_CURRENTLY_ON(BrowserThread::UI); 512 DCHECK_CURRENTLY_ON(BrowserThread::UI);
497 513
498 NavigationMap::iterator nav_it = 514 NavigationMap::iterator nav_it =
499 inflight_navigations_.find(nav_id_without_timing_info); 515 inflight_navigations_.find(nav_id_without_timing_info);
500 if (nav_it == inflight_navigations_.end()) 516 if (nav_it == inflight_navigations_.end())
501 return; 517 return;
502 518
503 const NavigationID navigation_id(nav_it->first); 519 const NavigationID navigation_id(nav_it->first);
504 520
505 // Remove the navigation from the inflight navigations. 521 // Remove the navigation from the inflight navigations.
506 std::vector<URLRequestSummary>* requests = (nav_it->second).release(); 522 std::unique_ptr<Navigation> navigation = std::move(nav_it->second);
507 inflight_navigations_.erase(nav_it); 523 inflight_navigations_.erase(nav_it);
508 524
509 // Kick off history lookup to determine if we should record the URL. 525 // Kick off history lookup to determine if we should record the URL.
510 history::HistoryService* history_service = 526 history::HistoryService* history_service =
511 HistoryServiceFactory::GetForProfile(profile_, 527 HistoryServiceFactory::GetForProfile(profile_,
512 ServiceAccessType::EXPLICIT_ACCESS); 528 ServiceAccessType::EXPLICIT_ACCESS);
513 DCHECK(history_service); 529 DCHECK(history_service);
514 history_service->ScheduleDBTask( 530 history_service->ScheduleDBTask(
515 std::unique_ptr<history::HistoryDBTask>(new GetUrlVisitCountTask( 531 std::unique_ptr<history::HistoryDBTask>(new GetUrlVisitCountTask(
516 navigation_id, requests, 532 navigation_id, std::move(navigation),
517 base::Bind(&ResourcePrefetchPredictor::OnVisitCountLookup, 533 base::Bind(&ResourcePrefetchPredictor::OnVisitCountLookup,
518 AsWeakPtr()))), 534 AsWeakPtr()))),
519 &history_lookup_consumer_); 535 &history_lookup_consumer_);
520 } 536 }
521 537
522 bool ResourcePrefetchPredictor::GetPrefetchData( 538 bool ResourcePrefetchPredictor::GetPrefetchData(
523 const NavigationID& navigation_id, 539 const NavigationID& navigation_id,
524 ResourcePrefetcher::RequestVector* prefetch_requests, 540 ResourcePrefetcher::RequestVector* prefetch_requests,
525 PrefetchKeyType* key_type) { 541 PrefetchKeyType* key_type) {
526 DCHECK(prefetch_requests); 542 DCHECK(prefetch_requests);
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 625
610 void ResourcePrefetchPredictor::StartInitialization() { 626 void ResourcePrefetchPredictor::StartInitialization() {
611 DCHECK_CURRENTLY_ON(BrowserThread::UI); 627 DCHECK_CURRENTLY_ON(BrowserThread::UI);
612 628
613 DCHECK_EQ(NOT_INITIALIZED, initialization_state_); 629 DCHECK_EQ(NOT_INITIALIZED, initialization_state_);
614 initialization_state_ = INITIALIZING; 630 initialization_state_ = INITIALIZING;
615 631
616 // Create local caches using the database as loaded. 632 // Create local caches using the database as loaded.
617 std::unique_ptr<PrefetchDataMap> url_data_map(new PrefetchDataMap()); 633 std::unique_ptr<PrefetchDataMap> url_data_map(new PrefetchDataMap());
618 std::unique_ptr<PrefetchDataMap> host_data_map(new PrefetchDataMap()); 634 std::unique_ptr<PrefetchDataMap> host_data_map(new PrefetchDataMap());
635 std::unique_ptr<RedirectDataMap> url_redirect_data_map(new RedirectDataMap());
636 std::unique_ptr<RedirectDataMap> host_redirect_data_map(
637 new RedirectDataMap());
619 PrefetchDataMap* url_data_ptr = url_data_map.get(); 638 PrefetchDataMap* url_data_ptr = url_data_map.get();
620 PrefetchDataMap* host_data_ptr = host_data_map.get(); 639 PrefetchDataMap* host_data_ptr = host_data_map.get();
640 RedirectDataMap* url_redirect_data_ptr = url_redirect_data_map.get();
641 RedirectDataMap* host_redirect_data_ptr = host_redirect_data_map.get();
621 642
622 BrowserThread::PostTaskAndReply( 643 BrowserThread::PostTaskAndReply(
623 BrowserThread::DB, FROM_HERE, 644 BrowserThread::DB, FROM_HERE,
624 base::Bind(&ResourcePrefetchPredictorTables::GetAllData, 645 base::Bind(&ResourcePrefetchPredictorTables::GetAllData, tables_,
Benoit L 2016/09/19 13:53:47 nit: Why not just url_data.get() here (and so on f
alexilin 2016/09/19 16:49:25 I'm still not very confident with this "passing po
625 tables_, url_data_ptr, host_data_ptr), 646 url_data_ptr, host_data_ptr, url_redirect_data_ptr,
647 host_redirect_data_ptr),
626 base::Bind(&ResourcePrefetchPredictor::CreateCaches, AsWeakPtr(), 648 base::Bind(&ResourcePrefetchPredictor::CreateCaches, AsWeakPtr(),
627 base::Passed(&url_data_map), base::Passed(&host_data_map))); 649 base::Passed(&url_data_map), base::Passed(&host_data_map),
650 base::Passed(&url_redirect_data_map),
651 base::Passed(&host_redirect_data_map)));
628 } 652 }
629 653
630 void ResourcePrefetchPredictor::CreateCaches( 654 void ResourcePrefetchPredictor::CreateCaches(
631 std::unique_ptr<PrefetchDataMap> url_data_map, 655 std::unique_ptr<PrefetchDataMap> url_data_map,
632 std::unique_ptr<PrefetchDataMap> host_data_map) { 656 std::unique_ptr<PrefetchDataMap> host_data_map,
657 std::unique_ptr<RedirectDataMap> url_redirect_data_map,
658 std::unique_ptr<RedirectDataMap> host_redirect_data_map) {
633 DCHECK_CURRENTLY_ON(BrowserThread::UI); 659 DCHECK_CURRENTLY_ON(BrowserThread::UI);
634 660
635 DCHECK_EQ(INITIALIZING, initialization_state_); 661 DCHECK_EQ(INITIALIZING, initialization_state_);
636 DCHECK(!url_table_cache_); 662 DCHECK(!url_table_cache_);
637 DCHECK(!host_table_cache_); 663 DCHECK(!host_table_cache_);
664 DCHECK(!url_redirect_table_cache_);
665 DCHECK(!host_redirect_table_cache_);
638 DCHECK(inflight_navigations_.empty()); 666 DCHECK(inflight_navigations_.empty());
639 667
640 url_table_cache_.reset(url_data_map.release()); 668 url_table_cache_.reset(url_data_map.release());
641 host_table_cache_.reset(host_data_map.release()); 669 host_table_cache_.reset(host_data_map.release());
670 url_redirect_table_cache_.reset(url_redirect_data_map.release());
671 host_redirect_table_cache_.reset(host_redirect_data_map.release());
642 672
643 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.UrlTableMainFrameUrlCount", 673 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.UrlTableMainFrameUrlCount",
644 url_table_cache_->size()); 674 url_table_cache_->size());
645 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HostTableHostCount", 675 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HostTableHostCount",
646 host_table_cache_->size()); 676 host_table_cache_->size());
647 677
648 ConnectToHistoryService(); 678 ConnectToHistoryService();
649 } 679 }
650 680
651 void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() { 681 void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
708 } 738 }
709 739
710 const std::string& host = it.url().host(); 740 const std::string& host = it.url().host();
711 if (host_table_cache_->find(host) != host_table_cache_->end()) { 741 if (host_table_cache_->find(host) != host_table_cache_->end()) {
712 hosts_to_delete.push_back(host); 742 hosts_to_delete.push_back(host);
713 host_table_cache_->erase(host); 743 host_table_cache_->erase(host);
714 } 744 }
715 } 745 }
716 746
717 if (!urls_to_delete.empty() || !hosts_to_delete.empty()) { 747 if (!urls_to_delete.empty() || !hosts_to_delete.empty()) {
718 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, 748 BrowserThread::PostTask(
719 base::Bind(&ResourcePrefetchPredictorTables::DeleteData, 749 BrowserThread::DB, FROM_HERE,
720 tables_, 750 base::Bind(&ResourcePrefetchPredictorTables::DeleteResourceData,
721 urls_to_delete, 751 tables_, urls_to_delete, hosts_to_delete));
722 hosts_to_delete));
723 } 752 }
724 } 753 }
725 754
726 void ResourcePrefetchPredictor::RemoveOldestEntryInPrefetchDataMap( 755 void ResourcePrefetchPredictor::RemoveOldestEntryInPrefetchDataMap(
727 PrefetchKeyType key_type, 756 PrefetchKeyType key_type,
728 PrefetchDataMap* data_map) { 757 PrefetchDataMap* data_map) {
729 if (data_map->empty()) 758 if (data_map->empty())
730 return; 759 return;
731 760
732 base::Time oldest_time; 761 base::Time oldest_time;
733 std::string key_to_delete; 762 std::string key_to_delete;
734 for (PrefetchDataMap::iterator it = data_map->begin(); 763 for (PrefetchDataMap::iterator it = data_map->begin();
735 it != data_map->end(); ++it) { 764 it != data_map->end(); ++it) {
736 if (key_to_delete.empty() || it->second.last_visit < oldest_time) { 765 if (key_to_delete.empty() || it->second.last_visit < oldest_time) {
737 key_to_delete = it->first; 766 key_to_delete = it->first;
738 oldest_time = it->second.last_visit; 767 oldest_time = it->second.last_visit;
739 } 768 }
740 } 769 }
741 770
742 data_map->erase(key_to_delete); 771 data_map->erase(key_to_delete);
743 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, 772 BrowserThread::PostTask(
744 base::Bind(&ResourcePrefetchPredictorTables::DeleteSingleDataPoint, 773 BrowserThread::DB, FROM_HERE,
745 tables_, 774 base::Bind(
746 key_to_delete, 775 &ResourcePrefetchPredictorTables::DeleteSingleResourceDataPoint,
747 key_type)); 776 tables_, key_to_delete, key_type));
777 }
778
779 void ResourcePrefetchPredictor::RemoveOldestEntryInRedirectDataMap(
780 PrefetchKeyType key_type,
781 RedirectDataMap* data_map) {
782 if (data_map->empty())
783 return;
784
785 base::Time oldest_time;
786 std::string key_to_delete;
787 for (RedirectDataMap::iterator it = data_map->begin(); it != data_map->end();
Benoit L 2016/09/19 13:53:47 nit: Can you use a range for loop here?
alexilin 2016/09/19 16:49:25 Of course!
788 ++it) {
789 if (key_to_delete.empty() || it->second.last_visit < oldest_time) {
790 key_to_delete = it->first;
791 oldest_time = it->second.last_visit;
792 }
793 }
794
795 data_map->erase(key_to_delete);
796 BrowserThread::PostTask(
797 BrowserThread::DB, FROM_HERE,
798 base::Bind(
799 &ResourcePrefetchPredictorTables::DeleteSingleRedirectDataPoint,
800 tables_, key_to_delete, key_type));
748 } 801 }
749 802
750 void ResourcePrefetchPredictor::OnVisitCountLookup( 803 void ResourcePrefetchPredictor::OnVisitCountLookup(
751 size_t visit_count, 804 size_t visit_count,
752 const NavigationID& navigation_id, 805 const NavigationID& navigation_id,
753 const std::vector<URLRequestSummary>& requests) { 806 const Navigation& navigation) {
754 DCHECK_CURRENTLY_ON(BrowserThread::UI); 807 DCHECK_CURRENTLY_ON(BrowserThread::UI);
755 808
756 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HistoryVisitCountForUrl", 809 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HistoryVisitCountForUrl",
757 visit_count); 810 visit_count);
758 811
812 // TODO(alexilin) make only one request to DB thread
813
759 // URL level data - merge only if we are already saving the data, or we it 814 // URL level data - merge only if we are already saving the data, or we it
760 // meets the cutoff requirement. 815 // meets the cutoff requirement.
761 const std::string url_spec = navigation_id.main_frame_url.spec(); 816 const std::string url_spec = navigation_id.main_frame_url.spec();
762 bool already_tracking = url_table_cache_->find(url_spec) != 817 bool already_tracking = url_table_cache_->find(url_spec) !=
763 url_table_cache_->end(); 818 url_table_cache_->end();
764 bool should_track_url = already_tracking || 819 bool should_track_url = already_tracking ||
765 (visit_count >= config_.min_url_visit_count); 820 (visit_count >= config_.min_url_visit_count);
766 821
767 if (should_track_url && config_.IsURLLearningEnabled()) { 822 if (should_track_url && config_.IsURLLearningEnabled()) {
768 LearnNavigation(url_spec, PREFETCH_KEY_TYPE_URL, requests, 823 LearnNavigation(url_spec, PREFETCH_KEY_TYPE_URL, navigation.requests,
769 config_.max_urls_to_track, url_table_cache_.get()); 824 config_.max_urls_to_track, url_table_cache_.get());
825
826 const std::string initial_url_spec = navigation.initial_url.spec();
827 if (url_spec != initial_url_spec) {
828 LearnRedirect(initial_url_spec, PREFETCH_KEY_TYPE_URL, url_spec,
829 config_.max_urls_to_track, url_redirect_table_cache_.get());
830 }
770 } 831 }
771 832
772 // Host level data - no cutoff, always learn the navigation if enabled. 833 // Host level data - no cutoff, always learn the navigation if enabled.
773 if (config_.IsHostLearningEnabled()) { 834 if (config_.IsHostLearningEnabled()) {
774 LearnNavigation(navigation_id.main_frame_url.host(), 835 const std::string host = navigation_id.main_frame_url.host();
775 PREFETCH_KEY_TYPE_HOST, 836 LearnNavigation(host, PREFETCH_KEY_TYPE_HOST, navigation.requests,
776 requests, 837 config_.max_hosts_to_track, host_table_cache_.get());
838
839 const std::string initial_host = navigation.initial_url.host();
840 if (host != initial_host) {
841 LearnRedirect(initial_host, PREFETCH_KEY_TYPE_HOST, host,
777 config_.max_hosts_to_track, 842 config_.max_hosts_to_track,
778 host_table_cache_.get()); 843 host_redirect_table_cache_.get());
844 }
779 } 845 }
780 846
781 // Remove the navigation from the results map. 847 // Remove the navigation from the results map.
782 results_map_.erase(navigation_id); 848 results_map_.erase(navigation_id);
783 } 849 }
784 850
785 void ResourcePrefetchPredictor::LearnNavigation( 851 void ResourcePrefetchPredictor::LearnNavigation(
786 const std::string& key, 852 const std::string& key,
787 PrefetchKeyType key_type, 853 PrefetchKeyType key_type,
788 const std::vector<URLRequestSummary>& new_resources, 854 const std::vector<URLRequestSummary>& new_resources,
(...skipping 27 matching lines...) Expand all
816 row_to_add.resource_type = new_resources[i].resource_type; 882 row_to_add.resource_type = new_resources[i].resource_type;
817 row_to_add.number_of_hits = 1; 883 row_to_add.number_of_hits = 1;
818 row_to_add.average_position = i + 1; 884 row_to_add.average_position = i + 1;
819 row_to_add.priority = new_resources[i].priority; 885 row_to_add.priority = new_resources[i].priority;
820 row_to_add.has_validators = new_resources[i].has_validators; 886 row_to_add.has_validators = new_resources[i].has_validators;
821 row_to_add.always_revalidate = new_resources[i].always_revalidate; 887 row_to_add.always_revalidate = new_resources[i].always_revalidate;
822 cache_entry->second.resources.push_back(row_to_add); 888 cache_entry->second.resources.push_back(row_to_add);
823 resources_seen.insert(new_resources[i].resource_url); 889 resources_seen.insert(new_resources[i].resource_url);
824 } 890 }
825 } else { 891 } else {
826 ResourceRows& old_resources = cache_entry->second.resources; 892 std::vector<ResourceRow>& old_resources = cache_entry->second.resources;
827 cache_entry->second.last_visit = base::Time::Now(); 893 cache_entry->second.last_visit = base::Time::Now();
828 894
829 // Build indices over the data. 895 // Build indices over the data.
830 std::map<GURL, int> new_index, old_index; 896 std::map<GURL, int> new_index, old_index;
831 int new_resources_size = static_cast<int>(new_resources.size()); 897 int new_resources_size = static_cast<int>(new_resources.size());
832 for (int i = 0; i < new_resources_size; ++i) { 898 for (int i = 0; i < new_resources_size; ++i) {
833 const URLRequestSummary& summary = new_resources[i]; 899 const URLRequestSummary& summary = new_resources[i];
834 // Take the first occurence of every url. 900 // Take the first occurence of every url.
835 if (new_index.find(summary.resource_url) == new_index.end()) 901 if (new_index.find(summary.resource_url) == new_index.end())
836 new_index[summary.resource_url] = i; 902 new_index[summary.resource_url] = i;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 row_to_add.has_validators = new_resources[i].has_validators; 949 row_to_add.has_validators = new_resources[i].has_validators;
884 row_to_add.always_revalidate = new_resources[i].always_revalidate; 950 row_to_add.always_revalidate = new_resources[i].always_revalidate;
885 old_resources.push_back(row_to_add); 951 old_resources.push_back(row_to_add);
886 952
887 // To ensure we dont add the same url twice. 953 // To ensure we dont add the same url twice.
888 old_index[summary.resource_url] = 0; 954 old_index[summary.resource_url] = 0;
889 } 955 }
890 } 956 }
891 957
892 // Trim and sort the resources after the update. 958 // Trim and sort the resources after the update.
893 ResourceRows& resources = cache_entry->second.resources; 959 std::vector<ResourceRow>& resources = cache_entry->second.resources;
894 for (ResourceRows::iterator it = resources.begin(); 960 for (std::vector<ResourceRow>::iterator it = resources.begin();
Benoit L 2016/09/19 13:53:47 tiny nit: this is one of the trivial cases where a
895 it != resources.end();) { 961 it != resources.end();) {
896 it->UpdateScore(); 962 it->UpdateScore();
897 if (it->consecutive_misses >= config_.max_consecutive_misses) 963 if (it->consecutive_misses >= config_.max_consecutive_misses)
898 it = resources.erase(it); 964 it = resources.erase(it);
899 else 965 else
900 ++it; 966 ++it;
901 } 967 }
902 ResourcePrefetchPredictorTables::SortResourceRows(&resources); 968 ResourcePrefetchPredictorTables::SortResourceRows(&resources);
903 if (resources.size() > config_.max_resources_per_entry) 969 if (resources.size() > config_.max_resources_per_entry)
904 resources.resize(config_.max_resources_per_entry); 970 resources.resize(config_.max_resources_per_entry);
905 971
906 // If the row has no resources, remove it from the cache and delete the 972 // If the row has no resources, remove it from the cache and delete the
907 // entry in the database. Else update the database. 973 // entry in the database. Else update the database.
908 if (resources.empty()) { 974 if (resources.empty()) {
909 data_map->erase(key); 975 data_map->erase(key);
910 BrowserThread::PostTask( 976 BrowserThread::PostTask(
911 BrowserThread::DB, FROM_HERE, 977 BrowserThread::DB, FROM_HERE,
912 base::Bind(&ResourcePrefetchPredictorTables::DeleteSingleDataPoint, 978 base::Bind(
913 tables_, 979 &ResourcePrefetchPredictorTables::DeleteSingleResourceDataPoint,
914 key, 980 tables_, key, key_type));
915 key_type));
916 } else { 981 } else {
917 bool is_host = key_type == PREFETCH_KEY_TYPE_HOST; 982 bool is_host = key_type == PREFETCH_KEY_TYPE_HOST;
918 PrefetchData empty_data( 983 PrefetchData empty_data(
919 !is_host ? PREFETCH_KEY_TYPE_HOST : PREFETCH_KEY_TYPE_URL, 984 !is_host ? PREFETCH_KEY_TYPE_HOST : PREFETCH_KEY_TYPE_URL,
920 std::string()); 985 std::string());
986 RedirectData empty_url_redirect_data(PREFETCH_KEY_TYPE_URL, std::string());
987 RedirectData empty_host_redirect_data(PREFETCH_KEY_TYPE_HOST,
988 std::string());
921 const PrefetchData& host_data = is_host ? cache_entry->second : empty_data; 989 const PrefetchData& host_data = is_host ? cache_entry->second : empty_data;
922 const PrefetchData& url_data = is_host ? empty_data : cache_entry->second; 990 const PrefetchData& url_data = is_host ? empty_data : cache_entry->second;
923 BrowserThread::PostTask( 991 BrowserThread::PostTask(
924 BrowserThread::DB, FROM_HERE, 992 BrowserThread::DB, FROM_HERE,
925 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, 993 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, tables_,
926 tables_, 994 url_data, host_data, empty_url_redirect_data,
927 url_data, 995 empty_host_redirect_data));
928 host_data));
929 } 996 }
930 } 997 }
931 998
999 void ResourcePrefetchPredictor::LearnRedirect(const std::string& key,
1000 PrefetchKeyType key_type,
1001 const std::string& final_redirect,
1002 size_t max_redirect_map_size,
1003 RedirectDataMap* redirect_map) {
1004 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1005
1006 RedirectDataMap::iterator cache_entry = redirect_map->find(key);
1007 if (cache_entry == redirect_map->end()) {
1008 if (redirect_map->size() >= max_redirect_map_size) {
1009 RemoveOldestEntryInRedirectDataMap(key_type, redirect_map);
Benoit L 2016/09/19 13:53:47 nit: no braces.
1010 }
1011
1012 cache_entry =
1013 redirect_map->insert(std::make_pair(key, RedirectData(key_type, key)))
1014 .first;
1015 cache_entry->second.last_visit = base::Time::Now();
1016 RedirectRow row_to_add;
1017 row_to_add.url = final_redirect;
1018 row_to_add.number_of_hits = 1;
1019 cache_entry->second.redirects.push_back(row_to_add);
1020 } else {
1021 std::vector<RedirectRow>& redirects = cache_entry->second.redirects;
1022 bool need_to_add = true;
1023
1024 cache_entry->second.last_visit = base::Time::Now();
1025 for (RedirectRow& redirect : redirects) {
1026 if (redirect.url == final_redirect) {
1027 need_to_add = false;
1028 ++redirect.number_of_hits;
1029 redirect.consecutive_misses = 0;
1030 } else {
1031 ++redirect.number_of_misses;
1032 ++redirect.consecutive_misses;
1033 }
1034 }
1035
1036 if (need_to_add) {
1037 RedirectRow row_to_add;
1038 row_to_add.url = final_redirect;
Benoit L 2016/09/19 13:53:47 The key is the final redirect url?
alexilin 2016/09/19 16:49:25 No. RedirectRow doesn't have a key at all, it is s
1039 row_to_add.number_of_hits = 1;
1040 redirects.push_back(row_to_add);
1041 }
1042 }
1043
1044 std::vector<RedirectRow>& redirects = cache_entry->second.redirects;
1045 // Trim and sort redirects after update.
1046 for (std::vector<RedirectRow>::iterator it = redirects.begin();
1047 it != redirects.end();) {
1048 it->UpdateScore();
1049 if (it->consecutive_misses >= config_.max_consecutive_misses)
1050 it = redirects.erase(it);
1051 else
1052 ++it;
1053 }
1054 ResourcePrefetchPredictorTables::SortRedirectRows(&redirects);
1055
1056 if (redirects.size() > config_.max_redirects_per_entry)
1057 redirects.resize(config_.max_redirects_per_entry);
1058
1059 if (redirects.empty()) {
1060 redirect_map->erase(cache_entry);
1061 BrowserThread::PostTask(
1062 BrowserThread::DB, FROM_HERE,
1063 base::Bind(
1064 &ResourcePrefetchPredictorTables::DeleteSingleRedirectDataPoint,
1065 tables_, key, key_type));
1066 } else {
1067 bool is_host = key_type == PREFETCH_KEY_TYPE_HOST;
1068 RedirectData empty_redirect_data(
1069 !is_host ? PREFETCH_KEY_TYPE_HOST : PREFETCH_KEY_TYPE_URL,
1070 std::string());
1071 PrefetchData empty_url_data(PREFETCH_KEY_TYPE_URL, std::string());
1072 PrefetchData empty_host_data(PREFETCH_KEY_TYPE_HOST, std::string());
1073 const RedirectData& host_redirect_data =
1074 is_host ? cache_entry->second : empty_redirect_data;
1075 const RedirectData& url_redirect_data =
1076 is_host ? empty_redirect_data : cache_entry->second;
1077 BrowserThread::PostTask(
1078 BrowserThread::DB, FROM_HERE,
1079 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, tables_,
1080 empty_url_data, empty_host_data, url_redirect_data,
1081 host_redirect_data));
1082 }
1083 }
1084
932 void ResourcePrefetchPredictor::OnURLsDeleted( 1085 void ResourcePrefetchPredictor::OnURLsDeleted(
933 history::HistoryService* history_service, 1086 history::HistoryService* history_service,
934 bool all_history, 1087 bool all_history,
935 bool expired, 1088 bool expired,
936 const history::URLRows& deleted_rows, 1089 const history::URLRows& deleted_rows,
937 const std::set<GURL>& favicon_urls) { 1090 const std::set<GURL>& favicon_urls) {
938 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1091 DCHECK_CURRENTLY_ON(BrowserThread::UI);
939 if (INITIALIZED != initialization_state_) 1092 if (INITIALIZED != initialization_state_)
940 return; 1093 return;
941 1094
(...skipping 27 matching lines...) Expand all
969 // HistoryService is already loaded. Continue with Initialization. 1122 // HistoryService is already loaded. Continue with Initialization.
970 OnHistoryAndCacheLoaded(); 1123 OnHistoryAndCacheLoaded();
971 return; 1124 return;
972 } 1125 }
973 DCHECK(!history_service_observer_.IsObserving(history_service)); 1126 DCHECK(!history_service_observer_.IsObserving(history_service));
974 history_service_observer_.Add(history_service); 1127 history_service_observer_.Add(history_service);
975 return; 1128 return;
976 } 1129 }
977 1130
978 } // namespace predictors 1131 } // namespace predictors
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698