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

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

Issue 2796783004: predictors: Add origin learning. (Closed)
Patch Set: Rebase (oops) and comments. Created 3 years, 8 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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 REPORTING_EVENT_ALL_HISTORY_CLEARED = 0, 60 REPORTING_EVENT_ALL_HISTORY_CLEARED = 0,
61 REPORTING_EVENT_PARTIAL_HISTORY_CLEARED = 1, 61 REPORTING_EVENT_PARTIAL_HISTORY_CLEARED = 1,
62 REPORTING_EVENT_COUNT = 2 62 REPORTING_EVENT_COUNT = 2
63 }; 63 };
64 64
65 float ComputeRedirectConfidence(const predictors::RedirectStat& redirect) { 65 float ComputeRedirectConfidence(const predictors::RedirectStat& redirect) {
66 return (redirect.number_of_hits() + 0.0) / 66 return (redirect.number_of_hits() + 0.0) /
67 (redirect.number_of_hits() + redirect.number_of_misses()); 67 (redirect.number_of_hits() + redirect.number_of_misses());
68 } 68 }
69 69
70 void UpdateOrAddToOrigins(
71 std::map<GURL, ResourcePrefetchPredictor::OriginRequestSummary>* summaries,
72 const ResourcePrefetchPredictor::URLRequestSummary& request_summary) {
73 DCHECK(request_summary.resource_url.is_valid());
74 if (!request_summary.resource_url.is_valid())
75 return;
76
77 GURL origin = request_summary.resource_url.GetOrigin();
78 auto it = summaries->find(origin);
79 if (it == summaries->end()) {
80 ResourcePrefetchPredictor::OriginRequestSummary summary;
81 summary.origin = origin;
82 summary.first_occurrence = summaries->size();
83 it = summaries->insert({origin, summary}).first;
84 }
85
86 it->second.always_access_network |=
87 request_summary.always_revalidate || request_summary.is_no_store;
88 it->second.accessed_network |= request_summary.network_accessed;
89 }
90
91 void InitializeOriginStatFromOriginRequestSummary(
92 OriginStat* origin,
93 const ResourcePrefetchPredictor::OriginRequestSummary& summary) {
94 origin->set_origin(summary.origin.spec());
95 origin->set_number_of_hits(1);
96 origin->set_average_position(summary.first_occurrence + 1);
97 origin->set_always_access_network(summary.always_access_network);
98 origin->set_accessed_network(summary.accessed_network);
99 }
100
70 // Used to fetch the visit count for a URL from the History database. 101 // Used to fetch the visit count for a URL from the History database.
71 class GetUrlVisitCountTask : public history::HistoryDBTask { 102 class GetUrlVisitCountTask : public history::HistoryDBTask {
72 public: 103 public:
73 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary; 104 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary;
74 using PageRequestSummary = ResourcePrefetchPredictor::PageRequestSummary; 105 using PageRequestSummary = ResourcePrefetchPredictor::PageRequestSummary;
75 typedef base::Callback<void(size_t, // URL visit count. 106 typedef base::Callback<void(size_t, // URL visit count.
76 const PageRequestSummary&)> 107 const PageRequestSummary&)>
77 VisitInfoCallback; 108 VisitInfoCallback;
78 109
79 GetUrlVisitCountTask(std::unique_ptr<PageRequestSummary> summary, 110 GetUrlVisitCountTask(std::unique_ptr<PageRequestSummary> summary,
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 302
272 content::ResourceType resource_type = request_info->GetResourceType(); 303 content::ResourceType resource_type = request_info->GetResourceType();
273 return resource_type == content::RESOURCE_TYPE_MAIN_FRAME 304 return resource_type == content::RESOURCE_TYPE_MAIN_FRAME
274 ? IsHandledMainPage(response) 305 ? IsHandledMainPage(response)
275 : IsHandledSubresource(response, resource_type); 306 : IsHandledSubresource(response, resource_type);
276 } 307 }
277 308
278 // static 309 // static
279 bool ResourcePrefetchPredictor::ShouldRecordRedirect( 310 bool ResourcePrefetchPredictor::ShouldRecordRedirect(
280 net::URLRequest* response) { 311 net::URLRequest* response) {
281 const content::ResourceRequestInfo* request_info = 312 return ShouldRecordResponse(response);
282 content::ResourceRequestInfo::ForRequest(response);
283 if (!request_info)
284 return false;
285
286 if (!request_info->IsMainFrame())
287 return false;
288
289 return request_info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME &&
290 IsHandledMainPage(response);
291 } 313 }
292 314
293 // static 315 // static
294 bool ResourcePrefetchPredictor::IsHandledMainPage(net::URLRequest* request) { 316 bool ResourcePrefetchPredictor::IsHandledMainPage(net::URLRequest* request) {
295 const GURL& url = request->url(); 317 const GURL& url = request->url();
296 bool bad_port = !g_allow_port_in_urls && url.has_port(); 318 bool bad_port = !g_allow_port_in_urls && url.has_port();
297 return url.SchemeIsHTTPOrHTTPS() && !bad_port; 319 return url.SchemeIsHTTPOrHTTPS() && !bad_port;
298 } 320 }
299 321
300 // static 322 // static
(...skipping 13 matching lines...) Expand all
314 return false; 336 return false;
315 337
316 if (response->method() != "GET") 338 if (response->method() != "GET")
317 return false; 339 return false;
318 340
319 if (response->original_url().spec().length() > 341 if (response->original_url().spec().length() >
320 ResourcePrefetchPredictorTables::kMaxStringLength) { 342 ResourcePrefetchPredictorTables::kMaxStringLength) {
321 return false; 343 return false;
322 } 344 }
323 345
324 if (!response->response_info().headers.get() || IsNoStore(response)) 346 if (!response->response_info().headers.get())
325 return false; 347 return false;
326 348
327 return true; 349 return true;
328 } 350 }
329 351
330 // static 352 // static
331 bool ResourcePrefetchPredictor::IsHandledResourceType( 353 bool ResourcePrefetchPredictor::IsHandledResourceType(
332 content::ResourceType resource_type, 354 content::ResourceType resource_type,
333 const std::string& mime_type) { 355 const std::string& mime_type) {
334 content::ResourceType actual_resource_type = 356 content::ResourceType actual_resource_type =
(...skipping 14 matching lines...) Expand all
349 if (resource_type == content::RESOURCE_TYPE_PREFETCH || 371 if (resource_type == content::RESOURCE_TYPE_PREFETCH ||
350 resource_type == content::RESOURCE_TYPE_SUB_RESOURCE || 372 resource_type == content::RESOURCE_TYPE_SUB_RESOURCE ||
351 resource_type == content::RESOURCE_TYPE_XHR) { 373 resource_type == content::RESOURCE_TYPE_XHR) {
352 return GetResourceTypeFromMimeType(mime_type, 374 return GetResourceTypeFromMimeType(mime_type,
353 content::RESOURCE_TYPE_LAST_TYPE); 375 content::RESOURCE_TYPE_LAST_TYPE);
354 } 376 }
355 return resource_type; 377 return resource_type;
356 } 378 }
357 379
358 // static 380 // static
359 bool ResourcePrefetchPredictor::IsNoStore(const net::URLRequest* response) { 381 bool ResourcePrefetchPredictor::IsNoStore(const net::URLRequest& response) {
360 if (response->was_cached()) 382 if (response.was_cached())
361 return false; 383 return false;
362 384
363 const net::HttpResponseInfo& response_info = response->response_info(); 385 const net::HttpResponseInfo& response_info = response.response_info();
364 if (!response_info.headers.get()) 386 if (!response_info.headers.get())
365 return false; 387 return false;
366 return response_info.headers->HasHeaderValue("cache-control", "no-store"); 388 return response_info.headers->HasHeaderValue("cache-control", "no-store");
367 } 389 }
368 390
369 // static 391 // static
370 content::ResourceType ResourcePrefetchPredictor::GetResourceTypeFromMimeType( 392 content::ResourceType ResourcePrefetchPredictor::GetResourceTypeFromMimeType(
371 const std::string& mime_type, 393 const std::string& mime_type,
372 content::ResourceType fallback) { 394 content::ResourceType fallback) {
373 if (mime_type.empty()) { 395 if (mime_type.empty()) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 } 445 }
424 446
425 // static 447 // static
426 void ResourcePrefetchPredictor::SetAllowPortInUrlsForTesting(bool state) { 448 void ResourcePrefetchPredictor::SetAllowPortInUrlsForTesting(bool state) {
427 g_allow_port_in_urls = state; 449 g_allow_port_in_urls = state;
428 } 450 }
429 451
430 //////////////////////////////////////////////////////////////////////////////// 452 ////////////////////////////////////////////////////////////////////////////////
431 // ResourcePrefetchPredictor nested types. 453 // ResourcePrefetchPredictor nested types.
432 454
455 ResourcePrefetchPredictor::OriginRequestSummary::OriginRequestSummary()
456 : origin(),
457 always_access_network(false),
458 accessed_network(false),
459 first_occurrence(0) {}
460
461 ResourcePrefetchPredictor::OriginRequestSummary::OriginRequestSummary(
462 const OriginRequestSummary& other) = default;
463
464 ResourcePrefetchPredictor::OriginRequestSummary::~OriginRequestSummary() {}
465
433 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary() 466 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary()
434 : resource_type(content::RESOURCE_TYPE_LAST_TYPE), 467 : resource_type(content::RESOURCE_TYPE_LAST_TYPE),
435 priority(net::IDLE), 468 priority(net::IDLE),
436 was_cached(false), 469 was_cached(false),
437 has_validators(false), 470 has_validators(false),
438 always_revalidate(false) {} 471 always_revalidate(false),
472 is_no_store(false),
473 network_accessed(false) {}
439 474
440 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary( 475 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary(
441 const URLRequestSummary& other) 476 const URLRequestSummary& other) = default;
442 : navigation_id(other.navigation_id),
443 resource_url(other.resource_url),
444 resource_type(other.resource_type),
445 priority(other.priority),
446 mime_type(other.mime_type),
447 was_cached(other.was_cached),
448 redirect_url(other.redirect_url),
449 has_validators(other.has_validators),
450 always_revalidate(other.always_revalidate) {}
451 477
452 ResourcePrefetchPredictor::URLRequestSummary::~URLRequestSummary() { 478 ResourcePrefetchPredictor::URLRequestSummary::~URLRequestSummary() {
453 } 479 }
454 480
455 // static 481 // static
456 bool ResourcePrefetchPredictor::URLRequestSummary::SummarizeResponse( 482 bool ResourcePrefetchPredictor::URLRequestSummary::SummarizeResponse(
457 const net::URLRequest& request, 483 const net::URLRequest& request,
458 URLRequestSummary* summary) { 484 URLRequestSummary* summary) {
459 const content::ResourceRequestInfo* request_info = 485 const content::ResourceRequestInfo* request_info =
460 content::ResourceRequestInfo::ForRequest(&request); 486 content::ResourceRequestInfo::ForRequest(&request);
(...skipping 11 matching lines...) Expand all
472 498
473 scoped_refptr<net::HttpResponseHeaders> headers = 499 scoped_refptr<net::HttpResponseHeaders> headers =
474 request.response_info().headers; 500 request.response_info().headers;
475 if (headers.get()) { 501 if (headers.get()) {
476 summary->has_validators = headers->HasValidators(); 502 summary->has_validators = headers->HasValidators();
477 // RFC 2616, section 14.9. 503 // RFC 2616, section 14.9.
478 summary->always_revalidate = 504 summary->always_revalidate =
479 headers->HasHeaderValue("cache-control", "no-cache") || 505 headers->HasHeaderValue("cache-control", "no-cache") ||
480 headers->HasHeaderValue("pragma", "no-cache") || 506 headers->HasHeaderValue("pragma", "no-cache") ||
481 headers->HasHeaderValue("vary", "*"); 507 headers->HasHeaderValue("vary", "*");
508 summary->is_no_store = IsNoStore(request);
482 } 509 }
510 summary->network_accessed = request.response_info().network_accessed;
483 return true; 511 return true;
484 } 512 }
485 513
486 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary( 514 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary(
487 const GURL& i_main_frame_url) 515 const GURL& i_main_frame_url)
488 : main_frame_url(i_main_frame_url), initial_url(i_main_frame_url) {} 516 : main_frame_url(i_main_frame_url), initial_url(i_main_frame_url) {}
489 517
490 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary( 518 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary(
491 const PageRequestSummary& other) = default; 519 const PageRequestSummary& other) = default;
492 520
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 if (initialization_state_ != NOT_INITIALIZED) 555 if (initialization_state_ != NOT_INITIALIZED)
528 return; 556 return;
529 initialization_state_ = INITIALIZING; 557 initialization_state_ = INITIALIZING;
530 558
531 // Create local caches using the database as loaded. 559 // Create local caches using the database as loaded.
532 auto url_data_map = base::MakeUnique<PrefetchDataMap>(); 560 auto url_data_map = base::MakeUnique<PrefetchDataMap>();
533 auto host_data_map = base::MakeUnique<PrefetchDataMap>(); 561 auto host_data_map = base::MakeUnique<PrefetchDataMap>();
534 auto url_redirect_data_map = base::MakeUnique<RedirectDataMap>(); 562 auto url_redirect_data_map = base::MakeUnique<RedirectDataMap>();
535 auto host_redirect_data_map = base::MakeUnique<RedirectDataMap>(); 563 auto host_redirect_data_map = base::MakeUnique<RedirectDataMap>();
536 auto manifest_data_map = base::MakeUnique<ManifestDataMap>(); 564 auto manifest_data_map = base::MakeUnique<ManifestDataMap>();
565 auto origin_data_map = base::MakeUnique<OriginDataMap>();
537 566
538 // Get raw pointers to pass to the first task. Ownership of the unique_ptrs 567 // Get raw pointers to pass to the first task. Ownership of the unique_ptrs
539 // will be passed to the reply task. 568 // will be passed to the reply task.
540 auto* url_data_map_ptr = url_data_map.get(); 569 auto* url_data_map_ptr = url_data_map.get();
541 auto* host_data_map_ptr = host_data_map.get(); 570 auto* host_data_map_ptr = host_data_map.get();
542 auto* url_redirect_data_map_ptr = url_redirect_data_map.get(); 571 auto* url_redirect_data_map_ptr = url_redirect_data_map.get();
543 auto* host_redirect_data_map_ptr = host_redirect_data_map.get(); 572 auto* host_redirect_data_map_ptr = host_redirect_data_map.get();
544 auto* manifest_data_map_ptr = manifest_data_map.get(); 573 auto* manifest_data_map_ptr = manifest_data_map.get();
574 auto* origin_data_map_ptr = origin_data_map.get();
545 575
546 BrowserThread::PostTaskAndReply( 576 BrowserThread::PostTaskAndReply(
547 BrowserThread::DB, FROM_HERE, 577 BrowserThread::DB, FROM_HERE,
548 base::Bind(&ResourcePrefetchPredictorTables::GetAllData, tables_, 578 base::Bind(&ResourcePrefetchPredictorTables::GetAllData, tables_,
549 url_data_map_ptr, host_data_map_ptr, url_redirect_data_map_ptr, 579 url_data_map_ptr, host_data_map_ptr, url_redirect_data_map_ptr,
550 host_redirect_data_map_ptr, manifest_data_map_ptr), 580 host_redirect_data_map_ptr, manifest_data_map_ptr,
581 origin_data_map_ptr),
551 base::Bind(&ResourcePrefetchPredictor::CreateCaches, AsWeakPtr(), 582 base::Bind(&ResourcePrefetchPredictor::CreateCaches, AsWeakPtr(),
552 base::Passed(&url_data_map), base::Passed(&host_data_map), 583 base::Passed(&url_data_map), base::Passed(&host_data_map),
553 base::Passed(&url_redirect_data_map), 584 base::Passed(&url_redirect_data_map),
554 base::Passed(&host_redirect_data_map), 585 base::Passed(&host_redirect_data_map),
555 base::Passed(&manifest_data_map))); 586 base::Passed(&manifest_data_map),
587 base::Passed(&origin_data_map)));
556 } 588 }
557 589
558 void ResourcePrefetchPredictor::RecordURLRequest( 590 void ResourcePrefetchPredictor::RecordURLRequest(
559 const URLRequestSummary& request) { 591 const URLRequestSummary& request) {
560 DCHECK_CURRENTLY_ON(BrowserThread::UI); 592 DCHECK_CURRENTLY_ON(BrowserThread::UI);
561 if (initialization_state_ != INITIALIZED) 593 if (initialization_state_ != INITIALIZED)
562 return; 594 return;
563 595
564 CHECK_EQ(request.resource_type, content::RESOURCE_TYPE_MAIN_FRAME); 596 CHECK_EQ(request.resource_type, content::RESOURCE_TYPE_MAIN_FRAME);
565 OnMainFrameRequest(request); 597 OnMainFrameRequest(request);
(...skipping 10 matching lines...) Expand all
576 else 608 else
577 OnSubresourceResponse(response); 609 OnSubresourceResponse(response);
578 } 610 }
579 611
580 void ResourcePrefetchPredictor::RecordURLRedirect( 612 void ResourcePrefetchPredictor::RecordURLRedirect(
581 const URLRequestSummary& response) { 613 const URLRequestSummary& response) {
582 DCHECK_CURRENTLY_ON(BrowserThread::UI); 614 DCHECK_CURRENTLY_ON(BrowserThread::UI);
583 if (initialization_state_ != INITIALIZED) 615 if (initialization_state_ != INITIALIZED)
584 return; 616 return;
585 617
586 CHECK_EQ(response.resource_type, content::RESOURCE_TYPE_MAIN_FRAME); 618 if (response.resource_type == content::RESOURCE_TYPE_MAIN_FRAME)
587 OnMainFrameRedirect(response); 619 OnMainFrameRedirect(response);
620 else
621 OnSubresourceRedirect(response);
588 } 622 }
589 623
590 void ResourcePrefetchPredictor::RecordMainFrameLoadComplete( 624 void ResourcePrefetchPredictor::RecordMainFrameLoadComplete(
591 const NavigationID& navigation_id) { 625 const NavigationID& navigation_id) {
592 switch (initialization_state_) { 626 switch (initialization_state_) {
593 case NOT_INITIALIZED: 627 case NOT_INITIALIZED:
594 StartInitialization(); 628 StartInitialization();
595 break; 629 break;
596 case INITIALIZING: 630 case INITIALIZING:
597 break; 631 break;
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
757 inflight_navigations_.insert( 791 inflight_navigations_.insert(
758 std::make_pair(navigation_id, std::move(summary))); 792 std::make_pair(navigation_id, std::move(summary)));
759 } 793 }
760 794
761 void ResourcePrefetchPredictor::OnSubresourceResponse( 795 void ResourcePrefetchPredictor::OnSubresourceResponse(
762 const URLRequestSummary& response) { 796 const URLRequestSummary& response) {
763 DCHECK_CURRENTLY_ON(BrowserThread::UI); 797 DCHECK_CURRENTLY_ON(BrowserThread::UI);
764 DCHECK_EQ(INITIALIZED, initialization_state_); 798 DCHECK_EQ(INITIALIZED, initialization_state_);
765 799
766 NavigationMap::const_iterator nav_it = 800 NavigationMap::const_iterator nav_it =
767 inflight_navigations_.find(response.navigation_id); 801 inflight_navigations_.find(response.navigation_id);
768 if (nav_it == inflight_navigations_.end()) { 802 if (nav_it == inflight_navigations_.end())
769 return; 803 return;
770 } 804 auto& page_request_summary = *nav_it->second;
771 805
772 nav_it->second->subresource_requests.push_back(response); 806 if (!response.is_no_store)
807 page_request_summary.subresource_requests.push_back(response);
808
809 if (config_.is_origin_prediction_enabled)
810 UpdateOrAddToOrigins(&page_request_summary.origins, response);
811 }
812
813 void ResourcePrefetchPredictor::OnSubresourceRedirect(
814 const URLRequestSummary& response) {
815 DCHECK_CURRENTLY_ON(BrowserThread::UI);
816 DCHECK_EQ(INITIALIZED, initialization_state_);
817
818 if (!config_.is_origin_prediction_enabled)
819 return;
820
821 NavigationMap::const_iterator nav_it =
822 inflight_navigations_.find(response.navigation_id);
823 if (nav_it == inflight_navigations_.end())
824 return;
825 auto& page_request_summary = *nav_it->second;
826 UpdateOrAddToOrigins(&page_request_summary.origins, response);
773 } 827 }
774 828
775 void ResourcePrefetchPredictor::OnNavigationComplete( 829 void ResourcePrefetchPredictor::OnNavigationComplete(
776 const NavigationID& nav_id_without_timing_info) { 830 const NavigationID& nav_id_without_timing_info) {
777 DCHECK_CURRENTLY_ON(BrowserThread::UI); 831 DCHECK_CURRENTLY_ON(BrowserThread::UI);
778 DCHECK_EQ(INITIALIZED, initialization_state_); 832 DCHECK_EQ(INITIALIZED, initialization_state_);
779 833
780 NavigationMap::iterator nav_it = 834 NavigationMap::iterator nav_it =
781 inflight_navigations_.find(nav_id_without_timing_info); 835 inflight_navigations_.find(nav_id_without_timing_info);
782 if (nav_it == inflight_navigations_.end()) 836 if (nav_it == inflight_navigations_.end())
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
896 } 950 }
897 951
898 return has_prefetchable_resource; 952 return has_prefetchable_resource;
899 } 953 }
900 954
901 void ResourcePrefetchPredictor::CreateCaches( 955 void ResourcePrefetchPredictor::CreateCaches(
902 std::unique_ptr<PrefetchDataMap> url_data_map, 956 std::unique_ptr<PrefetchDataMap> url_data_map,
903 std::unique_ptr<PrefetchDataMap> host_data_map, 957 std::unique_ptr<PrefetchDataMap> host_data_map,
904 std::unique_ptr<RedirectDataMap> url_redirect_data_map, 958 std::unique_ptr<RedirectDataMap> url_redirect_data_map,
905 std::unique_ptr<RedirectDataMap> host_redirect_data_map, 959 std::unique_ptr<RedirectDataMap> host_redirect_data_map,
906 std::unique_ptr<ManifestDataMap> manifest_data_map) { 960 std::unique_ptr<ManifestDataMap> manifest_data_map,
961 std::unique_ptr<OriginDataMap> origin_data_map) {
907 DCHECK_CURRENTLY_ON(BrowserThread::UI); 962 DCHECK_CURRENTLY_ON(BrowserThread::UI);
908 963
909 DCHECK_EQ(INITIALIZING, initialization_state_); 964 DCHECK_EQ(INITIALIZING, initialization_state_);
910 DCHECK(!url_table_cache_); 965 DCHECK(!url_table_cache_);
911 DCHECK(!host_table_cache_); 966 DCHECK(!host_table_cache_);
912 DCHECK(!url_redirect_table_cache_); 967 DCHECK(!url_redirect_table_cache_);
913 DCHECK(!host_redirect_table_cache_); 968 DCHECK(!host_redirect_table_cache_);
914 DCHECK(!manifest_table_cache_); 969 DCHECK(!manifest_table_cache_);
970 DCHECK(!origin_table_cache_);
971
915 DCHECK(inflight_navigations_.empty()); 972 DCHECK(inflight_navigations_.empty());
916 973
917 url_table_cache_ = std::move(url_data_map); 974 url_table_cache_ = std::move(url_data_map);
918 host_table_cache_ = std::move(host_data_map); 975 host_table_cache_ = std::move(host_data_map);
919 url_redirect_table_cache_ = std::move(url_redirect_data_map); 976 url_redirect_table_cache_ = std::move(url_redirect_data_map);
920 host_redirect_table_cache_ = std::move(host_redirect_data_map); 977 host_redirect_table_cache_ = std::move(host_redirect_data_map);
921 manifest_table_cache_ = std::move(manifest_data_map); 978 manifest_table_cache_ = std::move(manifest_data_map);
979 origin_table_cache_ = std::move(origin_data_map);
922 980
923 ConnectToHistoryService(); 981 ConnectToHistoryService();
924 } 982 }
925 983
926 void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() { 984 void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() {
927 DCHECK_CURRENTLY_ON(BrowserThread::UI); 985 DCHECK_CURRENTLY_ON(BrowserThread::UI);
928 DCHECK_EQ(INITIALIZING, initialization_state_); 986 DCHECK_EQ(INITIALIZING, initialization_state_);
929 987
930 // Initialize the prefetch manager only if prefetching is enabled. 988 // Initialize the prefetch manager only if prefetching is enabled.
931 if (config_.IsPrefetchingEnabledForSomeOrigin(profile_)) { 989 if (config_.IsPrefetchingEnabledForSomeOrigin(profile_)) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
982 } 1040 }
983 } 1041 }
984 1042
985 void ResourcePrefetchPredictor::DeleteAllUrls() { 1043 void ResourcePrefetchPredictor::DeleteAllUrls() {
986 inflight_navigations_.clear(); 1044 inflight_navigations_.clear();
987 url_table_cache_->clear(); 1045 url_table_cache_->clear();
988 host_table_cache_->clear(); 1046 host_table_cache_->clear();
989 url_redirect_table_cache_->clear(); 1047 url_redirect_table_cache_->clear();
990 host_redirect_table_cache_->clear(); 1048 host_redirect_table_cache_->clear();
991 manifest_table_cache_->clear(); 1049 manifest_table_cache_->clear();
1050 origin_table_cache_->clear();
992 1051
993 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, 1052 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
994 base::Bind(&ResourcePrefetchPredictorTables::DeleteAllData, tables_)); 1053 base::Bind(&ResourcePrefetchPredictorTables::DeleteAllData, tables_));
995 } 1054 }
996 1055
997 void ResourcePrefetchPredictor::DeleteUrls(const history::URLRows& urls) { 1056 void ResourcePrefetchPredictor::DeleteUrls(const history::URLRows& urls) {
998 // Check all the urls in the database and pick out the ones that are present 1057 // Check all the urls in the database and pick out the ones that are present
999 // in the cache. 1058 // in the cache.
1000 std::vector<std::string> urls_to_delete, hosts_to_delete; 1059 std::vector<std::string> urls_to_delete, hosts_to_delete;
1001 std::vector<std::string> url_redirects_to_delete, host_redirects_to_delete; 1060 std::vector<std::string> url_redirects_to_delete, host_redirects_to_delete;
1002 std::vector<std::string> manifest_hosts_to_delete; 1061 std::vector<std::string> manifest_hosts_to_delete;
1062 std::vector<std::string> origin_hosts_to_delete;
1003 1063
1004 for (const auto& it : urls) { 1064 for (const auto& it : urls) {
1005 const std::string& url_spec = it.url().spec(); 1065 const std::string& url_spec = it.url().spec();
1006 if (url_table_cache_->find(url_spec) != url_table_cache_->end()) { 1066 if (url_table_cache_->find(url_spec) != url_table_cache_->end()) {
1007 urls_to_delete.push_back(url_spec); 1067 urls_to_delete.push_back(url_spec);
1008 url_table_cache_->erase(url_spec); 1068 url_table_cache_->erase(url_spec);
1009 } 1069 }
1010 1070
1011 if (url_redirect_table_cache_->find(url_spec) != 1071 if (url_redirect_table_cache_->find(url_spec) !=
1012 url_redirect_table_cache_->end()) { 1072 url_redirect_table_cache_->end()) {
(...skipping 12 matching lines...) Expand all
1025 host_redirects_to_delete.push_back(host); 1085 host_redirects_to_delete.push_back(host);
1026 host_redirect_table_cache_->erase(host); 1086 host_redirect_table_cache_->erase(host);
1027 } 1087 }
1028 1088
1029 std::string manifest_host = history::HostForTopHosts(it.url()); 1089 std::string manifest_host = history::HostForTopHosts(it.url());
1030 if (manifest_table_cache_->find(manifest_host) != 1090 if (manifest_table_cache_->find(manifest_host) !=
1031 manifest_table_cache_->end()) { 1091 manifest_table_cache_->end()) {
1032 manifest_hosts_to_delete.push_back(manifest_host); 1092 manifest_hosts_to_delete.push_back(manifest_host);
1033 manifest_table_cache_->erase(manifest_host); 1093 manifest_table_cache_->erase(manifest_host);
1034 } 1094 }
1095
1096 if (origin_table_cache_->find(host) != origin_table_cache_->end()) {
1097 origin_hosts_to_delete.push_back(host);
1098 origin_table_cache_->erase(host);
1099 }
1035 } 1100 }
1036 1101
1037 if (!urls_to_delete.empty() || !hosts_to_delete.empty()) { 1102 if (!urls_to_delete.empty() || !hosts_to_delete.empty()) {
1038 BrowserThread::PostTask( 1103 BrowserThread::PostTask(
1039 BrowserThread::DB, FROM_HERE, 1104 BrowserThread::DB, FROM_HERE,
1040 base::Bind(&ResourcePrefetchPredictorTables::DeleteResourceData, 1105 base::Bind(&ResourcePrefetchPredictorTables::DeleteResourceData,
1041 tables_, urls_to_delete, hosts_to_delete)); 1106 tables_, urls_to_delete, hosts_to_delete));
1042 } 1107 }
1043 1108
1044 if (!url_redirects_to_delete.empty() || !host_redirects_to_delete.empty()) { 1109 if (!url_redirects_to_delete.empty() || !host_redirects_to_delete.empty()) {
1045 BrowserThread::PostTask( 1110 BrowserThread::PostTask(
1046 BrowserThread::DB, FROM_HERE, 1111 BrowserThread::DB, FROM_HERE,
1047 base::Bind(&ResourcePrefetchPredictorTables::DeleteRedirectData, 1112 base::Bind(&ResourcePrefetchPredictorTables::DeleteRedirectData,
1048 tables_, url_redirects_to_delete, host_redirects_to_delete)); 1113 tables_, url_redirects_to_delete, host_redirects_to_delete));
1049 } 1114 }
1050 1115
1051 if (!manifest_hosts_to_delete.empty()) { 1116 if (!manifest_hosts_to_delete.empty()) {
1052 BrowserThread::PostTask( 1117 BrowserThread::PostTask(
1053 BrowserThread::DB, FROM_HERE, 1118 BrowserThread::DB, FROM_HERE,
1054 base::Bind(&ResourcePrefetchPredictorTables::DeleteManifestData, 1119 base::Bind(&ResourcePrefetchPredictorTables::DeleteManifestData,
1055 tables_, manifest_hosts_to_delete)); 1120 tables_, manifest_hosts_to_delete));
1056 } 1121 }
1122
1123 if (!origin_hosts_to_delete.empty()) {
1124 BrowserThread::PostTask(
1125 BrowserThread::DB, FROM_HERE,
1126 base::Bind(&ResourcePrefetchPredictorTables::DeleteOriginData, tables_,
1127 origin_hosts_to_delete));
1128 }
1057 } 1129 }
1058 1130
1059 void ResourcePrefetchPredictor::RemoveOldestEntryInPrefetchDataMap( 1131 void ResourcePrefetchPredictor::RemoveOldestEntryInPrefetchDataMap(
1060 PrefetchKeyType key_type, 1132 PrefetchKeyType key_type,
1061 PrefetchDataMap* data_map) { 1133 PrefetchDataMap* data_map) {
1062 if (data_map->empty()) 1134 if (data_map->empty())
1063 return; 1135 return;
1064 1136
1065 uint64_t oldest_time = UINT64_MAX; 1137 uint64_t oldest_time = UINT64_MAX;
1066 std::string key_to_delete; 1138 std::string key_to_delete;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1117 }); 1189 });
1118 1190
1119 std::string key_to_delete = oldest_entry->first; 1191 std::string key_to_delete = oldest_entry->first;
1120 data_map->erase(oldest_entry); 1192 data_map->erase(oldest_entry);
1121 BrowserThread::PostTask( 1193 BrowserThread::PostTask(
1122 BrowserThread::DB, FROM_HERE, 1194 BrowserThread::DB, FROM_HERE,
1123 base::Bind(&ResourcePrefetchPredictorTables::DeleteManifestData, tables_, 1195 base::Bind(&ResourcePrefetchPredictorTables::DeleteManifestData, tables_,
1124 std::vector<std::string>({key_to_delete}))); 1196 std::vector<std::string>({key_to_delete})));
1125 } 1197 }
1126 1198
1199 void ResourcePrefetchPredictor::RemoveOldestEntryInOriginDataMap(
1200 OriginDataMap* data_map) {
1201 if (data_map->empty())
1202 return;
1203
1204 uint64_t oldest_time = UINT64_MAX;
1205 std::string key_to_delete;
1206 for (const auto& kv : *data_map) {
1207 const OriginData& data = kv.second;
1208 if (key_to_delete.empty() || data.last_visit_time() < oldest_time) {
1209 key_to_delete = kv.first;
1210 oldest_time = data.last_visit_time();
1211 }
1212 }
1213
1214 data_map->erase(key_to_delete);
1215 BrowserThread::PostTask(
1216 BrowserThread::DB, FROM_HERE,
1217 base::Bind(&ResourcePrefetchPredictorTables::DeleteOriginData, tables_,
1218 std::vector<std::string>({key_to_delete})));
1219 }
1220
1127 void ResourcePrefetchPredictor::OnVisitCountLookup( 1221 void ResourcePrefetchPredictor::OnVisitCountLookup(
1128 size_t url_visit_count, 1222 size_t url_visit_count,
1129 const PageRequestSummary& summary) { 1223 const PageRequestSummary& summary) {
1130 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1224 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1131 1225
1132 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HistoryVisitCountForUrl", 1226 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HistoryVisitCountForUrl",
1133 url_visit_count); 1227 url_visit_count);
1134 1228
1135 // TODO(alexilin): make only one request to DB thread. 1229 // TODO(alexilin): make only one request to DB thread.
1136 1230
(...skipping 13 matching lines...) Expand all
1150 url_redirect_table_cache_.get()); 1244 url_redirect_table_cache_.get());
1151 } 1245 }
1152 } 1246 }
1153 1247
1154 // Host level data - no cutoff, always learn the navigation if enabled. 1248 // Host level data - no cutoff, always learn the navigation if enabled.
1155 const std::string host = summary.main_frame_url.host(); 1249 const std::string host = summary.main_frame_url.host();
1156 LearnNavigation(host, PREFETCH_KEY_TYPE_HOST, summary.subresource_requests, 1250 LearnNavigation(host, PREFETCH_KEY_TYPE_HOST, summary.subresource_requests,
1157 config_.max_hosts_to_track, host_table_cache_.get(), 1251 config_.max_hosts_to_track, host_table_cache_.get(),
1158 summary.initial_url.host(), host_redirect_table_cache_.get()); 1252 summary.initial_url.host(), host_redirect_table_cache_.get());
1159 1253
1254 if (config_.is_origin_prediction_enabled) {
1255 LearnOrigins(host, summary.origins, config_.max_hosts_to_track,
1256 origin_table_cache_.get());
1257 }
1258
1160 if (observer_) 1259 if (observer_)
1161 observer_->OnNavigationLearned(url_visit_count, summary); 1260 observer_->OnNavigationLearned(url_visit_count, summary);
1162 } 1261 }
1163 1262
1164 void ResourcePrefetchPredictor::LearnNavigation( 1263 void ResourcePrefetchPredictor::LearnNavigation(
1165 const std::string& key, 1264 const std::string& key,
1166 PrefetchKeyType key_type, 1265 PrefetchKeyType key_type,
1167 const std::vector<URLRequestSummary>& new_resources, 1266 const std::vector<URLRequestSummary>& new_resources,
1168 size_t max_data_map_size, 1267 size_t max_data_map_size,
1169 PrefetchDataMap* data_map, 1268 PrefetchDataMap* data_map,
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
1394 const RedirectData& url_redirect_data = 1493 const RedirectData& url_redirect_data =
1395 is_host ? empty_redirect_data : data; 1494 is_host ? empty_redirect_data : data;
1396 BrowserThread::PostTask( 1495 BrowserThread::PostTask(
1397 BrowserThread::DB, FROM_HERE, 1496 BrowserThread::DB, FROM_HERE,
1398 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, tables_, 1497 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, tables_,
1399 empty_data, empty_data, url_redirect_data, 1498 empty_data, empty_data, url_redirect_data,
1400 host_redirect_data)); 1499 host_redirect_data));
1401 } 1500 }
1402 } 1501 }
1403 1502
1503 void ResourcePrefetchPredictor::LearnOrigins(
1504 const std::string& host,
1505 const std::map<GURL, OriginRequestSummary>& summaries,
1506 size_t max_data_map_size,
1507 OriginDataMap* data_map) {
1508 if (host.size() > ResourcePrefetchPredictorTables::kMaxStringLength)
1509 return;
1510
1511 auto cache_entry = data_map->find(host);
1512 bool new_entry = cache_entry == data_map->end();
1513 if (new_entry) {
1514 if (data_map->size() >= max_data_map_size)
1515 RemoveOldestEntryInOriginDataMap(data_map);
1516
1517 cache_entry = data_map->insert({host, OriginData()}).first;
1518 OriginData& data = cache_entry->second;
1519 data.set_host(host);
1520 data.set_last_visit_time(base::Time::Now().ToInternalValue());
1521 size_t origins_size = summaries.size();
1522 auto ordered_origins =
1523 std::vector<const OriginRequestSummary*>(origins_size);
1524 for (const auto& kv : summaries) {
1525 size_t index = kv.second.first_occurrence;
1526 DCHECK_LT(index, origins_size);
1527 ordered_origins[index] = &kv.second;
1528 }
1529
1530 for (const OriginRequestSummary* summary : ordered_origins) {
1531 auto* origin_to_add = data.add_origins();
1532 InitializeOriginStatFromOriginRequestSummary(origin_to_add, *summary);
1533 }
1534 } else {
1535 auto& data = cache_entry->second;
1536 data.set_last_visit_time(base::Time::Now().ToInternalValue());
1537
1538 std::map<GURL, int> old_index;
1539 int old_size = static_cast<int>(data.origins_size());
1540 for (int i = 0; i < old_size; ++i) {
1541 bool is_new =
1542 old_index.insert({GURL(data.origins(i).origin()), i}).second;
1543 DCHECK(is_new);
1544 }
1545
1546 // Update the old origins.
1547 for (int i = 0; i < old_size; ++i) {
1548 auto* old_origin = data.mutable_origins(i);
1549 GURL origin(old_origin->origin());
1550 auto it = summaries.find(origin);
1551 if (it == summaries.end()) {
1552 // miss
1553 old_origin->set_number_of_misses(old_origin->number_of_misses() + 1);
1554 old_origin->set_consecutive_misses(old_origin->consecutive_misses() +
1555 1);
1556 } else {
1557 // hit: update.
1558 const auto& new_origin = it->second;
1559 old_origin->set_always_access_network(new_origin.always_access_network);
1560 old_origin->set_accessed_network(new_origin.accessed_network);
1561
1562 int position = new_origin.first_occurrence + 1;
1563 int total =
1564 old_origin->number_of_hits() + old_origin->number_of_misses();
1565 old_origin->set_average_position(
1566 ((old_origin->average_position() * total) + position) /
1567 (total + 1));
1568 old_origin->set_number_of_hits(old_origin->number_of_hits() + 1);
1569 old_origin->set_consecutive_misses(0);
1570 }
1571 }
1572
1573 // Add new origins.
1574 for (const auto& kv : summaries) {
1575 if (old_index.find(kv.first) != old_index.end())
1576 continue;
1577
1578 auto* origin_to_add = data.add_origins();
1579 InitializeOriginStatFromOriginRequestSummary(origin_to_add, kv.second);
1580 }
1581 }
1582
1583 // Trim and Sort.
1584 auto& data = cache_entry->second;
1585 ResourcePrefetchPredictorTables::TrimOrigins(&data,
1586 config_.max_consecutive_misses);
1587 ResourcePrefetchPredictorTables::SortOrigins(&data);
1588 if (data.origins_size() > static_cast<int>(config_.max_resources_per_entry)) {
1589 data.mutable_origins()->DeleteSubrange(
1590 config_.max_origins_per_entry,
1591 data.origins_size() - config_.max_origins_per_entry);
1592 }
1593
1594 // Update the database.
1595 if (data.origins_size() == 0) {
1596 data_map->erase(cache_entry);
1597 if (!new_entry) {
1598 BrowserThread::PostTask(
1599 BrowserThread::DB, FROM_HERE,
1600 base::Bind(&ResourcePrefetchPredictorTables::DeleteOriginData,
1601 tables_, std::vector<std::string>({host})));
1602 }
1603 } else {
1604 BrowserThread::PostTask(
1605 BrowserThread::DB, FROM_HERE,
1606 base::Bind(&ResourcePrefetchPredictorTables::UpdateOriginData, tables_,
1607 data));
1608 }
1609 }
1610
1404 void ResourcePrefetchPredictor::ReportDatabaseReadiness( 1611 void ResourcePrefetchPredictor::ReportDatabaseReadiness(
1405 const history::TopHostsList& top_hosts) const { 1612 const history::TopHostsList& top_hosts) const {
1406 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1613 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1407 if (top_hosts.size() == 0) 1614 if (top_hosts.size() == 0)
1408 return; 1615 return;
1409 1616
1410 size_t count_in_cache = 0; 1617 size_t count_in_cache = 0;
1411 size_t total_visits = 0; 1618 size_t total_visits = 0;
1412 for (const std::pair<std::string, int>& top_host : top_hosts) { 1619 for (const std::pair<std::string, int>& top_host : top_hosts) {
1413 const std::string& host = top_host.first; 1620 const std::string& host = top_host.first;
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
1512 TestObserver::~TestObserver() { 1719 TestObserver::~TestObserver() {
1513 predictor_->SetObserverForTesting(nullptr); 1720 predictor_->SetObserverForTesting(nullptr);
1514 } 1721 }
1515 1722
1516 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) 1723 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor)
1517 : predictor_(predictor) { 1724 : predictor_(predictor) {
1518 predictor_->SetObserverForTesting(this); 1725 predictor_->SetObserverForTesting(this);
1519 } 1726 }
1520 1727
1521 } // namespace predictors 1728 } // namespace predictors
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698