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 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 |