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

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

Powered by Google App Engine
This is Rietveld 408576698