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 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
383 std::any_of(std::begin(kFontMimeTypes), std::end(kFontMimeTypes), | 383 std::any_of(std::begin(kFontMimeTypes), std::end(kFontMimeTypes), |
384 [&mime_type](const std::string& mime) { | 384 [&mime_type](const std::string& mime) { |
385 return net::MatchesMimeType(mime, mime_type); | 385 return net::MatchesMimeType(mime, mime_type); |
386 }); | 386 }); |
387 if (found) | 387 if (found) |
388 return content::RESOURCE_TYPE_FONT_RESOURCE; | 388 return content::RESOURCE_TYPE_FONT_RESOURCE; |
389 } | 389 } |
390 return fallback; | 390 return fallback; |
391 } | 391 } |
392 | 392 |
393 // static | |
394 bool ResourcePrefetchPredictor::GetRedirectEndpoint( | 393 bool ResourcePrefetchPredictor::GetRedirectEndpoint( |
395 const std::string& first_redirect, | 394 const std::string& entry_point, |
396 const RedirectDataMap& redirect_data_map, | 395 const RedirectDataMap& redirect_data_map, |
397 std::string* final_redirect) { | 396 std::string* redirect_endpoint) const { |
398 DCHECK(final_redirect); | 397 DCHECK(redirect_endpoint); |
399 | 398 |
400 RedirectDataMap::const_iterator it = redirect_data_map.find(first_redirect); | 399 RedirectDataMap::const_iterator it = redirect_data_map.find(entry_point); |
401 if (it == redirect_data_map.end()) | 400 if (it == redirect_data_map.end()) { |
402 return false; | 401 // Fallback to fetching URLs based on the incoming URL/host. |
402 *redirect_endpoint = entry_point; | |
403 return true; | |
404 } | |
403 | 405 |
404 const RedirectData& redirect_data = it->second; | 406 const RedirectData& redirect_data = it->second; |
405 auto best_redirect = std::max_element( | 407 DCHECK_GT(redirect_data.redirect_endpoints_size(), 0); |
406 redirect_data.redirect_endpoints().begin(), | 408 if (redirect_data.redirect_endpoints_size() > 1) { |
alexilin
2017/04/06 13:05:21
This is the same thing as to require minimum numbe
| |
407 redirect_data.redirect_endpoints().end(), | 409 // Predictor observed multiple redirect destinations recently. Redirect |
408 [](const RedirectStat& x, const RedirectStat& y) { | 410 // endpoint is ambiguous. |
409 return ComputeRedirectConfidence(x) < ComputeRedirectConfidence(y); | 411 return false; |
410 }); | 412 } |
411 | 413 |
412 const float kMinRedirectConfidenceToTriggerPrefetch = 0.7f; | 414 // The threshold is higher than the threshold for resources because the |
415 // redirect misprediction causes the waste of whole prefetch. | |
416 const float kMinRedirectConfidenceToTriggerPrefetch = 0.9f; | |
413 const int kMinRedirectHitsToTriggerPrefetch = 2; | 417 const int kMinRedirectHitsToTriggerPrefetch = 2; |
414 | 418 |
415 if (best_redirect == redirect_data.redirect_endpoints().end() || | 419 const RedirectStat& redirect = redirect_data.redirect_endpoints(0); |
416 ComputeRedirectConfidence(*best_redirect) < | 420 if (ComputeRedirectConfidence(redirect) < |
417 kMinRedirectConfidenceToTriggerPrefetch || | 421 kMinRedirectConfidenceToTriggerPrefetch || |
418 best_redirect->number_of_hits() < kMinRedirectHitsToTriggerPrefetch) | 422 (redirect.number_of_hits() < kMinRedirectHitsToTriggerPrefetch && |
423 redirect.url() != entry_point)) { | |
419 return false; | 424 return false; |
425 } | |
420 | 426 |
421 *final_redirect = best_redirect->url(); | 427 *redirect_endpoint = redirect.url(); |
422 return true; | 428 return true; |
423 } | 429 } |
424 | 430 |
425 // static | 431 // static |
426 void ResourcePrefetchPredictor::SetAllowPortInUrlsForTesting(bool state) { | 432 void ResourcePrefetchPredictor::SetAllowPortInUrlsForTesting(bool state) { |
427 g_allow_port_in_urls = state; | 433 g_allow_port_in_urls = state; |
428 } | 434 } |
429 | 435 |
430 //////////////////////////////////////////////////////////////////////////////// | 436 //////////////////////////////////////////////////////////////////////////////// |
431 // ResourcePrefetchPredictor nested types. | 437 // ResourcePrefetchPredictor nested types. |
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
821 } | 827 } |
822 } | 828 } |
823 | 829 |
824 bool ResourcePrefetchPredictor::GetPrefetchData( | 830 bool ResourcePrefetchPredictor::GetPrefetchData( |
825 const GURL& main_frame_url, | 831 const GURL& main_frame_url, |
826 ResourcePrefetchPredictor::Prediction* prediction) const { | 832 ResourcePrefetchPredictor::Prediction* prediction) const { |
827 std::vector<GURL>* urls = | 833 std::vector<GURL>* urls = |
828 prediction ? &prediction->subresource_urls : nullptr; | 834 prediction ? &prediction->subresource_urls : nullptr; |
829 DCHECK(!urls || urls->empty()); | 835 DCHECK(!urls || urls->empty()); |
830 | 836 |
831 // Fetch URLs based on a redirect endpoint for URL/host first. | 837 // Fetch resources using URL-keyed data first. |
832 std::string redirect_endpoint; | 838 std::string redirect_endpoint; |
839 const std::string& main_frame_url_spec = main_frame_url.spec(); | |
833 if (config_.is_url_learning_enabled && | 840 if (config_.is_url_learning_enabled && |
834 GetRedirectEndpoint(main_frame_url.spec(), *url_redirect_table_cache_, | 841 GetRedirectEndpoint(main_frame_url_spec, *url_redirect_table_cache_, |
835 &redirect_endpoint) && | 842 &redirect_endpoint) && |
836 PopulatePrefetcherRequest(redirect_endpoint, *url_table_cache_, urls)) { | 843 PopulatePrefetcherRequest(redirect_endpoint, *url_table_cache_, urls)) { |
837 if (prediction) { | 844 if (prediction) { |
838 prediction->is_host = false; | 845 prediction->is_host = false; |
839 prediction->is_redirected = true; | |
840 prediction->main_frame_key = redirect_endpoint; | 846 prediction->main_frame_key = redirect_endpoint; |
847 prediction->is_redirected = (redirect_endpoint != main_frame_url_spec); | |
841 } | 848 } |
842 return true; | 849 return true; |
843 } | 850 } |
844 | 851 |
845 if (GetRedirectEndpoint(main_frame_url.host(), *host_redirect_table_cache_, | 852 // Use host data if the URL-based prediction isn't available. |
853 std::string main_frame_url_host = main_frame_url.host(); | |
854 if (GetRedirectEndpoint(main_frame_url_host, *host_redirect_table_cache_, | |
846 &redirect_endpoint) && | 855 &redirect_endpoint) && |
847 PopulatePrefetcherRequest(redirect_endpoint, *host_table_cache_, urls)) { | 856 PopulatePrefetcherRequest(redirect_endpoint, *host_table_cache_, urls)) { |
848 if (prediction) { | 857 if (prediction) { |
849 prediction->is_host = true; | 858 prediction->is_host = true; |
850 prediction->is_redirected = true; | |
851 prediction->main_frame_key = redirect_endpoint; | 859 prediction->main_frame_key = redirect_endpoint; |
860 prediction->is_redirected = (redirect_endpoint != main_frame_url_host); | |
852 } | 861 } |
853 return true; | 862 return true; |
854 } | 863 } |
855 | |
856 // Fallback to fetching URLs based on the incoming URL/host. | |
857 if (config_.is_url_learning_enabled && | |
858 PopulatePrefetcherRequest(main_frame_url.spec(), *url_table_cache_, | |
859 urls)) { | |
860 if (prediction) { | |
861 prediction->is_host = false; | |
862 prediction->is_redirected = false; | |
863 prediction->main_frame_key = main_frame_url.spec(); | |
864 } | |
865 return true; | |
866 } | |
867 | |
868 if (PopulatePrefetcherRequest(main_frame_url.host(), *host_table_cache_, | |
869 urls)) { | |
870 if (prediction) { | |
871 prediction->is_host = true; | |
872 prediction->is_redirected = false; | |
873 prediction->main_frame_key = main_frame_url.host(); | |
874 } | |
875 return true; | |
876 } | |
877 | 864 |
878 return false; | 865 return false; |
879 } | 866 } |
880 | 867 |
881 bool ResourcePrefetchPredictor::PopulatePrefetcherRequest( | 868 bool ResourcePrefetchPredictor::PopulatePrefetcherRequest( |
882 const std::string& main_frame_key, | 869 const std::string& main_frame_key, |
883 const PrefetchDataMap& data_map, | 870 const PrefetchDataMap& data_map, |
884 std::vector<GURL>* urls) const { | 871 std::vector<GURL>* urls) const { |
885 PrefetchDataMap::const_iterator it = data_map.find(main_frame_key); | 872 PrefetchDataMap::const_iterator it = data_map.find(main_frame_key); |
886 if (it == data_map.end()) | 873 if (it == data_map.end()) |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1314 bool is_host = key_type == PREFETCH_KEY_TYPE_HOST; | 1301 bool is_host = key_type == PREFETCH_KEY_TYPE_HOST; |
1315 const PrefetchData& host_data = is_host ? data : empty_data; | 1302 const PrefetchData& host_data = is_host ? data : empty_data; |
1316 const PrefetchData& url_data = is_host ? empty_data : data; | 1303 const PrefetchData& url_data = is_host ? empty_data : data; |
1317 BrowserThread::PostTask( | 1304 BrowserThread::PostTask( |
1318 BrowserThread::DB, FROM_HERE, | 1305 BrowserThread::DB, FROM_HERE, |
1319 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, tables_, | 1306 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, tables_, |
1320 url_data, host_data, empty_redirect_data, | 1307 url_data, host_data, empty_redirect_data, |
1321 empty_redirect_data)); | 1308 empty_redirect_data)); |
1322 } | 1309 } |
1323 | 1310 |
1324 if (key != key_before_redirects) { | 1311 LearnRedirect(key_before_redirects, key_type, key, max_data_map_size, |
1325 LearnRedirect(key_before_redirects, key_type, key, max_data_map_size, | 1312 redirect_map); |
1326 redirect_map); | |
1327 } | |
1328 } | 1313 } |
1329 | 1314 |
1330 void ResourcePrefetchPredictor::LearnRedirect(const std::string& key, | 1315 void ResourcePrefetchPredictor::LearnRedirect(const std::string& key, |
1331 PrefetchKeyType key_type, | 1316 PrefetchKeyType key_type, |
1332 const std::string& final_redirect, | 1317 const std::string& final_redirect, |
1333 size_t max_redirect_map_size, | 1318 size_t max_redirect_map_size, |
1334 RedirectDataMap* redirect_map) { | 1319 RedirectDataMap* redirect_map) { |
1335 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1320 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
1336 // If the primary key is too long reject it. | 1321 // If the primary key is too long reject it. |
1337 if (key.length() > ResourcePrefetchPredictorTables::kMaxStringLength) | 1322 if (key.length() > ResourcePrefetchPredictorTables::kMaxStringLength) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1369 if (need_to_add) { | 1354 if (need_to_add) { |
1370 RedirectStat* redirect_to_add = data.add_redirect_endpoints(); | 1355 RedirectStat* redirect_to_add = data.add_redirect_endpoints(); |
1371 redirect_to_add->set_url(final_redirect); | 1356 redirect_to_add->set_url(final_redirect); |
1372 redirect_to_add->set_number_of_hits(1); | 1357 redirect_to_add->set_number_of_hits(1); |
1373 } | 1358 } |
1374 } | 1359 } |
1375 | 1360 |
1376 RedirectData& data = cache_entry->second; | 1361 RedirectData& data = cache_entry->second; |
1377 // Trim the redirects after the update. | 1362 // Trim the redirects after the update. |
1378 ResourcePrefetchPredictorTables::TrimRedirects( | 1363 ResourcePrefetchPredictorTables::TrimRedirects( |
1379 &data, config_.max_consecutive_misses); | 1364 &data, config_.max_redirect_consecutive_misses); |
1380 | 1365 |
1381 if (data.redirect_endpoints_size() == 0) { | 1366 if (data.redirect_endpoints_size() == 0) { |
1382 redirect_map->erase(cache_entry); | 1367 redirect_map->erase(cache_entry); |
1383 BrowserThread::PostTask( | 1368 BrowserThread::PostTask( |
1384 BrowserThread::DB, FROM_HERE, | 1369 BrowserThread::DB, FROM_HERE, |
1385 base::Bind( | 1370 base::Bind( |
1386 &ResourcePrefetchPredictorTables::DeleteSingleRedirectDataPoint, | 1371 &ResourcePrefetchPredictorTables::DeleteSingleRedirectDataPoint, |
1387 tables_, key, key_type)); | 1372 tables_, key, key_type)); |
1388 } else { | 1373 } else { |
1389 RedirectData empty_redirect_data; | 1374 RedirectData empty_redirect_data; |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1511 TestObserver::~TestObserver() { | 1496 TestObserver::~TestObserver() { |
1512 predictor_->SetObserverForTesting(nullptr); | 1497 predictor_->SetObserverForTesting(nullptr); |
1513 } | 1498 } |
1514 | 1499 |
1515 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) | 1500 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) |
1516 : predictor_(predictor) { | 1501 : predictor_(predictor) { |
1517 predictor_->SetObserverForTesting(this); | 1502 predictor_->SetObserverForTesting(this); |
1518 } | 1503 } |
1519 | 1504 |
1520 } // namespace predictors | 1505 } // namespace predictors |
OLD | NEW |