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

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

Issue 2796783004: predictors: Add origin learning. (Closed)
Patch Set: Advancing our amazing database version number. 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 17 matching lines...) Expand all
28 #include "content/public/browser/web_contents.h" 28 #include "content/public/browser/web_contents.h"
29 #include "net/http/http_response_headers.h" 29 #include "net/http/http_response_headers.h"
30 #include "net/url_request/url_request.h" 30 #include "net/url_request/url_request.h"
31 31
32 using content::BrowserThread; 32 using content::BrowserThread;
33 33
34 namespace predictors { 34 namespace predictors {
35 35
36 namespace { 36 namespace {
37 37
38 using OriginStat = OriginData_OriginStat;
39
38 // Sorted by decreasing likelihood according to HTTP archive. 40 // Sorted by decreasing likelihood according to HTTP archive.
39 const char* kFontMimeTypes[] = {"font/woff2", 41 const char* kFontMimeTypes[] = {"font/woff2",
40 "application/x-font-woff", 42 "application/x-font-woff",
41 "application/font-woff", 43 "application/font-woff",
42 "application/font-woff2", 44 "application/font-woff2",
43 "font/x-woff", 45 "font/x-woff",
44 "application/x-font-ttf", 46 "application/x-font-ttf",
45 "font/woff", 47 "font/woff",
46 "font/ttf", 48 "font/ttf",
47 "application/x-font-otf", 49 "application/x-font-otf",
(...skipping 12 matching lines...) Expand all
60 REPORTING_EVENT_ALL_HISTORY_CLEARED = 0, 62 REPORTING_EVENT_ALL_HISTORY_CLEARED = 0,
61 REPORTING_EVENT_PARTIAL_HISTORY_CLEARED = 1, 63 REPORTING_EVENT_PARTIAL_HISTORY_CLEARED = 1,
62 REPORTING_EVENT_COUNT = 2 64 REPORTING_EVENT_COUNT = 2
63 }; 65 };
64 66
65 float ComputeRedirectConfidence(const predictors::RedirectStat& redirect) { 67 float ComputeRedirectConfidence(const predictors::RedirectStat& redirect) {
66 return (redirect.number_of_hits() + 0.0) / 68 return (redirect.number_of_hits() + 0.0) /
67 (redirect.number_of_hits() + redirect.number_of_misses()); 69 (redirect.number_of_hits() + redirect.number_of_misses());
68 } 70 }
69 71
72 void UpdateOrAddToSummaries(
alexilin 2017/04/10 14:58:27 nit: We have a lot of different summaries. I'd pro
Benoit L 2017/04/11 09:04:05 Done.
73 std::map<GURL, ResourcePrefetchPredictor::OriginRequestSummary>* summaries,
74 const ResourcePrefetchPredictor::URLRequestSummary& request_summary) {
75 GURL origin = request_summary.resource_url.GetOrigin();
alexilin 2017/04/10 14:58:28 Do we need a check for incorrect url here? From th
Benoit L 2017/04/11 09:04:05 Given the way this code is called, this should not
76 auto it = summaries->find(origin);
77 if (it == summaries->end()) {
78 ResourcePrefetchPredictor::OriginRequestSummary summary;
79 summary.origin = origin;
80 summary.first_occurrence = summaries->size();
81 it = summaries->insert({origin, summary}).first;
82 }
83
84 it->second.always_access_network |=
85 request_summary.always_revalidate || request_summary.is_no_store;
86 it->second.accessed_network |= request_summary.network_accessed;
87 }
88
89 void InitializeOriginStatFromOriginRequestSummary(
90 OriginStat* origin,
91 const ResourcePrefetchPredictor::OriginRequestSummary& summary) {
92 origin->set_origin(summary.origin.spec());
93 origin->set_number_of_hits(1);
94 origin->set_average_position(summary.first_occurrence + 1);
95 origin->set_always_access_network(summary.always_access_network);
96 origin->set_accessed_network(summary.accessed_network);
97 }
98
70 // Used to fetch the visit count for a URL from the History database. 99 // Used to fetch the visit count for a URL from the History database.
71 class GetUrlVisitCountTask : public history::HistoryDBTask { 100 class GetUrlVisitCountTask : public history::HistoryDBTask {
72 public: 101 public:
73 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary; 102 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary;
74 using PageRequestSummary = ResourcePrefetchPredictor::PageRequestSummary; 103 using PageRequestSummary = ResourcePrefetchPredictor::PageRequestSummary;
75 typedef base::Callback<void(size_t, // URL visit count. 104 typedef base::Callback<void(size_t, // URL visit count.
76 const PageRequestSummary&)> 105 const PageRequestSummary&)>
77 VisitInfoCallback; 106 VisitInfoCallback;
78 107
79 GetUrlVisitCountTask(std::unique_ptr<PageRequestSummary> summary, 108 GetUrlVisitCountTask(std::unique_ptr<PageRequestSummary> summary,
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 if (!request_info->IsMainFrame()) 282 if (!request_info->IsMainFrame())
254 return false; 283 return false;
255 284
256 content::ResourceType resource_type = request_info->GetResourceType(); 285 content::ResourceType resource_type = request_info->GetResourceType();
257 return resource_type == content::RESOURCE_TYPE_MAIN_FRAME 286 return resource_type == content::RESOURCE_TYPE_MAIN_FRAME
258 ? IsHandledMainPage(response) 287 ? IsHandledMainPage(response)
259 : IsHandledSubresource(response, resource_type); 288 : IsHandledSubresource(response, resource_type);
260 } 289 }
261 290
262 // static 291 // static
263 bool ResourcePrefetchPredictor::ShouldRecordRedirect( 292 bool ResourcePrefetchPredictor::ShouldRecordRedirect(
alexilin 2017/04/10 14:58:28 ShouldRecordRedirect and ShouldRecordResponse are
Benoit L 2017/04/11 09:04:05 Thanks! Done.
264 net::URLRequest* response) { 293 net::URLRequest* response) {
265 const content::ResourceRequestInfo* request_info = 294 const content::ResourceRequestInfo* request_info =
266 content::ResourceRequestInfo::ForRequest(response); 295 content::ResourceRequestInfo::ForRequest(response);
267 if (!request_info) 296 if (!request_info)
268 return false; 297 return false;
269 298
270 if (!request_info->IsMainFrame()) 299 if (!request_info->IsMainFrame())
271 return false; 300 return false;
272 301
273 return request_info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME && 302 content::ResourceType resource_type = request_info->GetResourceType();
274 IsHandledMainPage(response); 303 return resource_type == content::RESOURCE_TYPE_MAIN_FRAME
304 ? IsHandledMainPage(response)
305 : IsHandledSubresource(response, resource_type);
275 } 306 }
276 307
277 // static 308 // static
278 bool ResourcePrefetchPredictor::IsHandledMainPage(net::URLRequest* request) { 309 bool ResourcePrefetchPredictor::IsHandledMainPage(net::URLRequest* request) {
279 const GURL& url = request->url(); 310 const GURL& url = request->url();
280 bool bad_port = !g_allow_port_in_urls && url.has_port(); 311 bool bad_port = !g_allow_port_in_urls && url.has_port();
281 return url.SchemeIsHTTPOrHTTPS() && !bad_port; 312 return url.SchemeIsHTTPOrHTTPS() && !bad_port;
282 } 313 }
283 314
284 // static 315 // static
(...skipping 13 matching lines...) Expand all
298 return false; 329 return false;
299 330
300 if (response->method() != "GET") 331 if (response->method() != "GET")
301 return false; 332 return false;
302 333
303 if (response->original_url().spec().length() > 334 if (response->original_url().spec().length() >
304 ResourcePrefetchPredictorTables::kMaxStringLength) { 335 ResourcePrefetchPredictorTables::kMaxStringLength) {
305 return false; 336 return false;
306 } 337 }
307 338
308 if (!response->response_info().headers.get() || IsNoStore(response)) 339 if (!response->response_info().headers.get())
309 return false; 340 return false;
310 341
311 return true; 342 return true;
312 } 343 }
313 344
314 // static 345 // static
315 bool ResourcePrefetchPredictor::IsHandledResourceType( 346 bool ResourcePrefetchPredictor::IsHandledResourceType(
316 content::ResourceType resource_type, 347 content::ResourceType resource_type,
317 const std::string& mime_type) { 348 const std::string& mime_type) {
318 content::ResourceType actual_resource_type = 349 content::ResourceType actual_resource_type =
(...skipping 14 matching lines...) Expand all
333 if (resource_type == content::RESOURCE_TYPE_PREFETCH || 364 if (resource_type == content::RESOURCE_TYPE_PREFETCH ||
334 resource_type == content::RESOURCE_TYPE_SUB_RESOURCE || 365 resource_type == content::RESOURCE_TYPE_SUB_RESOURCE ||
335 resource_type == content::RESOURCE_TYPE_XHR) { 366 resource_type == content::RESOURCE_TYPE_XHR) {
336 return GetResourceTypeFromMimeType(mime_type, 367 return GetResourceTypeFromMimeType(mime_type,
337 content::RESOURCE_TYPE_LAST_TYPE); 368 content::RESOURCE_TYPE_LAST_TYPE);
338 } 369 }
339 return resource_type; 370 return resource_type;
340 } 371 }
341 372
342 // static 373 // static
343 bool ResourcePrefetchPredictor::IsNoStore(const net::URLRequest* response) { 374 bool ResourcePrefetchPredictor::IsNoStore(const net::URLRequest& response) {
344 if (response->was_cached()) 375 if (response.was_cached())
345 return false; 376 return false;
346 377
347 const net::HttpResponseInfo& response_info = response->response_info(); 378 const net::HttpResponseInfo& response_info = response.response_info();
348 if (!response_info.headers.get()) 379 if (!response_info.headers.get())
349 return false; 380 return false;
350 return response_info.headers->HasHeaderValue("cache-control", "no-store"); 381 return response_info.headers->HasHeaderValue("cache-control", "no-store");
351 } 382 }
352 383
353 // static 384 // static
354 content::ResourceType ResourcePrefetchPredictor::GetResourceTypeFromMimeType( 385 content::ResourceType ResourcePrefetchPredictor::GetResourceTypeFromMimeType(
355 const std::string& mime_type, 386 const std::string& mime_type,
356 content::ResourceType fallback) { 387 content::ResourceType fallback) {
357 if (mime_type.empty()) { 388 if (mime_type.empty()) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 } 438 }
408 439
409 // static 440 // static
410 void ResourcePrefetchPredictor::SetAllowPortInUrlsForTesting(bool state) { 441 void ResourcePrefetchPredictor::SetAllowPortInUrlsForTesting(bool state) {
411 g_allow_port_in_urls = state; 442 g_allow_port_in_urls = state;
412 } 443 }
413 444
414 //////////////////////////////////////////////////////////////////////////////// 445 ////////////////////////////////////////////////////////////////////////////////
415 // ResourcePrefetchPredictor nested types. 446 // ResourcePrefetchPredictor nested types.
416 447
448 ResourcePrefetchPredictor::OriginRequestSummary::OriginRequestSummary()
449 : origin(), always_access_network(false), accessed_network(false) {}
alexilin 2017/04/10 14:58:28 Initializer for |first_occurrence|?
Benoit L 2017/04/11 09:04:05 Ooops... Thanks. Too bad that neither I nor the co
450
451 ResourcePrefetchPredictor::OriginRequestSummary::OriginRequestSummary(
452 const ResourcePrefetchPredictor::OriginRequestSummary& other) = default;
alexilin 2017/04/10 14:58:28 nit: No need to fully specialize the parameter nam
Benoit L 2017/04/11 09:04:05 Done.
453
454 ResourcePrefetchPredictor::OriginRequestSummary::~OriginRequestSummary() {}
455
417 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary() 456 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary()
418 : resource_type(content::RESOURCE_TYPE_LAST_TYPE), 457 : resource_type(content::RESOURCE_TYPE_LAST_TYPE),
419 priority(net::IDLE), 458 priority(net::IDLE),
420 was_cached(false), 459 was_cached(false),
421 has_validators(false), 460 has_validators(false),
422 always_revalidate(false) {} 461 always_revalidate(false),
462 is_no_store(false) {}
alexilin 2017/04/10 14:58:27 Initializer for |network_accessed|?
Benoit L 2017/04/11 09:04:05 Done.
423 463
424 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary( 464 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary(
425 const URLRequestSummary& other) 465 const URLRequestSummary& other) = default;
alexilin 2017/04/10 14:58:28 Nice catch!
426 : navigation_id(other.navigation_id),
427 resource_url(other.resource_url),
428 resource_type(other.resource_type),
429 priority(other.priority),
430 mime_type(other.mime_type),
431 was_cached(other.was_cached),
432 redirect_url(other.redirect_url),
433 has_validators(other.has_validators),
434 always_revalidate(other.always_revalidate) {}
435 466
436 ResourcePrefetchPredictor::URLRequestSummary::~URLRequestSummary() { 467 ResourcePrefetchPredictor::URLRequestSummary::~URLRequestSummary() {
437 } 468 }
438 469
439 // static 470 // static
440 bool ResourcePrefetchPredictor::URLRequestSummary::SummarizeResponse( 471 bool ResourcePrefetchPredictor::URLRequestSummary::SummarizeResponse(
441 const net::URLRequest& request, 472 const net::URLRequest& request,
442 URLRequestSummary* summary) { 473 URLRequestSummary* summary) {
443 const content::ResourceRequestInfo* request_info = 474 const content::ResourceRequestInfo* request_info =
444 content::ResourceRequestInfo::ForRequest(&request); 475 content::ResourceRequestInfo::ForRequest(&request);
(...skipping 11 matching lines...) Expand all
456 487
457 scoped_refptr<net::HttpResponseHeaders> headers = 488 scoped_refptr<net::HttpResponseHeaders> headers =
458 request.response_info().headers; 489 request.response_info().headers;
459 if (headers.get()) { 490 if (headers.get()) {
460 summary->has_validators = headers->HasValidators(); 491 summary->has_validators = headers->HasValidators();
461 // RFC 2616, section 14.9. 492 // RFC 2616, section 14.9.
462 summary->always_revalidate = 493 summary->always_revalidate =
463 headers->HasHeaderValue("cache-control", "no-cache") || 494 headers->HasHeaderValue("cache-control", "no-cache") ||
464 headers->HasHeaderValue("pragma", "no-cache") || 495 headers->HasHeaderValue("pragma", "no-cache") ||
465 headers->HasHeaderValue("vary", "*"); 496 headers->HasHeaderValue("vary", "*");
497 summary->is_no_store = IsNoStore(request);
466 } 498 }
499 summary->network_accessed = request.response_info().network_accessed;
467 return true; 500 return true;
468 } 501 }
469 502
470 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary( 503 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary(
471 const GURL& i_main_frame_url) 504 const GURL& i_main_frame_url)
472 : main_frame_url(i_main_frame_url), initial_url(i_main_frame_url) {} 505 : main_frame_url(i_main_frame_url), initial_url(i_main_frame_url) {}
473 506
474 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary( 507 ResourcePrefetchPredictor::PageRequestSummary::PageRequestSummary(
475 const PageRequestSummary& other) = default; 508 const PageRequestSummary& other) = default;
476 509
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 if (initialization_state_ != NOT_INITIALIZED) 544 if (initialization_state_ != NOT_INITIALIZED)
512 return; 545 return;
513 initialization_state_ = INITIALIZING; 546 initialization_state_ = INITIALIZING;
514 547
515 // Create local caches using the database as loaded. 548 // Create local caches using the database as loaded.
516 auto url_data_map = base::MakeUnique<PrefetchDataMap>(); 549 auto url_data_map = base::MakeUnique<PrefetchDataMap>();
517 auto host_data_map = base::MakeUnique<PrefetchDataMap>(); 550 auto host_data_map = base::MakeUnique<PrefetchDataMap>();
518 auto url_redirect_data_map = base::MakeUnique<RedirectDataMap>(); 551 auto url_redirect_data_map = base::MakeUnique<RedirectDataMap>();
519 auto host_redirect_data_map = base::MakeUnique<RedirectDataMap>(); 552 auto host_redirect_data_map = base::MakeUnique<RedirectDataMap>();
520 auto manifest_data_map = base::MakeUnique<ManifestDataMap>(); 553 auto manifest_data_map = base::MakeUnique<ManifestDataMap>();
554 auto origin_data_map = base::MakeUnique<OriginDataMap>();
521 555
522 // Get raw pointers to pass to the first task. Ownership of the unique_ptrs 556 // Get raw pointers to pass to the first task. Ownership of the unique_ptrs
523 // will be passed to the reply task. 557 // will be passed to the reply task.
524 auto* url_data_map_ptr = url_data_map.get(); 558 auto* url_data_map_ptr = url_data_map.get();
525 auto* host_data_map_ptr = host_data_map.get(); 559 auto* host_data_map_ptr = host_data_map.get();
526 auto* url_redirect_data_map_ptr = url_redirect_data_map.get(); 560 auto* url_redirect_data_map_ptr = url_redirect_data_map.get();
527 auto* host_redirect_data_map_ptr = host_redirect_data_map.get(); 561 auto* host_redirect_data_map_ptr = host_redirect_data_map.get();
528 auto* manifest_data_map_ptr = manifest_data_map.get(); 562 auto* manifest_data_map_ptr = manifest_data_map.get();
563 auto* origin_data_map_ptr = origin_data_map.get();
529 564
530 BrowserThread::PostTaskAndReply( 565 BrowserThread::PostTaskAndReply(
531 BrowserThread::DB, FROM_HERE, 566 BrowserThread::DB, FROM_HERE,
532 base::Bind(&ResourcePrefetchPredictorTables::GetAllData, tables_, 567 base::Bind(&ResourcePrefetchPredictorTables::GetAllData, tables_,
533 url_data_map_ptr, host_data_map_ptr, url_redirect_data_map_ptr, 568 url_data_map_ptr, host_data_map_ptr, url_redirect_data_map_ptr,
534 host_redirect_data_map_ptr, manifest_data_map_ptr), 569 host_redirect_data_map_ptr, manifest_data_map_ptr,
570 origin_data_map_ptr),
535 base::Bind(&ResourcePrefetchPredictor::CreateCaches, AsWeakPtr(), 571 base::Bind(&ResourcePrefetchPredictor::CreateCaches, AsWeakPtr(),
536 base::Passed(&url_data_map), base::Passed(&host_data_map), 572 base::Passed(&url_data_map), base::Passed(&host_data_map),
537 base::Passed(&url_redirect_data_map), 573 base::Passed(&url_redirect_data_map),
538 base::Passed(&host_redirect_data_map), 574 base::Passed(&host_redirect_data_map),
539 base::Passed(&manifest_data_map))); 575 base::Passed(&manifest_data_map),
576 base::Passed(&origin_data_map)));
540 } 577 }
541 578
542 void ResourcePrefetchPredictor::RecordURLRequest( 579 void ResourcePrefetchPredictor::RecordURLRequest(
543 const URLRequestSummary& request) { 580 const URLRequestSummary& request) {
544 DCHECK_CURRENTLY_ON(BrowserThread::UI); 581 DCHECK_CURRENTLY_ON(BrowserThread::UI);
545 if (initialization_state_ != INITIALIZED) 582 if (initialization_state_ != INITIALIZED)
546 return; 583 return;
547 584
548 CHECK_EQ(request.resource_type, content::RESOURCE_TYPE_MAIN_FRAME); 585 CHECK_EQ(request.resource_type, content::RESOURCE_TYPE_MAIN_FRAME);
549 OnMainFrameRequest(request); 586 OnMainFrameRequest(request);
(...skipping 10 matching lines...) Expand all
560 else 597 else
561 OnSubresourceResponse(response); 598 OnSubresourceResponse(response);
562 } 599 }
563 600
564 void ResourcePrefetchPredictor::RecordURLRedirect( 601 void ResourcePrefetchPredictor::RecordURLRedirect(
565 const URLRequestSummary& response) { 602 const URLRequestSummary& response) {
566 DCHECK_CURRENTLY_ON(BrowserThread::UI); 603 DCHECK_CURRENTLY_ON(BrowserThread::UI);
567 if (initialization_state_ != INITIALIZED) 604 if (initialization_state_ != INITIALIZED)
568 return; 605 return;
569 606
570 CHECK_EQ(response.resource_type, content::RESOURCE_TYPE_MAIN_FRAME); 607 if (response.resource_type == content::RESOURCE_TYPE_MAIN_FRAME)
571 OnMainFrameRedirect(response); 608 OnMainFrameRedirect(response);
609 else
610 OnSubresourceRedirect(response);
572 } 611 }
573 612
574 void ResourcePrefetchPredictor::RecordMainFrameLoadComplete( 613 void ResourcePrefetchPredictor::RecordMainFrameLoadComplete(
575 const NavigationID& navigation_id) { 614 const NavigationID& navigation_id) {
576 switch (initialization_state_) { 615 switch (initialization_state_) {
577 case NOT_INITIALIZED: 616 case NOT_INITIALIZED:
578 StartInitialization(); 617 StartInitialization();
579 break; 618 break;
580 case INITIALIZING: 619 case INITIALIZING:
581 break; 620 break;
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 inflight_navigations_.insert( 780 inflight_navigations_.insert(
742 std::make_pair(navigation_id, std::move(summary))); 781 std::make_pair(navigation_id, std::move(summary)));
743 } 782 }
744 783
745 void ResourcePrefetchPredictor::OnSubresourceResponse( 784 void ResourcePrefetchPredictor::OnSubresourceResponse(
746 const URLRequestSummary& response) { 785 const URLRequestSummary& response) {
747 DCHECK_CURRENTLY_ON(BrowserThread::UI); 786 DCHECK_CURRENTLY_ON(BrowserThread::UI);
748 DCHECK_EQ(INITIALIZED, initialization_state_); 787 DCHECK_EQ(INITIALIZED, initialization_state_);
749 788
750 NavigationMap::const_iterator nav_it = 789 NavigationMap::const_iterator nav_it =
751 inflight_navigations_.find(response.navigation_id); 790 inflight_navigations_.find(response.navigation_id);
752 if (nav_it == inflight_navigations_.end()) { 791 if (nav_it == inflight_navigations_.end())
753 return; 792 return;
754 } 793 auto& page_request_summary = *nav_it->second;
755 794
756 nav_it->second->subresource_requests.push_back(response); 795 if (!response.is_no_store)
796 page_request_summary.subresource_requests.push_back(response);
797
798 if (config_.is_origin_prediction_enabled)
799 UpdateOrAddToSummaries(&page_request_summary.origins, response);
800 }
801
802 void ResourcePrefetchPredictor::OnSubresourceRedirect(
803 const URLRequestSummary& response) {
804 if (!config_.is_origin_prediction_enabled)
alexilin 2017/04/10 14:58:28 nit: Please, add DCHECK for the UI thread and the
Benoit L 2017/04/11 09:04:05 Done.
805 return;
806
807 NavigationMap::const_iterator nav_it =
808 inflight_navigations_.find(response.navigation_id);
809 if (nav_it == inflight_navigations_.end())
810 return;
811 auto& page_request_summary = *nav_it->second;
812 UpdateOrAddToSummaries(&page_request_summary.origins, response);
alexilin 2017/04/10 14:58:28 Just to make it clear: do you need original url or
Benoit L 2017/04/11 09:04:05 As discussed offline, we want to keep the redirect
757 } 813 }
758 814
759 void ResourcePrefetchPredictor::OnNavigationComplete( 815 void ResourcePrefetchPredictor::OnNavigationComplete(
760 const NavigationID& nav_id_without_timing_info) { 816 const NavigationID& nav_id_without_timing_info) {
761 DCHECK_CURRENTLY_ON(BrowserThread::UI); 817 DCHECK_CURRENTLY_ON(BrowserThread::UI);
762 DCHECK_EQ(INITIALIZED, initialization_state_); 818 DCHECK_EQ(INITIALIZED, initialization_state_);
763 819
764 NavigationMap::iterator nav_it = 820 NavigationMap::iterator nav_it =
765 inflight_navigations_.find(nav_id_without_timing_info); 821 inflight_navigations_.find(nav_id_without_timing_info);
766 if (nav_it == inflight_navigations_.end()) 822 if (nav_it == inflight_navigations_.end())
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
880 } 936 }
881 937
882 return has_prefetchable_resource; 938 return has_prefetchable_resource;
883 } 939 }
884 940
885 void ResourcePrefetchPredictor::CreateCaches( 941 void ResourcePrefetchPredictor::CreateCaches(
886 std::unique_ptr<PrefetchDataMap> url_data_map, 942 std::unique_ptr<PrefetchDataMap> url_data_map,
887 std::unique_ptr<PrefetchDataMap> host_data_map, 943 std::unique_ptr<PrefetchDataMap> host_data_map,
888 std::unique_ptr<RedirectDataMap> url_redirect_data_map, 944 std::unique_ptr<RedirectDataMap> url_redirect_data_map,
889 std::unique_ptr<RedirectDataMap> host_redirect_data_map, 945 std::unique_ptr<RedirectDataMap> host_redirect_data_map,
890 std::unique_ptr<ManifestDataMap> manifest_data_map) { 946 std::unique_ptr<ManifestDataMap> manifest_data_map,
947 std::unique_ptr<OriginDataMap> origin_data_map) {
891 DCHECK_CURRENTLY_ON(BrowserThread::UI); 948 DCHECK_CURRENTLY_ON(BrowserThread::UI);
892 949
893 DCHECK_EQ(INITIALIZING, initialization_state_); 950 DCHECK_EQ(INITIALIZING, initialization_state_);
894 DCHECK(!url_table_cache_); 951 DCHECK(!url_table_cache_);
895 DCHECK(!host_table_cache_); 952 DCHECK(!host_table_cache_);
896 DCHECK(!url_redirect_table_cache_); 953 DCHECK(!url_redirect_table_cache_);
897 DCHECK(!host_redirect_table_cache_); 954 DCHECK(!host_redirect_table_cache_);
898 DCHECK(!manifest_table_cache_); 955 DCHECK(!manifest_table_cache_);
956 DCHECK(!origin_table_cache_);
957
899 DCHECK(inflight_navigations_.empty()); 958 DCHECK(inflight_navigations_.empty());
900 959
901 url_table_cache_ = std::move(url_data_map); 960 url_table_cache_ = std::move(url_data_map);
902 host_table_cache_ = std::move(host_data_map); 961 host_table_cache_ = std::move(host_data_map);
903 url_redirect_table_cache_ = std::move(url_redirect_data_map); 962 url_redirect_table_cache_ = std::move(url_redirect_data_map);
904 host_redirect_table_cache_ = std::move(host_redirect_data_map); 963 host_redirect_table_cache_ = std::move(host_redirect_data_map);
905 manifest_table_cache_ = std::move(manifest_data_map); 964 manifest_table_cache_ = std::move(manifest_data_map);
965 origin_table_cache_ = std::move(origin_data_map);
906 966
907 ConnectToHistoryService(); 967 ConnectToHistoryService();
908 } 968 }
909 969
910 void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() { 970 void ResourcePrefetchPredictor::OnHistoryAndCacheLoaded() {
911 DCHECK_CURRENTLY_ON(BrowserThread::UI); 971 DCHECK_CURRENTLY_ON(BrowserThread::UI);
912 DCHECK_EQ(INITIALIZING, initialization_state_); 972 DCHECK_EQ(INITIALIZING, initialization_state_);
913 973
914 // Initialize the prefetch manager only if prefetching is enabled. 974 // Initialize the prefetch manager only if prefetching is enabled.
915 if (config_.IsPrefetchingEnabledForSomeOrigin(profile_)) { 975 if (config_.IsPrefetchingEnabledForSomeOrigin(profile_)) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
966 } 1026 }
967 } 1027 }
968 1028
969 void ResourcePrefetchPredictor::DeleteAllUrls() { 1029 void ResourcePrefetchPredictor::DeleteAllUrls() {
970 inflight_navigations_.clear(); 1030 inflight_navigations_.clear();
971 url_table_cache_->clear(); 1031 url_table_cache_->clear();
972 host_table_cache_->clear(); 1032 host_table_cache_->clear();
973 url_redirect_table_cache_->clear(); 1033 url_redirect_table_cache_->clear();
974 host_redirect_table_cache_->clear(); 1034 host_redirect_table_cache_->clear();
975 manifest_table_cache_->clear(); 1035 manifest_table_cache_->clear();
1036 origin_table_cache_->clear();
976 1037
977 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, 1038 BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
978 base::Bind(&ResourcePrefetchPredictorTables::DeleteAllData, tables_)); 1039 base::Bind(&ResourcePrefetchPredictorTables::DeleteAllData, tables_));
979 } 1040 }
980 1041
981 void ResourcePrefetchPredictor::DeleteUrls(const history::URLRows& urls) { 1042 void ResourcePrefetchPredictor::DeleteUrls(const history::URLRows& urls) {
982 // Check all the urls in the database and pick out the ones that are present 1043 // Check all the urls in the database and pick out the ones that are present
983 // in the cache. 1044 // in the cache.
984 std::vector<std::string> urls_to_delete, hosts_to_delete; 1045 std::vector<std::string> urls_to_delete, hosts_to_delete;
985 std::vector<std::string> url_redirects_to_delete, host_redirects_to_delete; 1046 std::vector<std::string> url_redirects_to_delete, host_redirects_to_delete;
986 std::vector<std::string> manifest_hosts_to_delete; 1047 std::vector<std::string> manifest_hosts_to_delete;
1048 std::vector<std::string> origin_hosts_to_delete;
987 1049
988 for (const auto& it : urls) { 1050 for (const auto& it : urls) {
989 const std::string& url_spec = it.url().spec(); 1051 const std::string& url_spec = it.url().spec();
990 if (url_table_cache_->find(url_spec) != url_table_cache_->end()) { 1052 if (url_table_cache_->find(url_spec) != url_table_cache_->end()) {
alexilin 2017/04/10 14:58:28 TODO for future CLs: Use erase with iterator to av
991 urls_to_delete.push_back(url_spec); 1053 urls_to_delete.push_back(url_spec);
992 url_table_cache_->erase(url_spec); 1054 url_table_cache_->erase(url_spec);
993 } 1055 }
994 1056
995 if (url_redirect_table_cache_->find(url_spec) != 1057 if (url_redirect_table_cache_->find(url_spec) !=
996 url_redirect_table_cache_->end()) { 1058 url_redirect_table_cache_->end()) {
997 url_redirects_to_delete.push_back(url_spec); 1059 url_redirects_to_delete.push_back(url_spec);
998 url_redirect_table_cache_->erase(url_spec); 1060 url_redirect_table_cache_->erase(url_spec);
999 } 1061 }
1000 1062
1001 const std::string& host = it.url().host(); 1063 const std::string& host = it.url().host();
1002 if (host_table_cache_->find(host) != host_table_cache_->end()) { 1064 if (host_table_cache_->find(host) != host_table_cache_->end()) {
1003 hosts_to_delete.push_back(host); 1065 hosts_to_delete.push_back(host);
1004 host_table_cache_->erase(host); 1066 host_table_cache_->erase(host);
1005 } 1067 }
1006 1068
1007 if (host_redirect_table_cache_->find(host) != 1069 if (host_redirect_table_cache_->find(host) !=
1008 host_redirect_table_cache_->end()) { 1070 host_redirect_table_cache_->end()) {
1009 host_redirects_to_delete.push_back(host); 1071 host_redirects_to_delete.push_back(host);
1010 host_redirect_table_cache_->erase(host); 1072 host_redirect_table_cache_->erase(host);
1011 } 1073 }
1012 1074
1013 std::string manifest_host = history::HostForTopHosts(it.url()); 1075 std::string manifest_host = history::HostForTopHosts(it.url());
1014 if (manifest_table_cache_->find(manifest_host) != 1076 if (manifest_table_cache_->find(manifest_host) !=
1015 manifest_table_cache_->end()) { 1077 manifest_table_cache_->end()) {
1016 manifest_hosts_to_delete.push_back(manifest_host); 1078 manifest_hosts_to_delete.push_back(manifest_host);
1017 manifest_table_cache_->erase(manifest_host); 1079 manifest_table_cache_->erase(manifest_host);
1018 } 1080 }
1081
1082 if (origin_table_cache_->find(host) != origin_table_cache_->end()) {
1083 origin_hosts_to_delete.push_back(host);
1084 origin_table_cache_->erase(host);
1085 }
1019 } 1086 }
1020 1087
1021 if (!urls_to_delete.empty() || !hosts_to_delete.empty()) { 1088 if (!urls_to_delete.empty() || !hosts_to_delete.empty()) {
1022 BrowserThread::PostTask( 1089 BrowserThread::PostTask(
1023 BrowserThread::DB, FROM_HERE, 1090 BrowserThread::DB, FROM_HERE,
1024 base::Bind(&ResourcePrefetchPredictorTables::DeleteResourceData, 1091 base::Bind(&ResourcePrefetchPredictorTables::DeleteResourceData,
1025 tables_, urls_to_delete, hosts_to_delete)); 1092 tables_, urls_to_delete, hosts_to_delete));
1026 } 1093 }
1027 1094
1028 if (!url_redirects_to_delete.empty() || !host_redirects_to_delete.empty()) { 1095 if (!url_redirects_to_delete.empty() || !host_redirects_to_delete.empty()) {
1029 BrowserThread::PostTask( 1096 BrowserThread::PostTask(
1030 BrowserThread::DB, FROM_HERE, 1097 BrowserThread::DB, FROM_HERE,
1031 base::Bind(&ResourcePrefetchPredictorTables::DeleteRedirectData, 1098 base::Bind(&ResourcePrefetchPredictorTables::DeleteRedirectData,
1032 tables_, url_redirects_to_delete, host_redirects_to_delete)); 1099 tables_, url_redirects_to_delete, host_redirects_to_delete));
1033 } 1100 }
1034 1101
1035 if (!manifest_hosts_to_delete.empty()) { 1102 if (!manifest_hosts_to_delete.empty()) {
1036 BrowserThread::PostTask( 1103 BrowserThread::PostTask(
1037 BrowserThread::DB, FROM_HERE, 1104 BrowserThread::DB, FROM_HERE,
1038 base::Bind(&ResourcePrefetchPredictorTables::DeleteManifestData, 1105 base::Bind(&ResourcePrefetchPredictorTables::DeleteManifestData,
1039 tables_, manifest_hosts_to_delete)); 1106 tables_, manifest_hosts_to_delete));
1040 } 1107 }
1108
1109 if (!origin_hosts_to_delete.empty()) {
1110 BrowserThread::PostTask(
1111 BrowserThread::DB, FROM_HERE,
1112 base::Bind(&ResourcePrefetchPredictorTables::DeleteOriginData, tables_,
1113 origin_hosts_to_delete));
1114 }
1041 } 1115 }
1042 1116
1043 void ResourcePrefetchPredictor::RemoveOldestEntryInPrefetchDataMap( 1117 void ResourcePrefetchPredictor::RemoveOldestEntryInPrefetchDataMap(
1044 PrefetchKeyType key_type, 1118 PrefetchKeyType key_type,
1045 PrefetchDataMap* data_map) { 1119 PrefetchDataMap* data_map) {
1046 if (data_map->empty()) 1120 if (data_map->empty())
1047 return; 1121 return;
1048 1122
1049 uint64_t oldest_time = UINT64_MAX; 1123 uint64_t oldest_time = UINT64_MAX;
1050 std::string key_to_delete; 1124 std::string key_to_delete;
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1134 url_redirect_table_cache_.get()); 1208 url_redirect_table_cache_.get());
1135 } 1209 }
1136 } 1210 }
1137 1211
1138 // Host level data - no cutoff, always learn the navigation if enabled. 1212 // Host level data - no cutoff, always learn the navigation if enabled.
1139 const std::string host = summary.main_frame_url.host(); 1213 const std::string host = summary.main_frame_url.host();
1140 LearnNavigation(host, PREFETCH_KEY_TYPE_HOST, summary.subresource_requests, 1214 LearnNavigation(host, PREFETCH_KEY_TYPE_HOST, summary.subresource_requests,
1141 config_.max_hosts_to_track, host_table_cache_.get(), 1215 config_.max_hosts_to_track, host_table_cache_.get(),
1142 summary.initial_url.host(), host_redirect_table_cache_.get()); 1216 summary.initial_url.host(), host_redirect_table_cache_.get());
1143 1217
1218 if (config_.is_origin_prediction_enabled) {
1219 LearnOrigins(host, summary.origins, config_.max_hosts_to_track,
1220 origin_table_cache_.get());
1221 }
1222
1144 if (observer_) 1223 if (observer_)
1145 observer_->OnNavigationLearned(url_visit_count, summary); 1224 observer_->OnNavigationLearned(url_visit_count, summary);
1146 } 1225 }
1147 1226
1148 void ResourcePrefetchPredictor::LearnNavigation( 1227 void ResourcePrefetchPredictor::LearnNavigation(
1149 const std::string& key, 1228 const std::string& key,
1150 PrefetchKeyType key_type, 1229 PrefetchKeyType key_type,
1151 const std::vector<URLRequestSummary>& new_resources, 1230 const std::vector<URLRequestSummary>& new_resources,
1152 size_t max_data_map_size, 1231 size_t max_data_map_size,
1153 PrefetchDataMap* data_map, 1232 PrefetchDataMap* data_map,
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
1378 const RedirectData& url_redirect_data = 1457 const RedirectData& url_redirect_data =
1379 is_host ? empty_redirect_data : data; 1458 is_host ? empty_redirect_data : data;
1380 BrowserThread::PostTask( 1459 BrowserThread::PostTask(
1381 BrowserThread::DB, FROM_HERE, 1460 BrowserThread::DB, FROM_HERE,
1382 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, tables_, 1461 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, tables_,
1383 empty_data, empty_data, url_redirect_data, 1462 empty_data, empty_data, url_redirect_data,
1384 host_redirect_data)); 1463 host_redirect_data));
1385 } 1464 }
1386 } 1465 }
1387 1466
1467 void ResourcePrefetchPredictor::LearnOrigins(
1468 const std::string& host,
1469 const std::map<GURL, OriginRequestSummary>& summaries,
1470 size_t max_data_map_size,
1471 OriginDataMap* data_map) {
1472 if (host.size() > ResourcePrefetchPredictorTables::kMaxStringLength)
1473 return;
1474
1475 auto cache_entry = data_map->find(host);
1476 bool new_entry = cache_entry == data_map->end();
1477 if (new_entry) {
1478 if (data_map->size() >= max_data_map_size)
1479 RemoveOldestEntryInOriginDataMap(data_map);
1480
1481 cache_entry = data_map->insert({host, OriginData()}).first;
1482 OriginData& data = cache_entry->second;
1483 data.set_host(host);
1484 data.set_last_visit_time(base::Time::Now().ToInternalValue());
1485 size_t origins_size = summaries.size();
1486 auto ordered_origins =
1487 std::vector<const OriginRequestSummary*>(origins_size);
1488 for (auto& kv : summaries) {
alexilin 2017/04/10 14:58:28 const auto& ?
Benoit L 2017/04/11 09:04:05 Done.
1489 size_t index = kv.second.first_occurrence;
1490 DCHECK_LT(index, origins_size);
1491 ordered_origins[index] = &kv.second;
1492 }
1493
1494 for (const OriginRequestSummary* summary : ordered_origins) {
1495 auto* origin_to_add = data.add_origins();
1496 InitializeOriginStatFromOriginRequestSummary(origin_to_add, *summary);
1497 }
1498 } else {
1499 auto& data = cache_entry->second;
1500 data.set_last_visit_time(base::Time::Now().ToInternalValue());
1501
1502 std::map<GURL, int> old_index;
1503 int old_size = static_cast<int>(data.origins_size());
1504 for (int i = 0; i < old_size; ++i) {
1505 bool is_new =
1506 old_index.insert({GURL(data.origins(i).origin()), i}).second;
1507 DCHECK(is_new);
1508 }
1509
1510 // Update the old origins.
1511 for (int i = 0; i < old_size; ++i) {
1512 auto* old_origin = data.mutable_origins(i);
1513 GURL origin(old_origin->origin());
1514 auto it = summaries.find(origin);
1515 if (it == summaries.end()) {
1516 // miss
1517 old_origin->set_number_of_misses(old_origin->number_of_misses() + 1);
1518 old_origin->set_consecutive_misses(old_origin->consecutive_misses() +
1519 1);
1520 } else {
1521 // hit: update.
1522 const auto& new_origin = it->second;
1523 old_origin->set_always_access_network(new_origin.always_access_network);
1524 old_origin->set_accessed_network(true);
alexilin 2017/04/10 14:58:27 Why not `new_origin.accessed_network`?
Benoit L 2017/04/11 09:04:05 Oops. Done.
1525
1526 int position = new_origin.first_occurrence + 1;
1527 int total =
1528 old_origin->number_of_hits() + old_origin->number_of_misses();
1529 old_origin->set_average_position(
1530 ((old_origin->average_position() * total) + position) /
1531 (total + 1));
1532 old_origin->set_number_of_hits(old_origin->number_of_hits() + 1);
1533 old_origin->set_consecutive_misses(0);
1534 }
1535 }
1536
1537 // Add new origins.
1538 for (const auto& kv : summaries) {
1539 if (old_index.find(kv.first) != old_index.end())
1540 continue;
1541
1542 auto* origin_to_add = data.add_origins();
1543 InitializeOriginStatFromOriginRequestSummary(origin_to_add, kv.second);
1544 }
1545 }
1546
1547 // Trim and Sort.
1548 auto& data = cache_entry->second;
1549 ResourcePrefetchPredictorTables::TrimOrigins(&data,
1550 config_.max_consecutive_misses);
1551 ResourcePrefetchPredictorTables::SortOrigins(&data);
1552 if (data.origins_size() > static_cast<int>(config_.max_resources_per_entry)) {
1553 data.mutable_origins()->DeleteSubrange(
1554 config_.max_origins_per_entry,
1555 data.origins_size() - config_.max_origins_per_entry);
1556 }
1557
1558 // Update the database.
1559 if (data.origins_size() == 0) {
1560 data_map->erase(cache_entry);
1561 if (!new_entry) {
1562 BrowserThread::PostTask(
1563 BrowserThread::DB, FROM_HERE,
1564 base::Bind(&ResourcePrefetchPredictorTables::DeleteOriginData,
1565 tables_, std::vector<std::string>({host})));
1566 }
1567 } else {
1568 BrowserThread::PostTask(
1569 BrowserThread::DB, FROM_HERE,
1570 base::Bind(&ResourcePrefetchPredictorTables::UpdateOriginData, tables_,
1571 host, data));
1572 }
1573 }
1574
1575 void ResourcePrefetchPredictor::RemoveOldestEntryInOriginDataMap(
alexilin 2017/04/10 14:58:27 nit: Could you put this function before LearnNavig
Benoit L 2017/04/11 09:04:05 Done.
1576 OriginDataMap* data_map) {
1577 if (data_map->empty())
1578 return;
1579
1580 uint64_t oldest_time = UINT64_MAX;
1581 std::string key_to_delete;
1582 for (const auto& kv : *data_map) {
1583 const OriginData& data = kv.second;
1584 if (key_to_delete.empty() || data.last_visit_time() < oldest_time) {
1585 key_to_delete = kv.first;
1586 oldest_time = data.last_visit_time();
1587 }
1588 }
1589
1590 data_map->erase(key_to_delete);
1591 BrowserThread::PostTask(
1592 BrowserThread::DB, FROM_HERE,
1593 base::Bind(&ResourcePrefetchPredictorTables::DeleteOriginData, tables_,
1594 std::vector<std::string>({key_to_delete})));
1595 }
1596
1388 void ResourcePrefetchPredictor::ReportDatabaseReadiness( 1597 void ResourcePrefetchPredictor::ReportDatabaseReadiness(
1389 const history::TopHostsList& top_hosts) const { 1598 const history::TopHostsList& top_hosts) const {
1390 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1599 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1391 if (top_hosts.size() == 0) 1600 if (top_hosts.size() == 0)
1392 return; 1601 return;
1393 1602
1394 size_t count_in_cache = 0; 1603 size_t count_in_cache = 0;
1395 size_t total_visits = 0; 1604 size_t total_visits = 0;
1396 for (const std::pair<std::string, int>& top_host : top_hosts) { 1605 for (const std::pair<std::string, int>& top_host : top_hosts) {
1397 const std::string& host = top_host.first; 1606 const std::string& host = top_host.first;
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1493 TestObserver::~TestObserver() { 1702 TestObserver::~TestObserver() {
1494 predictor_->SetObserverForTesting(nullptr); 1703 predictor_->SetObserverForTesting(nullptr);
1495 } 1704 }
1496 1705
1497 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) 1706 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor)
1498 : predictor_(predictor) { 1707 : predictor_(predictor) {
1499 predictor_->SetObserverForTesting(this); 1708 predictor_->SetObserverForTesting(this);
1500 } 1709 }
1501 1710
1502 } // namespace predictors 1711 } // namespace predictors
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698