Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |