Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 203 std::any_of(std::begin(kFontMimeTypes), std::end(kFontMimeTypes), | 203 std::any_of(std::begin(kFontMimeTypes), std::end(kFontMimeTypes), |
| 204 [&mime_type](const std::string& mime) { | 204 [&mime_type](const std::string& mime) { |
| 205 return net::MatchesMimeType(mime, mime_type); | 205 return net::MatchesMimeType(mime, mime_type); |
| 206 }); | 206 }); |
| 207 if (found) | 207 if (found) |
| 208 return content::RESOURCE_TYPE_FONT_RESOURCE; | 208 return content::RESOURCE_TYPE_FONT_RESOURCE; |
| 209 } | 209 } |
| 210 return fallback; | 210 return fallback; |
| 211 } | 211 } |
| 212 | 212 |
| 213 // static | |
| 214 bool ResourcePrefetchPredictor::GetFinalRedirect( | |
| 215 const std::string& first_redirect, | |
| 216 RedirectDataMap* redirect_data_map, | |
| 217 std::string* final_redirect) { | |
| 218 DCHECK(final_redirect); | |
| 219 | |
| 220 RedirectDataMap::const_iterator it = redirect_data_map->find(first_redirect); | |
| 221 if (it == redirect_data_map->end()) | |
| 222 return false; | |
| 223 | |
| 224 const RedirectData& redirect_data = it->second; | |
| 225 int best_redirect_i = -1; | |
| 226 float best_confidence = 0.0; | |
| 227 for (int i = 0; i < redirect_data.redirect_endpoints_size(); ++i) { | |
| 228 const RedirectStat& redirect = redirect_data.redirect_endpoints(i); | |
| 229 float confidence = | |
| 230 (redirect.number_of_hits() + 0.0) / | |
| 231 (redirect.number_of_hits() + redirect.number_of_misses()); | |
| 232 if (confidence > best_confidence) { | |
| 233 best_redirect_i = i; | |
| 234 best_confidence = confidence; | |
| 235 } | |
| 236 } | |
| 237 | |
| 238 if (best_redirect_i == -1) | |
| 239 return false; | |
| 240 | |
| 241 const RedirectStat& best_redirect = | |
|
pasko
2016/10/07 13:44:27
std::max_element?
alexilin
2016/10/07 14:29:05
Well, it will lead to small overhead : we'll have
pasko
2016/10/07 15:42:44
Did you mean we would re-compute the confidence 2
alexilin
2016/10/07 16:33:44
I meant that std::max_element accepts comparer as
pasko
2016/10/07 17:18:54
Ah, sorry, you are right, this has a comparator, h
alexilin
2016/10/11 13:14:41
Done.
| |
| 242 redirect_data.redirect_endpoints(best_redirect_i); | |
| 243 const float kMinRedirectConfidenceToTriggerPrefetch = 0.7f; | |
| 244 const int kMinRedirectHitsToTriggerPrefetch = 2; | |
| 245 | |
| 246 if (best_confidence < kMinRedirectConfidenceToTriggerPrefetch || | |
| 247 best_redirect.number_of_hits() < kMinRedirectHitsToTriggerPrefetch) | |
| 248 return false; | |
| 249 | |
| 250 *final_redirect = best_redirect.url(); | |
| 251 return true; | |
| 252 } | |
| 253 | |
| 213 //////////////////////////////////////////////////////////////////////////////// | 254 //////////////////////////////////////////////////////////////////////////////// |
| 214 // ResourcePrefetchPredictor nested types. | 255 // ResourcePrefetchPredictor nested types. |
| 215 | 256 |
| 216 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary() | 257 ResourcePrefetchPredictor::URLRequestSummary::URLRequestSummary() |
| 217 : resource_type(content::RESOURCE_TYPE_LAST_TYPE), | 258 : resource_type(content::RESOURCE_TYPE_LAST_TYPE), |
| 218 priority(net::IDLE), | 259 priority(net::IDLE), |
| 219 was_cached(false), | 260 was_cached(false), |
| 220 has_validators(false), | 261 has_validators(false), |
| 221 always_revalidate(false) {} | 262 always_revalidate(false) {} |
| 222 | 263 |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 412 if (initialization_state_ != INITIALIZED) | 453 if (initialization_state_ != INITIALIZED) |
| 413 return; | 454 return; |
| 414 | 455 |
| 415 StopPrefetching(response.navigation_id.main_frame_url); | 456 StopPrefetching(response.navigation_id.main_frame_url); |
| 416 } | 457 } |
| 417 | 458 |
| 418 void ResourcePrefetchPredictor::OnMainFrameRedirect( | 459 void ResourcePrefetchPredictor::OnMainFrameRedirect( |
| 419 const URLRequestSummary& response) { | 460 const URLRequestSummary& response) { |
| 420 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 461 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 421 | 462 |
| 422 // Stop any inflight prefetching. Remove the older navigation. | |
| 423 StopPrefetching(response.navigation_id.main_frame_url); | |
| 424 | |
| 425 std::unique_ptr<PageRequestSummary> summary; | 463 std::unique_ptr<PageRequestSummary> summary; |
| 426 NavigationMap::iterator nav_it = | 464 NavigationMap::iterator nav_it = |
| 427 inflight_navigations_.find(response.navigation_id); | 465 inflight_navigations_.find(response.navigation_id); |
| 428 if (nav_it != inflight_navigations_.end()) { | 466 if (nav_it != inflight_navigations_.end()) { |
| 429 summary.reset(nav_it->second.release()); | 467 summary.reset(nav_it->second.release()); |
| 430 inflight_navigations_.erase(nav_it); | 468 inflight_navigations_.erase(nav_it); |
| 431 } | 469 } |
| 432 | 470 |
| 433 // The redirect url may be empty if the URL was invalid. | 471 // The redirect url may be empty if the URL was invalid. |
| 434 if (response.redirect_url.is_empty()) | 472 if (response.redirect_url.is_empty()) |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 485 std::unique_ptr<history::HistoryDBTask>(new GetUrlVisitCountTask( | 523 std::unique_ptr<history::HistoryDBTask>(new GetUrlVisitCountTask( |
| 486 navigation_id, std::move(summary), | 524 navigation_id, std::move(summary), |
| 487 base::Bind(&ResourcePrefetchPredictor::OnVisitCountLookup, | 525 base::Bind(&ResourcePrefetchPredictor::OnVisitCountLookup, |
| 488 AsWeakPtr()))), | 526 AsWeakPtr()))), |
| 489 &history_lookup_consumer_); | 527 &history_lookup_consumer_); |
| 490 } | 528 } |
| 491 | 529 |
| 492 bool ResourcePrefetchPredictor::GetPrefetchData(const GURL& main_frame_url, | 530 bool ResourcePrefetchPredictor::GetPrefetchData(const GURL& main_frame_url, |
| 493 std::vector<GURL>* urls) { | 531 std::vector<GURL>* urls) { |
| 494 DCHECK(urls); | 532 DCHECK(urls); |
| 495 | 533 DCHECK(urls->empty()); |
| 496 bool use_url_data = config_.IsPrefetchingEnabled(profile_) ? | 534 bool use_url_data = config_.IsPrefetchingEnabled(profile_) ? |
| 497 config_.IsURLPrefetchingEnabled(profile_) : | 535 config_.IsURLPrefetchingEnabled(profile_) : |
| 498 config_.IsURLLearningEnabled(); | 536 config_.IsURLLearningEnabled(); |
| 499 if (use_url_data) { | |
| 500 PrefetchDataMap::const_iterator iterator = | |
| 501 url_table_cache_->find(main_frame_url.spec()); | |
| 502 if (iterator != url_table_cache_->end()) | |
| 503 PopulatePrefetcherRequest(iterator->second, urls); | |
| 504 } | |
| 505 if (!urls->empty()) | |
| 506 return true; | |
| 507 | |
| 508 bool use_host_data = config_.IsPrefetchingEnabled(profile_) ? | 537 bool use_host_data = config_.IsPrefetchingEnabled(profile_) ? |
| 509 config_.IsHostPrefetchingEnabled(profile_) : | 538 config_.IsHostPrefetchingEnabled(profile_) : |
| 510 config_.IsHostLearningEnabled(); | 539 config_.IsHostLearningEnabled(); |
| 511 if (use_host_data) { | 540 |
| 512 PrefetchDataMap::const_iterator iterator = | 541 if (use_url_data && PopulatePrefetcherRequest(main_frame_url.spec(), |
| 513 host_table_cache_->find(main_frame_url.host()); | 542 url_table_cache_.get(), urls)) |
| 514 if (iterator != host_table_cache_->end()) | 543 return true; |
| 515 PopulatePrefetcherRequest(iterator->second, urls); | 544 |
| 545 if (use_host_data && PopulatePrefetcherRequest(main_frame_url.host(), | |
| 546 host_table_cache_.get(), urls)) | |
| 547 return true; | |
| 548 | |
| 549 std::string final_redirect; | |
| 550 if (GetFinalRedirect(main_frame_url.spec(), url_redirect_table_cache_.get(), | |
| 551 &final_redirect)) { | |
| 552 GURL redirect_url(final_redirect); | |
| 553 | |
| 554 if (use_url_data && PopulatePrefetcherRequest(redirect_url.spec(), | |
| 555 url_table_cache_.get(), urls)) | |
| 556 return true; | |
| 557 | |
| 558 if (use_host_data && | |
| 559 PopulatePrefetcherRequest(redirect_url.host(), host_table_cache_.get(), | |
| 560 urls)) | |
| 561 return true; | |
| 516 } | 562 } |
| 517 | 563 |
| 518 return !urls->empty(); | 564 return use_host_data && |
| 565 GetFinalRedirect(main_frame_url.host(), | |
| 566 host_redirect_table_cache_.get(), &final_redirect) && | |
| 567 PopulatePrefetcherRequest(final_redirect, host_table_cache_.get(), | |
| 568 urls); | |
| 519 } | 569 } |
| 520 | 570 |
| 521 void ResourcePrefetchPredictor::PopulatePrefetcherRequest( | 571 bool ResourcePrefetchPredictor::PopulatePrefetcherRequest( |
| 522 const PrefetchData& data, | 572 const std::string& main_frame_key, |
| 573 PrefetchDataMap* data_map, | |
| 523 std::vector<GURL>* urls) { | 574 std::vector<GURL>* urls) { |
| 524 for (const ResourceData& resource : data.resources()) { | 575 DCHECK(data_map); |
| 576 DCHECK(urls); | |
| 577 PrefetchDataMap::const_iterator it = data_map->find(main_frame_key); | |
| 578 if (it == data_map->end()) | |
| 579 return false; | |
| 580 | |
| 581 size_t initial_size = urls->size(); | |
| 582 for (const ResourceData& resource : it->second.resources()) { | |
| 525 float confidence = | 583 float confidence = |
| 526 static_cast<float>(resource.number_of_hits()) / | 584 static_cast<float>(resource.number_of_hits()) / |
| 527 (resource.number_of_hits() + resource.number_of_misses()); | 585 (resource.number_of_hits() + resource.number_of_misses()); |
| 528 if (confidence < config_.min_resource_confidence_to_trigger_prefetch || | 586 if (confidence < config_.min_resource_confidence_to_trigger_prefetch || |
| 529 resource.number_of_hits() < | 587 resource.number_of_hits() < |
| 530 config_.min_resource_hits_to_trigger_prefetch) { | 588 config_.min_resource_hits_to_trigger_prefetch) |
| 531 continue; | 589 continue; |
| 532 } | |
| 533 | 590 |
| 534 urls->push_back(GURL(resource.resource_url())); | 591 urls->push_back(GURL(resource.resource_url())); |
| 535 } | 592 } |
| 593 | |
| 594 return urls->size() > initial_size; | |
| 536 } | 595 } |
| 537 | 596 |
| 538 void ResourcePrefetchPredictor::StartPrefetching(const GURL& url) { | 597 void ResourcePrefetchPredictor::StartPrefetching(const GURL& url) { |
| 539 if (!prefetch_manager_.get()) // Prefetching not enabled. | 598 if (!prefetch_manager_.get()) // Prefetching not enabled. |
| 540 return; | 599 return; |
| 541 | 600 |
| 542 std::vector<GURL> subresource_urls; | 601 std::vector<GURL> subresource_urls; |
| 543 if (!GetPrefetchData(url, &subresource_urls)) { | 602 if (!GetPrefetchData(url, &subresource_urls)) { |
| 544 // No prefetching data at host or URL level. | 603 // No prefetching data at host or URL level. |
| 545 return; | 604 return; |
| (...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 993 } | 1052 } |
| 994 | 1053 |
| 995 if (need_to_add) { | 1054 if (need_to_add) { |
| 996 RedirectStat* redirect_to_add = data.add_redirect_endpoints(); | 1055 RedirectStat* redirect_to_add = data.add_redirect_endpoints(); |
| 997 redirect_to_add->set_url(final_redirect); | 1056 redirect_to_add->set_url(final_redirect); |
| 998 redirect_to_add->set_number_of_hits(1); | 1057 redirect_to_add->set_number_of_hits(1); |
| 999 } | 1058 } |
| 1000 } | 1059 } |
| 1001 | 1060 |
| 1002 RedirectData& data = cache_entry->second; | 1061 RedirectData& data = cache_entry->second; |
| 1003 // Trim and sort the redirects after the update. | 1062 // Trim the redirects after the update. |
| 1004 ResourcePrefetchPredictorTables::TrimRedirects( | 1063 ResourcePrefetchPredictorTables::TrimRedirects( |
| 1005 &data, config_.max_consecutive_misses); | 1064 &data, config_.max_consecutive_misses); |
| 1006 ResourcePrefetchPredictorTables::SortRedirects(&data); | |
| 1007 | 1065 |
| 1008 if (data.redirect_endpoints_size() == 0) { | 1066 if (data.redirect_endpoints_size() == 0) { |
| 1009 redirect_map->erase(cache_entry); | 1067 redirect_map->erase(cache_entry); |
| 1010 BrowserThread::PostTask( | 1068 BrowserThread::PostTask( |
| 1011 BrowserThread::DB, FROM_HERE, | 1069 BrowserThread::DB, FROM_HERE, |
| 1012 base::Bind( | 1070 base::Bind( |
| 1013 &ResourcePrefetchPredictorTables::DeleteSingleRedirectDataPoint, | 1071 &ResourcePrefetchPredictorTables::DeleteSingleRedirectDataPoint, |
| 1014 tables_, key, key_type)); | 1072 tables_, key, key_type)); |
| 1015 } else { | 1073 } else { |
| 1016 RedirectData empty_redirect_data; | 1074 RedirectData empty_redirect_data; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1068 // HistoryService is already loaded. Continue with Initialization. | 1126 // HistoryService is already loaded. Continue with Initialization. |
| 1069 OnHistoryAndCacheLoaded(); | 1127 OnHistoryAndCacheLoaded(); |
| 1070 return; | 1128 return; |
| 1071 } | 1129 } |
| 1072 DCHECK(!history_service_observer_.IsObserving(history_service)); | 1130 DCHECK(!history_service_observer_.IsObserving(history_service)); |
| 1073 history_service_observer_.Add(history_service); | 1131 history_service_observer_.Add(history_service); |
| 1074 return; | 1132 return; |
| 1075 } | 1133 } |
| 1076 | 1134 |
| 1077 } // namespace predictors | 1135 } // namespace predictors |
| OLD | NEW |