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

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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 REPORTING_EVENT_ALL_HISTORY_CLEARED = 0, 61 REPORTING_EVENT_ALL_HISTORY_CLEARED = 0,
62 REPORTING_EVENT_PARTIAL_HISTORY_CLEARED = 1, 62 REPORTING_EVENT_PARTIAL_HISTORY_CLEARED = 1,
63 REPORTING_EVENT_COUNT = 2 63 REPORTING_EVENT_COUNT = 2
64 }; 64 };
65 65
66 float ComputeRedirectConfidence(const predictors::RedirectStat& redirect) { 66 float ComputeRedirectConfidence(const predictors::RedirectStat& redirect) {
67 return (redirect.number_of_hits() + 0.0) / 67 return (redirect.number_of_hits() + 0.0) /
68 (redirect.number_of_hits() + redirect.number_of_misses()); 68 (redirect.number_of_hits() + redirect.number_of_misses());
69 } 69 }
70 70
71 void UpdateOrAddToOrigins(
72 std::map<GURL, ResourcePrefetchPredictor::OriginRequestSummary>* summaries,
73 const ResourcePrefetchPredictor::URLRequestSummary& request_summary) {
74 const GURL& request_url = request_summary.request_url;
75 DCHECK(request_url.is_valid());
76 if (!request_url.is_valid())
77 return;
78
79 GURL origin = request_url.GetOrigin();
80 auto it = summaries->find(origin);
81 if (it == summaries->end()) {
82 ResourcePrefetchPredictor::OriginRequestSummary summary;
83 summary.origin = origin;
84 summary.first_occurrence = summaries->size();
85 it = summaries->insert({origin, summary}).first;
86 }
87
88 it->second.always_access_network |=
89 request_summary.always_revalidate || request_summary.is_no_store;
90 it->second.accessed_network |= request_summary.network_accessed;
91 }
92
93 void InitializeOriginStatFromOriginRequestSummary(
94 OriginStat* origin,
95 const ResourcePrefetchPredictor::OriginRequestSummary& summary) {
96 origin->set_origin(summary.origin.spec());
97 origin->set_number_of_hits(1);
98 origin->set_average_position(summary.first_occurrence + 1);
99 origin->set_always_access_network(summary.always_access_network);
100 origin->set_accessed_network(summary.accessed_network);
101 }
102
71 // Used to fetch the visit count for a URL from the History database. 103 // Used to fetch the visit count for a URL from the History database.
72 class GetUrlVisitCountTask : public history::HistoryDBTask { 104 class GetUrlVisitCountTask : public history::HistoryDBTask {
73 public: 105 public:
74 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary; 106 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary;
75 using PageRequestSummary = ResourcePrefetchPredictor::PageRequestSummary; 107 using PageRequestSummary = ResourcePrefetchPredictor::PageRequestSummary;
76 typedef base::Callback<void(size_t, // URL visit count. 108 typedef base::Callback<void(size_t, // URL visit count.
77 const PageRequestSummary&)> 109 const PageRequestSummary&)>
78 VisitInfoCallback; 110 VisitInfoCallback;
79 111
80 GetUrlVisitCountTask(std::unique_ptr<PageRequestSummary> summary, 112 GetUrlVisitCountTask(std::unique_ptr<PageRequestSummary> summary,
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 288
257 content::ResourceType resource_type = request_info->GetResourceType(); 289 content::ResourceType resource_type = request_info->GetResourceType();
258 return resource_type == content::RESOURCE_TYPE_MAIN_FRAME 290 return resource_type == content::RESOURCE_TYPE_MAIN_FRAME
259 ? IsHandledMainPage(response) 291 ? IsHandledMainPage(response)
260 : IsHandledSubresource(response, resource_type); 292 : IsHandledSubresource(response, resource_type);
261 } 293 }
262 294
263 // static 295 // static
264 bool ResourcePrefetchPredictor::ShouldRecordRedirect( 296 bool ResourcePrefetchPredictor::ShouldRecordRedirect(
265 net::URLRequest* response) { 297 net::URLRequest* response) {
266 const content::ResourceRequestInfo* request_info = 298 return ShouldRecordResponse(response);
267 content::ResourceRequestInfo::ForRequest(response);
268 if (!request_info)
269 return false;
270
271 if (!request_info->IsMainFrame())
272 return false;
273
274 return request_info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME &&
275 IsHandledMainPage(response);
276 } 299 }
277 300
278 // static 301 // static
279 bool ResourcePrefetchPredictor::IsHandledMainPage(net::URLRequest* request) { 302 bool ResourcePrefetchPredictor::IsHandledMainPage(net::URLRequest* request) {
280 const GURL& url = request->url(); 303 const GURL& url = request->url();
281 bool bad_port = !g_allow_port_in_urls && url.has_port(); 304 bool bad_port = !g_allow_port_in_urls && url.has_port();
282 return url.SchemeIsHTTPOrHTTPS() && !bad_port; 305 return url.SchemeIsHTTPOrHTTPS() && !bad_port;
283 } 306 }
284 307
285 // static 308 // static
(...skipping 13 matching lines...) Expand all
299 return false; 322 return false;
300 323
301 if (response->method() != "GET") 324 if (response->method() != "GET")
302 return false; 325 return false;
303 326
304 if (response->original_url().spec().length() > 327 if (response->original_url().spec().length() >
305 ResourcePrefetchPredictorTables::kMaxStringLength) { 328 ResourcePrefetchPredictorTables::kMaxStringLength) {
306 return false; 329 return false;
307 } 330 }
308 331
309 if (!response->response_info().headers.get() || IsNoStore(response)) 332 if (!response->response_info().headers.get())
310 return false; 333 return false;
311 334
312 return true; 335 return true;
313 } 336 }
314 337
315 // static 338 // static
316 bool ResourcePrefetchPredictor::IsHandledResourceType( 339 bool ResourcePrefetchPredictor::IsHandledResourceType(
317 content::ResourceType resource_type, 340 content::ResourceType resource_type,
318 const std::string& mime_type) { 341 const std::string& mime_type) {
319 content::ResourceType actual_resource_type = 342 content::ResourceType actual_resource_type =
(...skipping 14 matching lines...) Expand all
334 if (resource_type == content::RESOURCE_TYPE_PREFETCH || 357 if (resource_type == content::RESOURCE_TYPE_PREFETCH ||
335 resource_type == content::RESOURCE_TYPE_SUB_RESOURCE || 358 resource_type == content::RESOURCE_TYPE_SUB_RESOURCE ||
336 resource_type == content::RESOURCE_TYPE_XHR) { 359 resource_type == content::RESOURCE_TYPE_XHR) {
337 return GetResourceTypeFromMimeType(mime_type, 360 return GetResourceTypeFromMimeType(mime_type,
338 content::RESOURCE_TYPE_LAST_TYPE); 361 content::RESOURCE_TYPE_LAST_TYPE);
339 } 362 }
340 return resource_type; 363 return resource_type;
341 } 364 }
342 365
343 // static 366 // static
344 bool ResourcePrefetchPredictor::IsNoStore(const net::URLRequest* response) { 367 bool ResourcePrefetchPredictor::IsNoStore(const net::URLRequest& response) {
345 if (response->was_cached()) 368 if (response.was_cached())
346 return false; 369 return false;
347 370
348 const net::HttpResponseInfo& response_info = response->response_info(); 371 const net::HttpResponseInfo& response_info = response.response_info();
349 if (!response_info.headers.get()) 372 if (!response_info.headers.get())
350 return false; 373 return false;
351 return response_info.headers->HasHeaderValue("cache-control", "no-store"); 374 return response_info.headers->HasHeaderValue("cache-control", "no-store");
352 } 375 }
353 376
354 // static 377 // static
355 content::ResourceType ResourcePrefetchPredictor::GetResourceTypeFromMimeType( 378 content::ResourceType ResourcePrefetchPredictor::GetResourceTypeFromMimeType(
356 const std::string& mime_type, 379 const std::string& mime_type,
357 content::ResourceType fallback) { 380 content::ResourceType fallback) {
358 if (mime_type.empty()) { 381 if (mime_type.empty()) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 } 431 }
409 432
410 // static 433 // static
411 void ResourcePrefetchPredictor::SetAllowPortInUrlsForTesting(bool state) { 434 void ResourcePrefetchPredictor::SetAllowPortInUrlsForTesting(bool state) {
412 g_allow_port_in_urls = state; 435 g_allow_port_in_urls = state;
413 } 436 }
414 437
415 //////////////////////////////////////////////////////////////////////////////// 438 ////////////////////////////////////////////////////////////////////////////////
416 // ResourcePrefetchPredictor nested types. 439 // ResourcePrefetchPredictor nested types.
417 440
441 ResourcePrefetchPredictor::OriginRequestSummary::OriginRequestSummary()
442 : origin(),
443 always_access_network(false),
444 accessed_network(false),
445 first_occurrence(0) {}
446
447 ResourcePrefetchPredictor::OriginRequestSummary::OriginRequestSummary(
448 const OriginRequestSummary& other) = default;
449
450 ResourcePrefetchPredictor::OriginRequestSummary::~OriginRequestSummary() {}
451
418 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary() 452 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary()
419 : resource_type(content::RESOURCE_TYPE_LAST_TYPE), 453 : resource_type(content::RESOURCE_TYPE_LAST_TYPE),
420 priority(net::IDLE), 454 priority(net::IDLE),
421 was_cached(false), 455 was_cached(false),
422 has_validators(false), 456 has_validators(false),
423 always_revalidate(false) {} 457 always_revalidate(false),
458 is_no_store(false),
459 network_accessed(false) {}
424 460
425 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary( 461 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary(
426 const URLRequestSummary& other) 462 const URLRequestSummary& other) = default;
427 : navigation_id(other.navigation_id),
428 resource_url(other.resource_url),
429 resource_type(other.resource_type),
430 priority(other.priority),
431 mime_type(other.mime_type),
432 was_cached(other.was_cached),
433 redirect_url(other.redirect_url),
434 has_validators(other.has_validators),
435 always_revalidate(other.always_revalidate) {}
436 463
437 ResourcePrefetchPredictor::URLRequestSummary::~URLRequestSummary() { 464 ResourcePrefetchPredictor::URLRequestSummary::~URLRequestSummary() {
438 } 465 }
439 466
440 // static 467 // static
441 bool ResourcePrefetchPredictor::URLRequestSummary::SummarizeResponse( 468 bool ResourcePrefetchPredictor::URLRequestSummary::SummarizeResponse(
442 const net::URLRequest& request, 469 const net::URLRequest& request,
443 URLRequestSummary* summary) { 470 URLRequestSummary* summary) {
444 const content::ResourceRequestInfo* request_info = 471 const content::ResourceRequestInfo* request_info =
445 content::ResourceRequestInfo::ForRequest(&request); 472 content::ResourceRequestInfo::ForRequest(&request);
446 if (!request_info) 473 if (!request_info)
447 return false; 474 return false;
448 475
449 summary->resource_url = request.original_url(); 476 summary->resource_url = request.original_url();
477 summary->request_url = request.url();
450 content::ResourceType resource_type_from_request = 478 content::ResourceType resource_type_from_request =
451 request_info->GetResourceType(); 479 request_info->GetResourceType();
452 summary->priority = request.priority(); 480 summary->priority = request.priority();
453 request.GetMimeType(&summary->mime_type); 481 request.GetMimeType(&summary->mime_type);
454 summary->was_cached = request.was_cached(); 482 summary->was_cached = request.was_cached();
455 summary->resource_type = 483 summary->resource_type =
456 GetResourceType(resource_type_from_request, summary->mime_type); 484 GetResourceType(resource_type_from_request, summary->mime_type);
457 485
458 scoped_refptr<net::HttpResponseHeaders> headers = 486 scoped_refptr<net::HttpResponseHeaders> headers =
459 request.response_info().headers; 487 request.response_info().headers;
460 if (headers.get()) { 488 if (headers.get()) {
461 summary->has_validators = headers->HasValidators(); 489 summary->has_validators = headers->HasValidators();
462 // RFC 2616, section 14.9. 490 // RFC 2616, section 14.9.
463 summary->always_revalidate = 491 summary->always_revalidate =
464 headers->HasHeaderValue("cache-control", "no-cache") || 492 headers->HasHeaderValue("cache-control", "no-cache") ||
465 headers->HasHeaderValue("pragma", "no-cache") || 493 headers->HasHeaderValue("pragma", "no-cache") ||
466 headers->HasHeaderValue("vary", "*"); 494 headers->HasHeaderValue("vary", "*");
495 summary->is_no_store = IsNoStore(request);
467 } 496 }
497 summary->network_accessed = request.response_info().network_accessed;
468 return true; 498 return true;
469 } 499 }
470 500
471 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary( 501 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary(
472 const GURL& i_main_frame_url) 502 const GURL& i_main_frame_url)
473 : main_frame_url(i_main_frame_url), initial_url(i_main_frame_url) {} 503 : main_frame_url(i_main_frame_url), initial_url(i_main_frame_url) {}
474 504
475 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary( 505 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary(
476 const PageRequestSummary& other) = default; 506 const PageRequestSummary& other) = default;
477 507
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
512 if (initialization_state_ != NOT_INITIALIZED) 542 if (initialization_state_ != NOT_INITIALIZED)
513 return; 543 return;
514 initialization_state_ = INITIALIZING; 544 initialization_state_ = INITIALIZING;
515 545
516 // Create local caches using the database as loaded. 546 // Create local caches using the database as loaded.
517 auto url_data_map = base::MakeUnique<PrefetchDataMap>(); 547 auto url_data_map = base::MakeUnique<PrefetchDataMap>();
518 auto host_data_map = base::MakeUnique<PrefetchDataMap>(); 548 auto host_data_map = base::MakeUnique<PrefetchDataMap>();
519 auto url_redirect_data_map = base::MakeUnique<RedirectDataMap>(); 549 auto url_redirect_data_map = base::MakeUnique<RedirectDataMap>();
520 auto host_redirect_data_map = base::MakeUnique<RedirectDataMap>(); 550 auto host_redirect_data_map = base::MakeUnique<RedirectDataMap>();
521 auto manifest_data_map = base::MakeUnique<ManifestDataMap>(); 551 auto manifest_data_map = base::MakeUnique<ManifestDataMap>();
552 auto origin_data_map = base::MakeUnique<OriginDataMap>();
522 553
523 // Get raw pointers to pass to the first task. Ownership of the unique_ptrs 554 // Get raw pointers to pass to the first task. Ownership of the unique_ptrs
524 // will be passed to the reply task. 555 // will be passed to the reply task.
525 auto* url_data_map_ptr = url_data_map.get(); 556 auto* url_data_map_ptr = url_data_map.get();
526 auto* host_data_map_ptr = host_data_map.get(); 557 auto* host_data_map_ptr = host_data_map.get();
527 auto* url_redirect_data_map_ptr = url_redirect_data_map.get(); 558 auto* url_redirect_data_map_ptr = url_redirect_data_map.get();
528 auto* host_redirect_data_map_ptr = host_redirect_data_map.get(); 559 auto* host_redirect_data_map_ptr = host_redirect_data_map.get();
529 auto* manifest_data_map_ptr = manifest_data_map.get(); 560 auto* manifest_data_map_ptr = manifest_data_map.get();
561 auto* origin_data_map_ptr = origin_data_map.get();
530 562
531 BrowserThread::PostTaskAndReply( 563 BrowserThread::PostTaskAndReply(
532 BrowserThread::DB, FROM_HERE, 564 BrowserThread::DB, FROM_HERE,
533 base::Bind(&ResourcePrefetchPredictorTables::GetAllData, tables_, 565 base::Bind(&ResourcePrefetchPredictorTables::GetAllData, tables_,
534 url_data_map_ptr, host_data_map_ptr, url_redirect_data_map_ptr, 566 url_data_map_ptr, host_data_map_ptr, url_redirect_data_map_ptr,
535 host_redirect_data_map_ptr, manifest_data_map_ptr), 567 host_redirect_data_map_ptr, manifest_data_map_ptr,
568 origin_data_map_ptr),
536 base::Bind(&ResourcePrefetchPredictor::CreateCaches, AsWeakPtr(), 569 base::Bind(&ResourcePrefetchPredictor::CreateCaches, AsWeakPtr(),
537 base::Passed(&url_data_map), base::Passed(&host_data_map), 570 base::Passed(&url_data_map), base::Passed(&host_data_map),
538 base::Passed(&url_redirect_data_map), 571 base::Passed(&url_redirect_data_map),
539 base::Passed(&host_redirect_data_map), 572 base::Passed(&host_redirect_data_map),
540 base::Passed(&manifest_data_map))); 573 base::Passed(&manifest_data_map),
574 base::Passed(&origin_data_map)));
541 } 575 }
542 576
543 void ResourcePrefetchPredictor::RecordURLRequest( 577 void ResourcePrefetchPredictor::RecordURLRequest(
544 const URLRequestSummary& request) { 578 const URLRequestSummary& request) {
545 DCHECK_CURRENTLY_ON(BrowserThread::UI); 579 DCHECK_CURRENTLY_ON(BrowserThread::UI);
546 if (initialization_state_ != INITIALIZED) 580 if (initialization_state_ != INITIALIZED)
547 return; 581 return;
548 582
549 CHECK_EQ(request.resource_type, content::RESOURCE_TYPE_MAIN_FRAME); 583 CHECK_EQ(request.resource_type, content::RESOURCE_TYPE_MAIN_FRAME);
550 OnMainFrameRequest(request); 584 OnMainFrameRequest(request);
(...skipping 10 matching lines...) Expand all
561 else 595 else
562 OnSubresourceResponse(response); 596 OnSubresourceResponse(response);
563 } 597 }
564 598
565 void ResourcePrefetchPredictor::RecordURLRedirect( 599 void ResourcePrefetchPredictor::RecordURLRedirect(
566 const URLRequestSummary& response) { 600 const URLRequestSummary& response) {
567 DCHECK_CURRENTLY_ON(BrowserThread::UI); 601 DCHECK_CURRENTLY_ON(BrowserThread::UI);
568 if (initialization_state_ != INITIALIZED) 602 if (initialization_state_ != INITIALIZED)
569 return; 603 return;
570 604
571 CHECK_EQ(response.resource_type, content::RESOURCE_TYPE_MAIN_FRAME); 605 if (response.resource_type == content::RESOURCE_TYPE_MAIN_FRAME)
572 OnMainFrameRedirect(response); 606 OnMainFrameRedirect(response);
607 else
608 OnSubresourceRedirect(response);
573 } 609 }
574 610
575 void ResourcePrefetchPredictor::RecordMainFrameLoadComplete( 611 void ResourcePrefetchPredictor::RecordMainFrameLoadComplete(
576 const NavigationID& navigation_id) { 612 const NavigationID& navigation_id) {
577 switch (initialization_state_) { 613 switch (initialization_state_) {
578 case NOT_INITIALIZED: 614 case NOT_INITIALIZED:
579 StartInitialization(); 615 StartInitialization();
580 break; 616 break;
581 case INITIALIZING: 617 case INITIALIZING:
582 break; 618 break;
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
742 inflight_navigations_.insert( 778 inflight_navigations_.insert(
743 std::make_pair(navigation_id, std::move(summary))); 779 std::make_pair(navigation_id, std::move(summary)));
744 } 780 }
745 781
746 void ResourcePrefetchPredictor::OnSubresourceResponse( 782 void ResourcePrefetchPredictor::OnSubresourceResponse(
747 const URLRequestSummary& response) { 783 const URLRequestSummary& response) {
748 DCHECK_CURRENTLY_ON(BrowserThread::UI); 784 DCHECK_CURRENTLY_ON(BrowserThread::UI);
749 DCHECK_EQ(INITIALIZED, initialization_state_); 785 DCHECK_EQ(INITIALIZED, initialization_state_);
750 786
751 NavigationMap::const_iterator nav_it = 787 NavigationMap::const_iterator nav_it =
752 inflight_navigations_.find(response.navigation_id); 788 inflight_navigations_.find(response.navigation_id);
753 if (nav_it == inflight_navigations_.end()) { 789 if (nav_it == inflight_navigations_.end())
754 return; 790 return;
755 } 791 auto& page_request_summary = *nav_it->second;
756 792
757 nav_it->second->subresource_requests.push_back(response); 793 if (!response.is_no_store)
794 page_request_summary.subresource_requests.push_back(response);
795
796 if (config_.is_origin_prediction_enabled)
797 UpdateOrAddToOrigins(&page_request_summary.origins, response);
798 }
799
800 void ResourcePrefetchPredictor::OnSubresourceRedirect(
801 const URLRequestSummary& response) {
802 DCHECK_CURRENTLY_ON(BrowserThread::UI);
803 DCHECK_EQ(INITIALIZED, initialization_state_);
804
805 if (!config_.is_origin_prediction_enabled)
806 return;
807
808 NavigationMap::const_iterator nav_it =
809 inflight_navigations_.find(response.navigation_id);
810 if (nav_it == inflight_navigations_.end())
811 return;
812 auto& page_request_summary = *nav_it->second;
813 UpdateOrAddToOrigins(&page_request_summary.origins, response);
758 } 814 }
759 815
760 void ResourcePrefetchPredictor::OnNavigationComplete( 816 void ResourcePrefetchPredictor::OnNavigationComplete(
761 const NavigationID& nav_id_without_timing_info) { 817 const NavigationID& nav_id_without_timing_info) {
762 DCHECK_CURRENTLY_ON(BrowserThread::UI); 818 DCHECK_CURRENTLY_ON(BrowserThread::UI);
763 DCHECK_EQ(INITIALIZED, initialization_state_); 819 DCHECK_EQ(INITIALIZED, initialization_state_);
764 820
765 NavigationMap::iterator nav_it = 821 NavigationMap::iterator nav_it =
766 inflight_navigations_.find(nav_id_without_timing_info); 822 inflight_navigations_.find(nav_id_without_timing_info);
767 if (nav_it == inflight_navigations_.end()) 823 if (nav_it == inflight_navigations_.end())
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
881 } 937 }
882 938
883 return has_prefetchable_resource; 939 return has_prefetchable_resource;
884 } 940 }
885 941
886 void ResourcePrefetchPredictor::CreateCaches( 942 void ResourcePrefetchPredictor::CreateCaches(
887 std::unique_ptr<PrefetchDataMap> url_data_map, 943 std::unique_ptr<PrefetchDataMap> url_data_map,
888 std::unique_ptr<PrefetchDataMap> host_data_map, 944 std::unique_ptr<PrefetchDataMap> host_data_map,
889 std::unique_ptr<RedirectDataMap> url_redirect_data_map, 945 std::unique_ptr<RedirectDataMap> url_redirect_data_map,
890 std::unique_ptr<RedirectDataMap> host_redirect_data_map, 946 std::unique_ptr<RedirectDataMap> host_redirect_data_map,
891 std::unique_ptr<ManifestDataMap> manifest_data_map) { 947 std::unique_ptr<ManifestDataMap> manifest_data_map,
948 std::unique_ptr<OriginDataMap> origin_data_map) {
892 DCHECK_CURRENTLY_ON(BrowserThread::UI); 949 DCHECK_CURRENTLY_ON(BrowserThread::UI);
893 950
894 DCHECK_EQ(INITIALIZING, initialization_state_); 951 DCHECK_EQ(INITIALIZING, initialization_state_);
895 DCHECK(!url_table_cache_); 952 DCHECK(!url_table_cache_);
896 DCHECK(!host_table_cache_); 953 DCHECK(!host_table_cache_);
897 DCHECK(!url_redirect_table_cache_); 954 DCHECK(!url_redirect_table_cache_);
898 DCHECK(!host_redirect_table_cache_); 955 DCHECK(!host_redirect_table_cache_);
899 DCHECK(!manifest_table_cache_); 956 DCHECK(!manifest_table_cache_);
957 DCHECK(!origin_table_cache_);
958
900 DCHECK(inflight_navigations_.empty()); 959 DCHECK(inflight_navigations_.empty());
901 960
902 url_table_cache_ = std::move(url_data_map); 961 url_table_cache_ = std::move(url_data_map);
903 host_table_cache_ = std::move(host_data_map); 962 host_table_cache_ = std::move(host_data_map);
904 url_redirect_table_cache_ = std::move(url_redirect_data_map); 963 url_redirect_table_cache_ = std::move(url_redirect_data_map);
905 host_redirect_table_cache_ = std::move(host_redirect_data_map); 964 host_redirect_table_cache_ = std::move(host_redirect_data_map);
906 manifest_table_cache_ = std::move(manifest_data_map); 965 manifest_table_cache_ = std::move(manifest_data_map);
966 origin_table_cache_ = std::move(origin_data_map);
907 967
908 ConnectToHistoryService(); 968 ConnectToHistoryService();
909 } 969 }
910 970
911 void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() { 971 void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() {
912 DCHECK_CURRENTLY_ON(BrowserThread::UI); 972 DCHECK_CURRENTLY_ON(BrowserThread::UI);
913 DCHECK_EQ(INITIALIZING, initialization_state_); 973 DCHECK_EQ(INITIALIZING, initialization_state_);
914 974
915 // Initialize the prefetch manager only if prefetching is enabled. 975 // Initialize the prefetch manager only if prefetching is enabled.
916 if (config_.IsPrefetchingEnabledForSomeOrigin(profile_)) { 976 if (config_.IsPrefetchingEnabledForSomeOrigin(profile_)) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
967 } 1027 }
968 } 1028 }
969 1029
970 void ResourcePrefetchPredictor::DeleteAllUrls() { 1030 void ResourcePrefetchPredictor::DeleteAllUrls() {
971 inflight_navigations_.clear(); 1031 inflight_navigations_.clear();
972 url_table_cache_->clear(); 1032 url_table_cache_->clear();
973 host_table_cache_->clear(); 1033 host_table_cache_->clear();
974 url_redirect_table_cache_->clear(); 1034 url_redirect_table_cache_->clear();
975 host_redirect_table_cache_->clear(); 1035 host_redirect_table_cache_->clear();
976 manifest_table_cache_->clear(); 1036 manifest_table_cache_->clear();
1037 origin_table_cache_->clear();
977 1038
978 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, 1039 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
979 base::Bind(&ResourcePrefetchPredictorTables::DeleteAllData, tables_)); 1040 base::Bind(&ResourcePrefetchPredictorTables::DeleteAllData, tables_));
980 } 1041 }
981 1042
982 void ResourcePrefetchPredictor::DeleteUrls(const history::URLRows& urls) { 1043 void ResourcePrefetchPredictor::DeleteUrls(const history::URLRows& urls) {
983 // Check all the urls in the database and pick out the ones that are present 1044 // Check all the urls in the database and pick out the ones that are present
984 // in the cache. 1045 // in the cache.
985 std::vector<std::string> urls_to_delete, hosts_to_delete; 1046 std::vector<std::string> urls_to_delete, hosts_to_delete;
986 std::vector<std::string> url_redirects_to_delete, host_redirects_to_delete; 1047 std::vector<std::string> url_redirects_to_delete, host_redirects_to_delete;
987 std::vector<std::string> manifest_hosts_to_delete; 1048 std::vector<std::string> manifest_hosts_to_delete;
1049 std::vector<std::string> origin_hosts_to_delete;
988 1050
989 for (const auto& it : urls) { 1051 for (const auto& it : urls) {
990 const std::string& url_spec = it.url().spec(); 1052 const std::string& url_spec = it.url().spec();
991 if (url_table_cache_->find(url_spec) != url_table_cache_->end()) { 1053 if (url_table_cache_->find(url_spec) != url_table_cache_->end()) {
992 urls_to_delete.push_back(url_spec); 1054 urls_to_delete.push_back(url_spec);
993 url_table_cache_->erase(url_spec); 1055 url_table_cache_->erase(url_spec);
994 } 1056 }
995 1057
996 if (url_redirect_table_cache_->find(url_spec) != 1058 if (url_redirect_table_cache_->find(url_spec) !=
997 url_redirect_table_cache_->end()) { 1059 url_redirect_table_cache_->end()) {
(...skipping 12 matching lines...) Expand all
1010 host_redirects_to_delete.push_back(host); 1072 host_redirects_to_delete.push_back(host);
1011 host_redirect_table_cache_->erase(host); 1073 host_redirect_table_cache_->erase(host);
1012 } 1074 }
1013 1075
1014 std::string manifest_host = history::HostForTopHosts(it.url()); 1076 std::string manifest_host = history::HostForTopHosts(it.url());
1015 if (manifest_table_cache_->find(manifest_host) != 1077 if (manifest_table_cache_->find(manifest_host) !=
1016 manifest_table_cache_->end()) { 1078 manifest_table_cache_->end()) {
1017 manifest_hosts_to_delete.push_back(manifest_host); 1079 manifest_hosts_to_delete.push_back(manifest_host);
1018 manifest_table_cache_->erase(manifest_host); 1080 manifest_table_cache_->erase(manifest_host);
1019 } 1081 }
1082
1083 if (origin_table_cache_->find(host) != origin_table_cache_->end()) {
1084 origin_hosts_to_delete.push_back(host);
1085 origin_table_cache_->erase(host);
1086 }
1020 } 1087 }
1021 1088
1022 if (!urls_to_delete.empty() || !hosts_to_delete.empty()) { 1089 if (!urls_to_delete.empty() || !hosts_to_delete.empty()) {
1023 BrowserThread::PostTask( 1090 BrowserThread::PostTask(
1024 BrowserThread::DB, FROM_HERE, 1091 BrowserThread::DB, FROM_HERE,
1025 base::Bind(&ResourcePrefetchPredictorTables::DeleteResourceData, 1092 base::Bind(&ResourcePrefetchPredictorTables::DeleteResourceData,
1026 tables_, urls_to_delete, hosts_to_delete)); 1093 tables_, urls_to_delete, hosts_to_delete));
1027 } 1094 }
1028 1095
1029 if (!url_redirects_to_delete.empty() || !host_redirects_to_delete.empty()) { 1096 if (!url_redirects_to_delete.empty() || !host_redirects_to_delete.empty()) {
1030 BrowserThread::PostTask( 1097 BrowserThread::PostTask(
1031 BrowserThread::DB, FROM_HERE, 1098 BrowserThread::DB, FROM_HERE,
1032 base::Bind(&ResourcePrefetchPredictorTables::DeleteRedirectData, 1099 base::Bind(&ResourcePrefetchPredictorTables::DeleteRedirectData,
1033 tables_, url_redirects_to_delete, host_redirects_to_delete)); 1100 tables_, url_redirects_to_delete, host_redirects_to_delete));
1034 } 1101 }
1035 1102
1036 if (!manifest_hosts_to_delete.empty()) { 1103 if (!manifest_hosts_to_delete.empty()) {
1037 BrowserThread::PostTask( 1104 BrowserThread::PostTask(
1038 BrowserThread::DB, FROM_HERE, 1105 BrowserThread::DB, FROM_HERE,
1039 base::Bind(&ResourcePrefetchPredictorTables::DeleteManifestData, 1106 base::Bind(&ResourcePrefetchPredictorTables::DeleteManifestData,
1040 tables_, manifest_hosts_to_delete)); 1107 tables_, manifest_hosts_to_delete));
1041 } 1108 }
1109
1110 if (!origin_hosts_to_delete.empty()) {
1111 BrowserThread::PostTask(
1112 BrowserThread::DB, FROM_HERE,
1113 base::Bind(&ResourcePrefetchPredictorTables::DeleteOriginData, tables_,
1114 origin_hosts_to_delete));
1115 }
1042 } 1116 }
1043 1117
1044 void ResourcePrefetchPredictor::RemoveOldestEntryInPrefetchDataMap( 1118 void ResourcePrefetchPredictor::RemoveOldestEntryInPrefetchDataMap(
1045 PrefetchKeyType key_type, 1119 PrefetchKeyType key_type,
1046 PrefetchDataMap* data_map) { 1120 PrefetchDataMap* data_map) {
1047 if (data_map->empty()) 1121 if (data_map->empty())
1048 return; 1122 return;
1049 1123
1050 uint64_t oldest_time = UINT64_MAX; 1124 uint64_t oldest_time = UINT64_MAX;
1051 std::string key_to_delete; 1125 std::string key_to_delete;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1102 }); 1176 });
1103 1177
1104 std::string key_to_delete = oldest_entry->first; 1178 std::string key_to_delete = oldest_entry->first;
1105 data_map->erase(oldest_entry); 1179 data_map->erase(oldest_entry);
1106 BrowserThread::PostTask( 1180 BrowserThread::PostTask(
1107 BrowserThread::DB, FROM_HERE, 1181 BrowserThread::DB, FROM_HERE,
1108 base::Bind(&ResourcePrefetchPredictorTables::DeleteManifestData, tables_, 1182 base::Bind(&ResourcePrefetchPredictorTables::DeleteManifestData, tables_,
1109 std::vector<std::string>({key_to_delete}))); 1183 std::vector<std::string>({key_to_delete})));
1110 } 1184 }
1111 1185
1186 void ResourcePrefetchPredictor::RemoveOldestEntryInOriginDataMap(
1187 OriginDataMap* data_map) {
1188 if (data_map->empty())
1189 return;
1190
1191 uint64_t oldest_time = UINT64_MAX;
1192 std::string key_to_delete;
1193 for (const auto& kv : *data_map) {
1194 const OriginData& data = kv.second;
1195 if (key_to_delete.empty() || data.last_visit_time() < oldest_time) {
1196 key_to_delete = kv.first;
1197 oldest_time = data.last_visit_time();
1198 }
1199 }
1200
1201 data_map->erase(key_to_delete);
1202 BrowserThread::PostTask(
1203 BrowserThread::DB, FROM_HERE,
1204 base::Bind(&ResourcePrefetchPredictorTables::DeleteOriginData, tables_,
1205 std::vector<std::string>({key_to_delete})));
1206 }
1207
1112 void ResourcePrefetchPredictor::OnVisitCountLookup( 1208 void ResourcePrefetchPredictor::OnVisitCountLookup(
1113 size_t url_visit_count, 1209 size_t url_visit_count,
1114 const PageRequestSummary& summary) { 1210 const PageRequestSummary& summary) {
1115 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1211 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1116 1212
1117 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HistoryVisitCountForUrl", 1213 UMA_HISTOGRAM_COUNTS("ResourcePrefetchPredictor.HistoryVisitCountForUrl",
1118 url_visit_count); 1214 url_visit_count);
1119 1215
1120 // TODO(alexilin): make only one request to DB thread. 1216 // TODO(alexilin): make only one request to DB thread.
1121 1217
(...skipping 13 matching lines...) Expand all
1135 url_redirect_table_cache_.get()); 1231 url_redirect_table_cache_.get());
1136 } 1232 }
1137 } 1233 }
1138 1234
1139 // Host level data - no cutoff, always learn the navigation if enabled. 1235 // Host level data - no cutoff, always learn the navigation if enabled.
1140 const std::string host = summary.main_frame_url.host(); 1236 const std::string host = summary.main_frame_url.host();
1141 LearnNavigation(host, PREFETCH_KEY_TYPE_HOST, summary.subresource_requests, 1237 LearnNavigation(host, PREFETCH_KEY_TYPE_HOST, summary.subresource_requests,
1142 config_.max_hosts_to_track, host_table_cache_.get(), 1238 config_.max_hosts_to_track, host_table_cache_.get(),
1143 summary.initial_url.host(), host_redirect_table_cache_.get()); 1239 summary.initial_url.host(), host_redirect_table_cache_.get());
1144 1240
1241 if (config_.is_origin_prediction_enabled) {
1242 LearnOrigins(host, summary.origins, config_.max_hosts_to_track,
1243 origin_table_cache_.get());
1244 }
1245
1145 if (observer_) 1246 if (observer_)
1146 observer_->OnNavigationLearned(url_visit_count, summary); 1247 observer_->OnNavigationLearned(url_visit_count, summary);
1147 } 1248 }
1148 1249
1149 void ResourcePrefetchPredictor::LearnNavigation( 1250 void ResourcePrefetchPredictor::LearnNavigation(
1150 const std::string& key, 1251 const std::string& key,
1151 PrefetchKeyType key_type, 1252 PrefetchKeyType key_type,
1152 const std::vector<URLRequestSummary>& new_resources, 1253 const std::vector<URLRequestSummary>& new_resources,
1153 size_t max_data_map_size, 1254 size_t max_data_map_size,
1154 PrefetchDataMap* data_map, 1255 PrefetchDataMap* data_map,
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
1379 const RedirectData& url_redirect_data = 1480 const RedirectData& url_redirect_data =
1380 is_host ? empty_redirect_data : data; 1481 is_host ? empty_redirect_data : data;
1381 BrowserThread::PostTask( 1482 BrowserThread::PostTask(
1382 BrowserThread::DB, FROM_HERE, 1483 BrowserThread::DB, FROM_HERE,
1383 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, tables_, 1484 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, tables_,
1384 empty_data, empty_data, url_redirect_data, 1485 empty_data, empty_data, url_redirect_data,
1385 host_redirect_data)); 1486 host_redirect_data));
1386 } 1487 }
1387 } 1488 }
1388 1489
1490 void ResourcePrefetchPredictor::LearnOrigins(
1491 const std::string& host,
1492 const std::map<GURL, OriginRequestSummary>& summaries,
1493 size_t max_data_map_size,
1494 OriginDataMap* data_map) {
1495 if (host.size() > ResourcePrefetchPredictorTables::kMaxStringLength)
1496 return;
1497
1498 auto cache_entry = data_map->find(host);
1499 bool new_entry = cache_entry == data_map->end();
1500 if (new_entry) {
1501 if (data_map->size() >= max_data_map_size)
1502 RemoveOldestEntryInOriginDataMap(data_map);
1503
1504 cache_entry = data_map->insert({host, OriginData()}).first;
1505 OriginData& data = cache_entry->second;
1506 data.set_host(host);
1507 data.set_last_visit_time(base::Time::Now().ToInternalValue());
1508 size_t origins_size = summaries.size();
1509 auto ordered_origins =
1510 std::vector<const OriginRequestSummary*>(origins_size);
1511 for (const auto& kv : summaries) {
1512 size_t index = kv.second.first_occurrence;
1513 DCHECK_LT(index, origins_size);
1514 ordered_origins[index] = &kv.second;
1515 }
1516
1517 for (const OriginRequestSummary* summary : ordered_origins) {
1518 auto* origin_to_add = data.add_origins();
1519 InitializeOriginStatFromOriginRequestSummary(origin_to_add, *summary);
1520 }
1521 } else {
1522 auto& data = cache_entry->second;
1523 data.set_last_visit_time(base::Time::Now().ToInternalValue());
1524
1525 std::map<GURL, int> old_index;
1526 int old_size = static_cast<int>(data.origins_size());
1527 for (int i = 0; i < old_size; ++i) {
1528 bool is_new =
1529 old_index.insert({GURL(data.origins(i).origin()), i}).second;
1530 DCHECK(is_new);
1531 }
1532
1533 // Update the old origins.
1534 for (int i = 0; i < old_size; ++i) {
1535 auto* old_origin = data.mutable_origins(i);
1536 GURL origin(old_origin->origin());
1537 auto it = summaries.find(origin);
1538 if (it == summaries.end()) {
1539 // miss
1540 old_origin->set_number_of_misses(old_origin->number_of_misses() + 1);
1541 old_origin->set_consecutive_misses(old_origin->consecutive_misses() +
1542 1);
1543 } else {
1544 // hit: update.
1545 const auto& new_origin = it->second;
1546 old_origin->set_always_access_network(new_origin.always_access_network);
1547 old_origin->set_accessed_network(new_origin.accessed_network);
1548
1549 int position = new_origin.first_occurrence + 1;
1550 int total =
1551 old_origin->number_of_hits() + old_origin->number_of_misses();
1552 old_origin->set_average_position(
1553 ((old_origin->average_position() * total) + position) /
1554 (total + 1));
1555 old_origin->set_number_of_hits(old_origin->number_of_hits() + 1);
1556 old_origin->set_consecutive_misses(0);
1557 }
1558 }
1559
1560 // Add new origins.
1561 for (const auto& kv : summaries) {
1562 if (old_index.find(kv.first) != old_index.end())
1563 continue;
1564
1565 auto* origin_to_add = data.add_origins();
1566 InitializeOriginStatFromOriginRequestSummary(origin_to_add, kv.second);
1567 }
1568 }
1569
1570 // Trim and Sort.
1571 auto& data = cache_entry->second;
1572 ResourcePrefetchPredictorTables::TrimOrigins(&data,
1573 config_.max_consecutive_misses);
1574 ResourcePrefetchPredictorTables::SortOrigins(&data);
1575 if (data.origins_size() > static_cast<int>(config_.max_resources_per_entry)) {
1576 data.mutable_origins()->DeleteSubrange(
1577 config_.max_origins_per_entry,
1578 data.origins_size() - config_.max_origins_per_entry);
1579 }
1580
1581 // Update the database.
1582 if (data.origins_size() == 0) {
1583 data_map->erase(cache_entry);
1584 if (!new_entry) {
1585 BrowserThread::PostTask(
1586 BrowserThread::DB, FROM_HERE,
1587 base::Bind(&ResourcePrefetchPredictorTables::DeleteOriginData,
1588 tables_, std::vector<std::string>({host})));
1589 }
1590 } else {
1591 BrowserThread::PostTask(
1592 BrowserThread::DB, FROM_HERE,
1593 base::Bind(&ResourcePrefetchPredictorTables::UpdateOriginData, tables_,
1594 data));
1595 }
1596 }
1597
1389 void ResourcePrefetchPredictor::ReportDatabaseReadiness( 1598 void ResourcePrefetchPredictor::ReportDatabaseReadiness(
1390 const history::TopHostsList& top_hosts) const { 1599 const history::TopHostsList& top_hosts) const {
1391 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1600 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1392 if (top_hosts.size() == 0) 1601 if (top_hosts.size() == 0)
1393 return; 1602 return;
1394 1603
1395 size_t count_in_cache = 0; 1604 size_t count_in_cache = 0;
1396 size_t total_visits = 0; 1605 size_t total_visits = 0;
1397 for (const std::pair<std::string, int>& top_host : top_hosts) { 1606 for (const std::pair<std::string, int>& top_host : top_hosts) {
1398 const std::string& host = top_host.first; 1607 const std::string& host = top_host.first;
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
1497 TestObserver::~TestObserver() { 1706 TestObserver::~TestObserver() {
1498 predictor_->SetObserverForTesting(nullptr); 1707 predictor_->SetObserverForTesting(nullptr);
1499 } 1708 }
1500 1709
1501 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) 1710 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor)
1502 : predictor_(predictor) { 1711 : predictor_(predictor) {
1503 predictor_->SetObserverForTesting(this); 1712 predictor_->SetObserverForTesting(this);
1504 } 1713 }
1505 1714
1506 } // namespace predictors 1715 } // 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