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

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

Issue 2796783004: predictors: Add origin learning. (Closed)
Patch Set: . 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 bool is_redirect) {
74 const GURL& resource_url = request_summary.resource_url;
75 const GURL& redirected_url = request_summary.redirect_url;
76 bool is_redirected = !redirected_url.is_empty();
77 bool valid_urls =
78 resource_url.is_valid() && (!is_redirected || redirected_url.is_valid());
79
80 DCHECK(valid_urls);
81 if (!valid_urls)
82 return;
83
84 // If the response is a redirect, then add the original origin, otherwise
85 // the redirected one. Note that this makes the predictor imprecise when
86 // a request goes through multiple redirects, as this will update the
87 // summary of the starting point of the redirect chain only.
88 GURL origin = is_redirect ? resource_url.GetOrigin()
89 : (is_redirected ? redirected_url.GetOrigin()
90 : resource_url.GetOrigin());
91 auto it = summaries->find(origin);
92 if (it == summaries->end()) {
93 ResourcePrefetchPredictor::OriginRequestSummary summary;
94 summary.origin = origin;
95 summary.first_occurrence = summaries->size();
96 it = summaries->insert({origin, summary}).first;
97 }
98
99 it->second.always_access_network |=
100 request_summary.always_revalidate || request_summary.is_no_store;
101 it->second.accessed_network |= request_summary.network_accessed;
102 }
103
104 void InitializeOriginStatFromOriginRequestSummary(
105 OriginStat* origin,
106 const ResourcePrefetchPredictor::OriginRequestSummary& summary) {
107 origin->set_origin(summary.origin.spec());
108 origin->set_number_of_hits(1);
109 origin->set_average_position(summary.first_occurrence + 1);
110 origin->set_always_access_network(summary.always_access_network);
111 origin->set_accessed_network(summary.accessed_network);
112 }
113
70 // Used to fetch the visit count for a URL from the History database. 114 // Used to fetch the visit count for a URL from the History database.
71 class GetUrlVisitCountTask : public history::HistoryDBTask { 115 class GetUrlVisitCountTask : public history::HistoryDBTask {
72 public: 116 public:
73 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary; 117 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary;
74 using PageRequestSummary = ResourcePrefetchPredictor::PageRequestSummary; 118 using PageRequestSummary = ResourcePrefetchPredictor::PageRequestSummary;
75 typedef base::Callback<void(size_t, // URL visit count. 119 typedef base::Callback<void(size_t, // URL visit count.
76 const PageRequestSummary&)> 120 const PageRequestSummary&)>
77 VisitInfoCallback; 121 VisitInfoCallback;
78 122
79 GetUrlVisitCountTask(std::unique_ptr<PageRequestSummary> summary, 123 GetUrlVisitCountTask(std::unique_ptr<PageRequestSummary> summary,
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 315
272 content::ResourceType resource_type = request_info->GetResourceType(); 316 content::ResourceType resource_type = request_info->GetResourceType();
273 return resource_type == content::RESOURCE_TYPE_MAIN_FRAME 317 return resource_type == content::RESOURCE_TYPE_MAIN_FRAME
274 ? IsHandledMainPage(response) 318 ? IsHandledMainPage(response)
275 : IsHandledSubresource(response, resource_type); 319 : IsHandledSubresource(response, resource_type);
276 } 320 }
277 321
278 // static 322 // static
279 bool ResourcePrefetchPredictor::ShouldRecordRedirect( 323 bool ResourcePrefetchPredictor::ShouldRecordRedirect(
280 net::URLRequest* response) { 324 net::URLRequest* response) {
281 const content::ResourceRequestInfo* request_info = 325 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 } 326 }
292 327
293 // static 328 // static
294 bool ResourcePrefetchPredictor::IsHandledMainPage(net::URLRequest* request) { 329 bool ResourcePrefetchPredictor::IsHandledMainPage(net::URLRequest* request) {
295 const GURL& url = request->url(); 330 const GURL& url = request->url();
296 bool bad_port = !g_allow_port_in_urls && url.has_port(); 331 bool bad_port = !g_allow_port_in_urls && url.has_port();
297 return url.SchemeIsHTTPOrHTTPS() && !bad_port; 332 return url.SchemeIsHTTPOrHTTPS() && !bad_port;
298 } 333 }
299 334
300 // static 335 // static
(...skipping 13 matching lines...) Expand all
314 return false; 349 return false;
315 350
316 if (response->method() != "GET") 351 if (response->method() != "GET")
317 return false; 352 return false;
318 353
319 if (response->original_url().spec().length() > 354 if (response->original_url().spec().length() >
320 ResourcePrefetchPredictorTables::kMaxStringLength) { 355 ResourcePrefetchPredictorTables::kMaxStringLength) {
321 return false; 356 return false;
322 } 357 }
323 358
324 if (!response->response_info().headers.get() || IsNoStore(response)) 359 if (!response->response_info().headers.get())
325 return false; 360 return false;
326 361
327 return true; 362 return true;
328 } 363 }
329 364
330 // static 365 // static
331 bool ResourcePrefetchPredictor::IsHandledResourceType( 366 bool ResourcePrefetchPredictor::IsHandledResourceType(
332 content::ResourceType resource_type, 367 content::ResourceType resource_type,
333 const std::string& mime_type) { 368 const std::string& mime_type) {
334 content::ResourceType actual_resource_type = 369 content::ResourceType actual_resource_type =
(...skipping 14 matching lines...) Expand all
349 if (resource_type == content::RESOURCE_TYPE_PREFETCH || 384 if (resource_type == content::RESOURCE_TYPE_PREFETCH ||
350 resource_type == content::RESOURCE_TYPE_SUB_RESOURCE || 385 resource_type == content::RESOURCE_TYPE_SUB_RESOURCE ||
351 resource_type == content::RESOURCE_TYPE_XHR) { 386 resource_type == content::RESOURCE_TYPE_XHR) {
352 return GetResourceTypeFromMimeType(mime_type, 387 return GetResourceTypeFromMimeType(mime_type,
353 content::RESOURCE_TYPE_LAST_TYPE); 388 content::RESOURCE_TYPE_LAST_TYPE);
354 } 389 }
355 return resource_type; 390 return resource_type;
356 } 391 }
357 392
358 // static 393 // static
359 bool ResourcePrefetchPredictor::IsNoStore(const net::URLRequest* response) { 394 bool ResourcePrefetchPredictor::IsNoStore(const net::URLRequest& response) {
360 if (response->was_cached()) 395 if (response.was_cached())
361 return false; 396 return false;
362 397
363 const net::HttpResponseInfo& response_info = response->response_info(); 398 const net::HttpResponseInfo& response_info = response.response_info();
364 if (!response_info.headers.get()) 399 if (!response_info.headers.get())
365 return false; 400 return false;
366 return response_info.headers->HasHeaderValue("cache-control", "no-store"); 401 return response_info.headers->HasHeaderValue("cache-control", "no-store");
367 } 402 }
368 403
369 // static 404 // static
370 content::ResourceType ResourcePrefetchPredictor::GetResourceTypeFromMimeType( 405 content::ResourceType ResourcePrefetchPredictor::GetResourceTypeFromMimeType(
371 const std::string& mime_type, 406 const std::string& mime_type,
372 content::ResourceType fallback) { 407 content::ResourceType fallback) {
373 if (mime_type.empty()) { 408 if (mime_type.empty()) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 } 458 }
424 459
425 // static 460 // static
426 void ResourcePrefetchPredictor::SetAllowPortInUrlsForTesting(bool state) { 461 void ResourcePrefetchPredictor::SetAllowPortInUrlsForTesting(bool state) {
427 g_allow_port_in_urls = state; 462 g_allow_port_in_urls = state;
428 } 463 }
429 464
430 //////////////////////////////////////////////////////////////////////////////// 465 ////////////////////////////////////////////////////////////////////////////////
431 // ResourcePrefetchPredictor nested types. 466 // ResourcePrefetchPredictor nested types.
432 467
468 ResourcePrefetchPredictor::OriginRequestSummary::OriginRequestSummary()
469 : origin(),
470 always_access_network(false),
471 accessed_network(false),
472 first_occurrence(0) {}
473
474 ResourcePrefetchPredictor::OriginRequestSummary::OriginRequestSummary(
475 const OriginRequestSummary& other) = default;
476
477 ResourcePrefetchPredictor::OriginRequestSummary::~OriginRequestSummary() {}
478
433 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary() 479 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary()
434 : resource_type(content::RESOURCE_TYPE_LAST_TYPE), 480 : resource_type(content::RESOURCE_TYPE_LAST_TYPE),
435 priority(net::IDLE), 481 priority(net::IDLE),
436 was_cached(false), 482 was_cached(false),
437 has_validators(false), 483 has_validators(false),
438 always_revalidate(false) {} 484 always_revalidate(false),
485 is_no_store(false),
486 network_accessed(false) {}
439 487
440 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary( 488 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary(
441 const URLRequestSummary& other) 489 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 490
452 ResourcePrefetchPredictor::URLRequestSummary::~URLRequestSummary() { 491 ResourcePrefetchPredictor::URLRequestSummary::~URLRequestSummary() {
453 } 492 }
454 493
455 // static 494 // static
456 bool ResourcePrefetchPredictor::URLRequestSummary::SummarizeResponse( 495 bool ResourcePrefetchPredictor::URLRequestSummary::SummarizeResponse(
457 const net::URLRequest& request, 496 const net::URLRequest& request,
458 URLRequestSummary* summary) { 497 URLRequestSummary* summary) {
459 const content::ResourceRequestInfo* request_info = 498 const content::ResourceRequestInfo* request_info =
460 content::ResourceRequestInfo::ForRequest(&request); 499 content::ResourceRequestInfo::ForRequest(&request);
461 if (!request_info) 500 if (!request_info)
462 return false; 501 return false;
463 502
464 summary->resource_url = request.original_url(); 503 summary->resource_url = request.original_url();
504 if (request.url_chain().size() > 1)
alexilin 2017/04/12 08:21:45 I'd prefer just to add a new `request_url` field t
Benoit L 2017/04/12 12:32:40 Done.
505 summary->redirect_url = request.url();
465 content::ResourceType resource_type_from_request = 506 content::ResourceType resource_type_from_request =
466 request_info->GetResourceType(); 507 request_info->GetResourceType();
467 summary->priority = request.priority(); 508 summary->priority = request.priority();
468 request.GetMimeType(&summary->mime_type); 509 request.GetMimeType(&summary->mime_type);
469 summary->was_cached = request.was_cached(); 510 summary->was_cached = request.was_cached();
470 summary->resource_type = 511 summary->resource_type =
471 GetResourceType(resource_type_from_request, summary->mime_type); 512 GetResourceType(resource_type_from_request, summary->mime_type);
472 513
473 scoped_refptr<net::HttpResponseHeaders> headers = 514 scoped_refptr<net::HttpResponseHeaders> headers =
474 request.response_info().headers; 515 request.response_info().headers;
475 if (headers.get()) { 516 if (headers.get()) {
476 summary->has_validators = headers->HasValidators(); 517 summary->has_validators = headers->HasValidators();
477 // RFC 2616, section 14.9. 518 // RFC 2616, section 14.9.
478 summary->always_revalidate = 519 summary->always_revalidate =
479 headers->HasHeaderValue("cache-control", "no-cache") || 520 headers->HasHeaderValue("cache-control", "no-cache") ||
480 headers->HasHeaderValue("pragma", "no-cache") || 521 headers->HasHeaderValue("pragma", "no-cache") ||
481 headers->HasHeaderValue("vary", "*"); 522 headers->HasHeaderValue("vary", "*");
523 summary->is_no_store = IsNoStore(request);
482 } 524 }
525 summary->network_accessed = request.response_info().network_accessed;
483 return true; 526 return true;
484 } 527 }
485 528
486 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary( 529 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary(
487 const GURL& i_main_frame_url) 530 const GURL& i_main_frame_url)
488 : main_frame_url(i_main_frame_url), initial_url(i_main_frame_url) {} 531 : main_frame_url(i_main_frame_url), initial_url(i_main_frame_url) {}
489 532
490 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary( 533 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary(
491 const PageRequestSummary& other) = default; 534 const PageRequestSummary& other) = default;
492 535
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 if (initialization_state_ != NOT_INITIALIZED) 570 if (initialization_state_ != NOT_INITIALIZED)
528 return; 571 return;
529 initialization_state_ = INITIALIZING; 572 initialization_state_ = INITIALIZING;
530 573
531 // Create local caches using the database as loaded. 574 // Create local caches using the database as loaded.
532 auto url_data_map = base::MakeUnique<PrefetchDataMap>(); 575 auto url_data_map = base::MakeUnique<PrefetchDataMap>();
533 auto host_data_map = base::MakeUnique<PrefetchDataMap>(); 576 auto host_data_map = base::MakeUnique<PrefetchDataMap>();
534 auto url_redirect_data_map = base::MakeUnique<RedirectDataMap>(); 577 auto url_redirect_data_map = base::MakeUnique<RedirectDataMap>();
535 auto host_redirect_data_map = base::MakeUnique<RedirectDataMap>(); 578 auto host_redirect_data_map = base::MakeUnique<RedirectDataMap>();
536 auto manifest_data_map = base::MakeUnique<ManifestDataMap>(); 579 auto manifest_data_map = base::MakeUnique<ManifestDataMap>();
580 auto origin_data_map = base::MakeUnique<OriginDataMap>();
537 581
538 // Get raw pointers to pass to the first task. Ownership of the unique_ptrs 582 // Get raw pointers to pass to the first task. Ownership of the unique_ptrs
539 // will be passed to the reply task. 583 // will be passed to the reply task.
540 auto* url_data_map_ptr = url_data_map.get(); 584 auto* url_data_map_ptr = url_data_map.get();
541 auto* host_data_map_ptr = host_data_map.get(); 585 auto* host_data_map_ptr = host_data_map.get();
542 auto* url_redirect_data_map_ptr = url_redirect_data_map.get(); 586 auto* url_redirect_data_map_ptr = url_redirect_data_map.get();
543 auto* host_redirect_data_map_ptr = host_redirect_data_map.get(); 587 auto* host_redirect_data_map_ptr = host_redirect_data_map.get();
544 auto* manifest_data_map_ptr = manifest_data_map.get(); 588 auto* manifest_data_map_ptr = manifest_data_map.get();
589 auto* origin_data_map_ptr = origin_data_map.get();
545 590
546 BrowserThread::PostTaskAndReply( 591 BrowserThread::PostTaskAndReply(
547 BrowserThread::DB, FROM_HERE, 592 BrowserThread::DB, FROM_HERE,
548 base::Bind(&ResourcePrefetchPredictorTables::GetAllData, tables_, 593 base::Bind(&ResourcePrefetchPredictorTables::GetAllData, tables_,
549 url_data_map_ptr, host_data_map_ptr, url_redirect_data_map_ptr, 594 url_data_map_ptr, host_data_map_ptr, url_redirect_data_map_ptr,
550 host_redirect_data_map_ptr, manifest_data_map_ptr), 595 host_redirect_data_map_ptr, manifest_data_map_ptr,
596 origin_data_map_ptr),
551 base::Bind(&ResourcePrefetchPredictor::CreateCaches, AsWeakPtr(), 597 base::Bind(&ResourcePrefetchPredictor::CreateCaches, AsWeakPtr(),
552 base::Passed(&url_data_map), base::Passed(&host_data_map), 598 base::Passed(&url_data_map), base::Passed(&host_data_map),
553 base::Passed(&url_redirect_data_map), 599 base::Passed(&url_redirect_data_map),
554 base::Passed(&host_redirect_data_map), 600 base::Passed(&host_redirect_data_map),
555 base::Passed(&manifest_data_map))); 601 base::Passed(&manifest_data_map),
602 base::Passed(&origin_data_map)));
556 } 603 }
557 604
558 void ResourcePrefetchPredictor::RecordURLRequest( 605 void ResourcePrefetchPredictor::RecordURLRequest(
559 const URLRequestSummary& request) { 606 const URLRequestSummary& request) {
560 DCHECK_CURRENTLY_ON(BrowserThread::UI); 607 DCHECK_CURRENTLY_ON(BrowserThread::UI);
561 if (initialization_state_ != INITIALIZED) 608 if (initialization_state_ != INITIALIZED)
562 return; 609 return;
563 610
564 CHECK_EQ(request.resource_type, content::RESOURCE_TYPE_MAIN_FRAME); 611 CHECK_EQ(request.resource_type, content::RESOURCE_TYPE_MAIN_FRAME);
565 OnMainFrameRequest(request); 612 OnMainFrameRequest(request);
(...skipping 10 matching lines...) Expand all
576 else 623 else
577 OnSubresourceResponse(response); 624 OnSubresourceResponse(response);
578 } 625 }
579 626
580 void ResourcePrefetchPredictor::RecordURLRedirect( 627 void ResourcePrefetchPredictor::RecordURLRedirect(
581 const URLRequestSummary& response) { 628 const URLRequestSummary& response) {
582 DCHECK_CURRENTLY_ON(BrowserThread::UI); 629 DCHECK_CURRENTLY_ON(BrowserThread::UI);
583 if (initialization_state_ != INITIALIZED) 630 if (initialization_state_ != INITIALIZED)
584 return; 631 return;
585 632
586 CHECK_EQ(response.resource_type, content::RESOURCE_TYPE_MAIN_FRAME); 633 if (response.resource_type == content::RESOURCE_TYPE_MAIN_FRAME)
587 OnMainFrameRedirect(response); 634 OnMainFrameRedirect(response);
635 else
636 OnSubresourceRedirect(response);
588 } 637 }
589 638
590 void ResourcePrefetchPredictor::RecordMainFrameLoadComplete( 639 void ResourcePrefetchPredictor::RecordMainFrameLoadComplete(
591 const NavigationID& navigation_id) { 640 const NavigationID& navigation_id) {
592 switch (initialization_state_) { 641 switch (initialization_state_) {
593 case NOT_INITIALIZED: 642 case NOT_INITIALIZED:
594 StartInitialization(); 643 StartInitialization();
595 break; 644 break;
596 case INITIALIZING: 645 case INITIALIZING:
597 break; 646 break;
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
757 inflight_navigations_.insert( 806 inflight_navigations_.insert(
758 std::make_pair(navigation_id, std::move(summary))); 807 std::make_pair(navigation_id, std::move(summary)));
759 } 808 }
760 809
761 void ResourcePrefetchPredictor::OnSubresourceResponse( 810 void ResourcePrefetchPredictor::OnSubresourceResponse(
762 const URLRequestSummary& response) { 811 const URLRequestSummary& response) {
763 DCHECK_CURRENTLY_ON(BrowserThread::UI); 812 DCHECK_CURRENTLY_ON(BrowserThread::UI);
764 DCHECK_EQ(INITIALIZED, initialization_state_); 813 DCHECK_EQ(INITIALIZED, initialization_state_);
765 814
766 NavigationMap::const_iterator nav_it = 815 NavigationMap::const_iterator nav_it =
767 inflight_navigations_.find(response.navigation_id); 816 inflight_navigations_.find(response.navigation_id);
768 if (nav_it == inflight_navigations_.end()) { 817 if (nav_it == inflight_navigations_.end())
769 return; 818 return;
770 } 819 auto& page_request_summary = *nav_it->second;
771 820
772 nav_it->second->subresource_requests.push_back(response); 821 if (!response.is_no_store)
822 page_request_summary.subresource_requests.push_back(response);
823
824 if (config_.is_origin_prediction_enabled)
825 UpdateOrAddToOrigins(&page_request_summary.origins, response, false);
826 }
827
828 void ResourcePrefetchPredictor::OnSubresourceRedirect(
829 const URLRequestSummary& response) {
830 DCHECK_CURRENTLY_ON(BrowserThread::UI);
831 DCHECK_EQ(INITIALIZED, initialization_state_);
832
833 if (!config_.is_origin_prediction_enabled)
834 return;
835
836 NavigationMap::const_iterator nav_it =
837 inflight_navigations_.find(response.navigation_id);
838 if (nav_it == inflight_navigations_.end())
839 return;
840 auto& page_request_summary = *nav_it->second;
841 UpdateOrAddToOrigins(&page_request_summary.origins, response, true);
773 } 842 }
774 843
775 void ResourcePrefetchPredictor::OnNavigationComplete( 844 void ResourcePrefetchPredictor::OnNavigationComplete(
776 const NavigationID& nav_id_without_timing_info) { 845 const NavigationID& nav_id_without_timing_info) {
777 DCHECK_CURRENTLY_ON(BrowserThread::UI); 846 DCHECK_CURRENTLY_ON(BrowserThread::UI);
778 DCHECK_EQ(INITIALIZED, initialization_state_); 847 DCHECK_EQ(INITIALIZED, initialization_state_);
779 848
780 NavigationMap::iterator nav_it = 849 NavigationMap::iterator nav_it =
781 inflight_navigations_.find(nav_id_without_timing_info); 850 inflight_navigations_.find(nav_id_without_timing_info);
782 if (nav_it == inflight_navigations_.end()) 851 if (nav_it == inflight_navigations_.end())
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
896 } 965 }
897 966
898 return has_prefetchable_resource; 967 return has_prefetchable_resource;
899 } 968 }
900 969
901 void ResourcePrefetchPredictor::CreateCaches( 970 void ResourcePrefetchPredictor::CreateCaches(
902 std::unique_ptr<PrefetchDataMap> url_data_map, 971 std::unique_ptr<PrefetchDataMap> url_data_map,
903 std::unique_ptr<PrefetchDataMap> host_data_map, 972 std::unique_ptr<PrefetchDataMap> host_data_map,
904 std::unique_ptr<RedirectDataMap> url_redirect_data_map, 973 std::unique_ptr<RedirectDataMap> url_redirect_data_map,
905 std::unique_ptr<RedirectDataMap> host_redirect_data_map, 974 std::unique_ptr<RedirectDataMap> host_redirect_data_map,
906 std::unique_ptr<ManifestDataMap> manifest_data_map) { 975 std::unique_ptr<ManifestDataMap> manifest_data_map,
976 std::unique_ptr<OriginDataMap> origin_data_map) {
907 DCHECK_CURRENTLY_ON(BrowserThread::UI); 977 DCHECK_CURRENTLY_ON(BrowserThread::UI);
908 978
909 DCHECK_EQ(INITIALIZING, initialization_state_); 979 DCHECK_EQ(INITIALIZING, initialization_state_);
910 DCHECK(!url_table_cache_); 980 DCHECK(!url_table_cache_);
911 DCHECK(!host_table_cache_); 981 DCHECK(!host_table_cache_);
912 DCHECK(!url_redirect_table_cache_); 982 DCHECK(!url_redirect_table_cache_);
913 DCHECK(!host_redirect_table_cache_); 983 DCHECK(!host_redirect_table_cache_);
914 DCHECK(!manifest_table_cache_); 984 DCHECK(!manifest_table_cache_);
985 DCHECK(!origin_table_cache_);
986
915 DCHECK(inflight_navigations_.empty()); 987 DCHECK(inflight_navigations_.empty());
916 988
917 url_table_cache_ = std::move(url_data_map); 989 url_table_cache_ = std::move(url_data_map);
918 host_table_cache_ = std::move(host_data_map); 990 host_table_cache_ = std::move(host_data_map);
919 url_redirect_table_cache_ = std::move(url_redirect_data_map); 991 url_redirect_table_cache_ = std::move(url_redirect_data_map);
920 host_redirect_table_cache_ = std::move(host_redirect_data_map); 992 host_redirect_table_cache_ = std::move(host_redirect_data_map);
921 manifest_table_cache_ = std::move(manifest_data_map); 993 manifest_table_cache_ = std::move(manifest_data_map);
994 origin_table_cache_ = std::move(origin_data_map);
922 995
923 ConnectToHistoryService(); 996 ConnectToHistoryService();
924 } 997 }
925 998
926 void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() { 999 void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() {
927 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1000 DCHECK_CURRENTLY_ON(BrowserThread::UI);
928 DCHECK_EQ(INITIALIZING, initialization_state_); 1001 DCHECK_EQ(INITIALIZING, initialization_state_);
929 1002
930 // Initialize the prefetch manager only if prefetching is enabled. 1003 // Initialize the prefetch manager only if prefetching is enabled.
931 if (config_.IsPrefetchingEnabledForSomeOrigin(profile_)) { 1004 if (config_.IsPrefetchingEnabledForSomeOrigin(profile_)) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
982 } 1055 }
983 } 1056 }
984 1057
985 void ResourcePrefetchPredictor::DeleteAllUrls() { 1058 void ResourcePrefetchPredictor::DeleteAllUrls() {
986 inflight_navigations_.clear(); 1059 inflight_navigations_.clear();
987 url_table_cache_->clear(); 1060 url_table_cache_->clear();
988 host_table_cache_->clear(); 1061 host_table_cache_->clear();
989 url_redirect_table_cache_->clear(); 1062 url_redirect_table_cache_->clear();
990 host_redirect_table_cache_->clear(); 1063 host_redirect_table_cache_->clear();
991 manifest_table_cache_->clear(); 1064 manifest_table_cache_->clear();
1065 origin_table_cache_->clear();
992 1066
993 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, 1067 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
994 base::Bind(&ResourcePrefetchPredictorTables::DeleteAllData, tables_)); 1068 base::Bind(&ResourcePrefetchPredictorTables::DeleteAllData, tables_));
995 } 1069 }
996 1070
997 void ResourcePrefetchPredictor::DeleteUrls(const history::URLRows& urls) { 1071 void ResourcePrefetchPredictor::DeleteUrls(const history::URLRows& urls) {
998 // Check all the urls in the database and pick out the ones that are present 1072 // Check all the urls in the database and pick out the ones that are present
999 // in the cache. 1073 // in the cache.
1000 std::vector<std::string> urls_to_delete, hosts_to_delete; 1074 std::vector<std::string> urls_to_delete, hosts_to_delete;
1001 std::vector<std::string> url_redirects_to_delete, host_redirects_to_delete; 1075 std::vector<std::string> url_redirects_to_delete, host_redirects_to_delete;
1002 std::vector<std::string> manifest_hosts_to_delete; 1076 std::vector<std::string> manifest_hosts_to_delete;
1077 std::vector<std::string> origin_hosts_to_delete;
1003 1078
1004 for (const auto& it : urls) { 1079 for (const auto& it : urls) {
1005 const std::string& url_spec = it.url().spec(); 1080 const std::string& url_spec = it.url().spec();
1006 if (url_table_cache_->find(url_spec) != url_table_cache_->end()) { 1081 if (url_table_cache_->find(url_spec) != url_table_cache_->end()) {
1007 urls_to_delete.push_back(url_spec); 1082 urls_to_delete.push_back(url_spec);
1008 url_table_cache_->erase(url_spec); 1083 url_table_cache_->erase(url_spec);
1009 } 1084 }
1010 1085
1011 if (url_redirect_table_cache_->find(url_spec) != 1086 if (url_redirect_table_cache_->find(url_spec) !=
1012 url_redirect_table_cache_->end()) { 1087 url_redirect_table_cache_->end()) {
(...skipping 12 matching lines...) Expand all
1025 host_redirects_to_delete.push_back(host); 1100 host_redirects_to_delete.push_back(host);
1026 host_redirect_table_cache_->erase(host); 1101 host_redirect_table_cache_->erase(host);
1027 } 1102 }
1028 1103
1029 std::string manifest_host = history::HostForTopHosts(it.url()); 1104 std::string manifest_host = history::HostForTopHosts(it.url());
1030 if (manifest_table_cache_->find(manifest_host) != 1105 if (manifest_table_cache_->find(manifest_host) !=
1031 manifest_table_cache_->end()) { 1106 manifest_table_cache_->end()) {
1032 manifest_hosts_to_delete.push_back(manifest_host); 1107 manifest_hosts_to_delete.push_back(manifest_host);
1033 manifest_table_cache_->erase(manifest_host); 1108 manifest_table_cache_->erase(manifest_host);
1034 } 1109 }
1110
1111 if (origin_table_cache_->find(host) != origin_table_cache_->end()) {
1112 origin_hosts_to_delete.push_back(host);
1113 origin_table_cache_->erase(host);
1114 }
1035 } 1115 }
1036 1116
1037 if (!urls_to_delete.empty() || !hosts_to_delete.empty()) { 1117 if (!urls_to_delete.empty() || !hosts_to_delete.empty()) {
1038 BrowserThread::PostTask( 1118 BrowserThread::PostTask(
1039 BrowserThread::DB, FROM_HERE, 1119 BrowserThread::DB, FROM_HERE,
1040 base::Bind(&ResourcePrefetchPredictorTables::DeleteResourceData, 1120 base::Bind(&ResourcePrefetchPredictorTables::DeleteResourceData,
1041 tables_, urls_to_delete, hosts_to_delete)); 1121 tables_, urls_to_delete, hosts_to_delete));
1042 } 1122 }
1043 1123
1044 if (!url_redirects_to_delete.empty() || !host_redirects_to_delete.empty()) { 1124 if (!url_redirects_to_delete.empty() || !host_redirects_to_delete.empty()) {
1045 BrowserThread::PostTask( 1125 BrowserThread::PostTask(
1046 BrowserThread::DB, FROM_HERE, 1126 BrowserThread::DB, FROM_HERE,
1047 base::Bind(&ResourcePrefetchPredictorTables::DeleteRedirectData, 1127 base::Bind(&ResourcePrefetchPredictorTables::DeleteRedirectData,
1048 tables_, url_redirects_to_delete, host_redirects_to_delete)); 1128 tables_, url_redirects_to_delete, host_redirects_to_delete));
1049 } 1129 }
1050 1130
1051 if (!manifest_hosts_to_delete.empty()) { 1131 if (!manifest_hosts_to_delete.empty()) {
1052 BrowserThread::PostTask( 1132 BrowserThread::PostTask(
1053 BrowserThread::DB, FROM_HERE, 1133 BrowserThread::DB, FROM_HERE,
1054 base::Bind(&ResourcePrefetchPredictorTables::DeleteManifestData, 1134 base::Bind(&ResourcePrefetchPredictorTables::DeleteManifestData,
1055 tables_, manifest_hosts_to_delete)); 1135 tables_, manifest_hosts_to_delete));
1056 } 1136 }
1137
1138 if (!origin_hosts_to_delete.empty()) {
1139 BrowserThread::PostTask(
1140 BrowserThread::DB, FROM_HERE,
1141 base::Bind(&ResourcePrefetchPredictorTables::DeleteOriginData, tables_,
1142 origin_hosts_to_delete));
1143 }
1057 } 1144 }
1058 1145
1059 void ResourcePrefetchPredictor::RemoveOldestEntryInPrefetchDataMap( 1146 void ResourcePrefetchPredictor::RemoveOldestEntryInPrefetchDataMap(
1060 PrefetchKeyType key_type, 1147 PrefetchKeyType key_type,
1061 PrefetchDataMap* data_map) { 1148 PrefetchDataMap* data_map) {
1062 if (data_map->empty()) 1149 if (data_map->empty())
1063 return; 1150 return;
1064 1151
1065 uint64_t oldest_time = UINT64_MAX; 1152 uint64_t oldest_time = UINT64_MAX;
1066 std::string key_to_delete; 1153 std::string key_to_delete;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1117 }); 1204 });
1118 1205
1119 std::string key_to_delete = oldest_entry->first; 1206 std::string key_to_delete = oldest_entry->first;
1120 data_map->erase(oldest_entry); 1207 data_map->erase(oldest_entry);
1121 BrowserThread::PostTask( 1208 BrowserThread::PostTask(
1122 BrowserThread::DB, FROM_HERE, 1209 BrowserThread::DB, FROM_HERE,
1123 base::Bind(&ResourcePrefetchPredictorTables::DeleteManifestData, tables_, 1210 base::Bind(&ResourcePrefetchPredictorTables::DeleteManifestData, tables_,
1124 std::vector<std::string>({key_to_delete}))); 1211 std::vector<std::string>({key_to_delete})));
1125 } 1212 }
1126 1213
1214 void ResourcePrefetchPredictor::RemoveOldestEntryInOriginDataMap(
1215 OriginDataMap* data_map) {
1216 if (data_map->empty())
1217 return;
1218
1219 uint64_t oldest_time = UINT64_MAX;
1220 std::string key_to_delete;
1221 for (const auto& kv : *data_map) {
1222 const OriginData& data = kv.second;
1223 if (key_to_delete.empty() || data.last_visit_time() < oldest_time) {
1224 key_to_delete = kv.first;
1225 oldest_time = data.last_visit_time();
1226 }
1227 }
1228
1229 data_map->erase(key_to_delete);
1230 BrowserThread::PostTask(
1231 BrowserThread::DB, FROM_HERE,
1232 base::Bind(&ResourcePrefetchPredictorTables::DeleteOriginData, tables_,
1233 std::vector<std::string>({key_to_delete})));
1234 }
1235
1127 void ResourcePrefetchPredictor::OnVisitCountLookup( 1236 void ResourcePrefetchPredictor::OnVisitCountLookup(
1128 size_t url_visit_count, 1237 size_t url_visit_count,
1129 const PageRequestSummary& summary) { 1238 const PageRequestSummary& summary) {
1130 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1239 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1131 1240
1132 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HistoryVisitCountForUrl", 1241 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HistoryVisitCountForUrl",
1133 url_visit_count); 1242 url_visit_count);
1134 1243
1135 // TODO(alexilin): make only one request to DB thread. 1244 // TODO(alexilin): make only one request to DB thread.
1136 1245
(...skipping 13 matching lines...) Expand all
1150 url_redirect_table_cache_.get()); 1259 url_redirect_table_cache_.get());
1151 } 1260 }
1152 } 1261 }
1153 1262
1154 // Host level data - no cutoff, always learn the navigation if enabled. 1263 // Host level data - no cutoff, always learn the navigation if enabled.
1155 const std::string host = summary.main_frame_url.host(); 1264 const std::string host = summary.main_frame_url.host();
1156 LearnNavigation(host, PREFETCH_KEY_TYPE_HOST, summary.subresource_requests, 1265 LearnNavigation(host, PREFETCH_KEY_TYPE_HOST, summary.subresource_requests,
1157 config_.max_hosts_to_track, host_table_cache_.get(), 1266 config_.max_hosts_to_track, host_table_cache_.get(),
1158 summary.initial_url.host(), host_redirect_table_cache_.get()); 1267 summary.initial_url.host(), host_redirect_table_cache_.get());
1159 1268
1269 if (config_.is_origin_prediction_enabled) {
1270 LearnOrigins(host, summary.origins, config_.max_hosts_to_track,
1271 origin_table_cache_.get());
1272 }
1273
1160 if (observer_) 1274 if (observer_)
1161 observer_->OnNavigationLearned(url_visit_count, summary); 1275 observer_->OnNavigationLearned(url_visit_count, summary);
1162 } 1276 }
1163 1277
1164 void ResourcePrefetchPredictor::LearnNavigation( 1278 void ResourcePrefetchPredictor::LearnNavigation(
1165 const std::string& key, 1279 const std::string& key,
1166 PrefetchKeyType key_type, 1280 PrefetchKeyType key_type,
1167 const std::vector<URLRequestSummary>& new_resources, 1281 const std::vector<URLRequestSummary>& new_resources,
1168 size_t max_data_map_size, 1282 size_t max_data_map_size,
1169 PrefetchDataMap* data_map, 1283 PrefetchDataMap* data_map,
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
1394 const RedirectData& url_redirect_data = 1508 const RedirectData& url_redirect_data =
1395 is_host ? empty_redirect_data : data; 1509 is_host ? empty_redirect_data : data;
1396 BrowserThread::PostTask( 1510 BrowserThread::PostTask(
1397 BrowserThread::DB, FROM_HERE, 1511 BrowserThread::DB, FROM_HERE,
1398 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, tables_, 1512 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, tables_,
1399 empty_data, empty_data, url_redirect_data, 1513 empty_data, empty_data, url_redirect_data,
1400 host_redirect_data)); 1514 host_redirect_data));
1401 } 1515 }
1402 } 1516 }
1403 1517
1518 void ResourcePrefetchPredictor::LearnOrigins(
1519 const std::string& host,
1520 const std::map<GURL, OriginRequestSummary>& summaries,
1521 size_t max_data_map_size,
1522 OriginDataMap* data_map) {
1523 if (host.size() > ResourcePrefetchPredictorTables::kMaxStringLength)
1524 return;
1525
1526 auto cache_entry = data_map->find(host);
1527 bool new_entry = cache_entry == data_map->end();
1528 if (new_entry) {
1529 if (data_map->size() >= max_data_map_size)
1530 RemoveOldestEntryInOriginDataMap(data_map);
1531
1532 cache_entry = data_map->insert({host, OriginData()}).first;
1533 OriginData& data = cache_entry->second;
1534 data.set_host(host);
1535 data.set_last_visit_time(base::Time::Now().ToInternalValue());
1536 size_t origins_size = summaries.size();
1537 auto ordered_origins =
1538 std::vector<const OriginRequestSummary*>(origins_size);
1539 for (const auto& kv : summaries) {
1540 size_t index = kv.second.first_occurrence;
1541 DCHECK_LT(index, origins_size);
1542 ordered_origins[index] = &kv.second;
1543 }
1544
1545 for (const OriginRequestSummary* summary : ordered_origins) {
1546 auto* origin_to_add = data.add_origins();
1547 InitializeOriginStatFromOriginRequestSummary(origin_to_add, *summary);
1548 }
1549 } else {
1550 auto& data = cache_entry->second;
1551 data.set_last_visit_time(base::Time::Now().ToInternalValue());
1552
1553 std::map<GURL, int> old_index;
1554 int old_size = static_cast<int>(data.origins_size());
1555 for (int i = 0; i < old_size; ++i) {
1556 bool is_new =
1557 old_index.insert({GURL(data.origins(i).origin()), i}).second;
1558 DCHECK(is_new);
1559 }
1560
1561 // Update the old origins.
1562 for (int i = 0; i < old_size; ++i) {
1563 auto* old_origin = data.mutable_origins(i);
1564 GURL origin(old_origin->origin());
1565 auto it = summaries.find(origin);
1566 if (it == summaries.end()) {
1567 // miss
1568 old_origin->set_number_of_misses(old_origin->number_of_misses() + 1);
1569 old_origin->set_consecutive_misses(old_origin->consecutive_misses() +
1570 1);
1571 } else {
1572 // hit: update.
1573 const auto& new_origin = it->second;
1574 old_origin->set_always_access_network(new_origin.always_access_network);
1575 old_origin->set_accessed_network(new_origin.accessed_network);
1576
1577 int position = new_origin.first_occurrence + 1;
1578 int total =
1579 old_origin->number_of_hits() + old_origin->number_of_misses();
1580 old_origin->set_average_position(
1581 ((old_origin->average_position() * total) + position) /
1582 (total + 1));
1583 old_origin->set_number_of_hits(old_origin->number_of_hits() + 1);
1584 old_origin->set_consecutive_misses(0);
1585 }
1586 }
1587
1588 // Add new origins.
1589 for (const auto& kv : summaries) {
1590 if (old_index.find(kv.first) != old_index.end())
1591 continue;
1592
1593 auto* origin_to_add = data.add_origins();
1594 InitializeOriginStatFromOriginRequestSummary(origin_to_add, kv.second);
1595 }
1596 }
1597
1598 // Trim and Sort.
1599 auto& data = cache_entry->second;
1600 ResourcePrefetchPredictorTables::TrimOrigins(&data,
1601 config_.max_consecutive_misses);
1602 ResourcePrefetchPredictorTables::SortOrigins(&data);
1603 if (data.origins_size() > static_cast<int>(config_.max_resources_per_entry)) {
1604 data.mutable_origins()->DeleteSubrange(
1605 config_.max_origins_per_entry,
1606 data.origins_size() - config_.max_origins_per_entry);
1607 }
1608
1609 // Update the database.
1610 if (data.origins_size() == 0) {
1611 data_map->erase(cache_entry);
1612 if (!new_entry) {
1613 BrowserThread::PostTask(
1614 BrowserThread::DB, FROM_HERE,
1615 base::Bind(&ResourcePrefetchPredictorTables::DeleteOriginData,
1616 tables_, std::vector<std::string>({host})));
1617 }
1618 } else {
1619 BrowserThread::PostTask(
1620 BrowserThread::DB, FROM_HERE,
1621 base::Bind(&ResourcePrefetchPredictorTables::UpdateOriginData, tables_,
1622 data));
1623 }
1624 }
1625
1404 void ResourcePrefetchPredictor::ReportDatabaseReadiness( 1626 void ResourcePrefetchPredictor::ReportDatabaseReadiness(
1405 const history::TopHostsList& top_hosts) const { 1627 const history::TopHostsList& top_hosts) const {
1406 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1628 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1407 if (top_hosts.size() == 0) 1629 if (top_hosts.size() == 0)
1408 return; 1630 return;
1409 1631
1410 size_t count_in_cache = 0; 1632 size_t count_in_cache = 0;
1411 size_t total_visits = 0; 1633 size_t total_visits = 0;
1412 for (const std::pair<std::string, int>& top_host : top_hosts) { 1634 for (const std::pair<std::string, int>& top_host : top_hosts) {
1413 const std::string& host = top_host.first; 1635 const std::string& host = top_host.first;
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
1512 TestObserver::~TestObserver() { 1734 TestObserver::~TestObserver() {
1513 predictor_->SetObserverForTesting(nullptr); 1735 predictor_->SetObserverForTesting(nullptr);
1514 } 1736 }
1515 1737
1516 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) 1738 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor)
1517 : predictor_(predictor) { 1739 : predictor_(predictor) {
1518 predictor_->SetObserverForTesting(this); 1740 predictor_->SetObserverForTesting(this);
1519 } 1741 }
1520 1742
1521 } // namespace predictors 1743 } // namespace predictors
OLDNEW
« no previous file with comments | « chrome/browser/predictors/resource_prefetch_predictor.h ('k') | chrome/browser/predictors/resource_prefetch_predictor.proto » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698