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

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

Issue 2268283005: predictors: Refactor the resource_prefetch_predictor database handling. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 4 years, 3 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
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/macros.h" 12 #include "base/macros.h"
13 #include "base/metrics/histogram.h" 13 #include "base/metrics/histogram.h"
14 #include "base/metrics/sparse_histogram.h" 14 #include "base/metrics/sparse_histogram.h"
15 #include "base/strings/string_number_conversions.h" 15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/stringprintf.h" 16 #include "base/strings/stringprintf.h"
17 #include "base/time/time.h" 17 #include "base/time/time.h"
18 #include "chrome/browser/history/history_service_factory.h" 18 #include "chrome/browser/history/history_service_factory.h"
19 #include "chrome/browser/predictors/predictor_database.h" 19 #include "chrome/browser/predictors/predictor_database.h"
20 #include "chrome/browser/predictors/predictor_database_factory.h" 20 #include "chrome/browser/predictors/predictor_database_factory.h"
21 #include "chrome/browser/predictors/resource_prefetch_predictor.pb.h"
21 #include "chrome/browser/predictors/resource_prefetcher_manager.h" 22 #include "chrome/browser/predictors/resource_prefetcher_manager.h"
22 #include "chrome/browser/profiles/profile.h" 23 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/common/chrome_switches.h" 24 #include "chrome/common/chrome_switches.h"
24 #include "chrome/common/url_constants.h" 25 #include "chrome/common/url_constants.h"
25 #include "components/history/core/browser/history_database.h" 26 #include "components/history/core/browser/history_database.h"
26 #include "components/history/core/browser/history_db_task.h" 27 #include "components/history/core/browser/history_db_task.h"
27 #include "components/history/core/browser/history_service.h" 28 #include "components/history/core/browser/history_service.h"
28 #include "components/mime_util/mime_util.h" 29 #include "components/mime_util/mime_util.h"
29 #include "content/public/browser/browser_thread.h" 30 #include "content/public/browser/browser_thread.h"
30 #include "content/public/browser/navigation_controller.h" 31 #include "content/public/browser/navigation_controller.h"
31 #include "content/public/browser/resource_request_info.h" 32 #include "content/public/browser/resource_request_info.h"
32 #include "content/public/browser/web_contents.h" 33 #include "content/public/browser/web_contents.h"
33 #include "net/base/mime_util.h" 34 #include "net/base/mime_util.h"
34 #include "net/base/network_change_notifier.h" 35 #include "net/base/network_change_notifier.h"
35 #include "net/http/http_response_headers.h" 36 #include "net/http/http_response_headers.h"
36 #include "net/url_request/url_request.h" 37 #include "net/url_request/url_request.h"
37 #include "net/url_request/url_request_context_getter.h" 38 #include "net/url_request/url_request_context_getter.h"
38 39
39 using content::BrowserThread; 40 using content::BrowserThread;
41 using chrome_browser_predictors::ResourceData;
40 42
41 namespace { 43 namespace {
42 44
43 // Sorted by decreasing likelihood according to HTTP archive. 45 // Sorted by decreasing likelihood according to HTTP archive.
44 const char* kFontMimeTypes[] = {"font/woff2", 46 const char* kFontMimeTypes[] = {"font/woff2",
45 "application/x-font-woff", 47 "application/x-font-woff",
46 "application/font-woff", 48 "application/font-woff",
47 "application/font-woff2", 49 "application/font-woff2",
48 "font/x-woff", 50 "font/x-woff",
49 "application/x-font-ttf", 51 "application/x-font-ttf",
(...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 PopulatePrefetcherRequest(iterator->second, prefetch_requests); 702 PopulatePrefetcherRequest(iterator->second, prefetch_requests);
701 } 703 }
702 } 704 }
703 705
704 return !prefetch_requests->empty(); 706 return !prefetch_requests->empty();
705 } 707 }
706 708
707 void ResourcePrefetchPredictor::PopulatePrefetcherRequest( 709 void ResourcePrefetchPredictor::PopulatePrefetcherRequest(
708 const PrefetchData& data, 710 const PrefetchData& data,
709 ResourcePrefetcher::RequestVector* requests) { 711 ResourcePrefetcher::RequestVector* requests) {
710 for (ResourceRows::const_iterator it = data.resources.begin(); 712 for (const ResourceData& resource : data.resources) {
711 it != data.resources.end(); ++it) { 713 float confidence =
712 float confidence = static_cast<float>(it->number_of_hits) / 714 static_cast<float>(resource.number_of_hits()) /
713 (it->number_of_hits + it->number_of_misses); 715 (resource.number_of_hits() + resource.number_of_misses());
714 if (confidence < config_.min_resource_confidence_to_trigger_prefetch || 716 if (confidence < config_.min_resource_confidence_to_trigger_prefetch ||
715 it->number_of_hits < config_.min_resource_hits_to_trigger_prefetch) { 717 resource.number_of_hits() <
718 config_.min_resource_hits_to_trigger_prefetch) {
716 continue; 719 continue;
717 } 720 }
718 721
719 ResourcePrefetcher::Request* req = new ResourcePrefetcher::Request( 722 ResourcePrefetcher::Request* req =
720 it->resource_url); 723 new ResourcePrefetcher::Request(GURL(resource.resource_url()));
721 requests->push_back(req); 724 requests->push_back(req);
722 } 725 }
723 } 726 }
724 727
725 void ResourcePrefetchPredictor::StartPrefetching( 728 void ResourcePrefetchPredictor::StartPrefetching(
726 const NavigationID& navigation_id) { 729 const NavigationID& navigation_id) {
727 if (!prefetch_manager_.get()) // Prefetching not enabled. 730 if (!prefetch_manager_.get()) // Prefetching not enabled.
728 return; 731 return;
729 732
730 // Prefer URL based data first. 733 // Prefer URL based data first.
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
939 } 942 }
940 943
941 void ResourcePrefetchPredictor::LearnNavigation( 944 void ResourcePrefetchPredictor::LearnNavigation(
942 const std::string& key, 945 const std::string& key,
943 PrefetchKeyType key_type, 946 PrefetchKeyType key_type,
944 const std::vector<URLRequestSummary>& new_resources, 947 const std::vector<URLRequestSummary>& new_resources,
945 size_t max_data_map_size, 948 size_t max_data_map_size,
946 PrefetchDataMap* data_map) { 949 PrefetchDataMap* data_map) {
947 DCHECK_CURRENTLY_ON(BrowserThread::UI); 950 DCHECK_CURRENTLY_ON(BrowserThread::UI);
948 951
952 using ResourceType = ::chrome_browser_predictors::ResourceData_ResourceType;
953 using Priority = ::chrome_browser_predictors::ResourceData_Priority;
954
949 // If the primary key is too long reject it. 955 // If the primary key is too long reject it.
950 if (key.length() > ResourcePrefetchPredictorTables::kMaxStringLength) { 956 if (key.length() > ResourcePrefetchPredictorTables::kMaxStringLength) {
951 if (key_type == PREFETCH_KEY_TYPE_HOST) 957 if (key_type == PREFETCH_KEY_TYPE_HOST)
952 RecordNavigationEvent(NAVIGATION_EVENT_HOST_TOO_LONG); 958 RecordNavigationEvent(NAVIGATION_EVENT_HOST_TOO_LONG);
953 else 959 else
954 RecordNavigationEvent(NAVIGATION_EVENT_MAIN_FRAME_URL_TOO_LONG); 960 RecordNavigationEvent(NAVIGATION_EVENT_MAIN_FRAME_URL_TOO_LONG);
955 return; 961 return;
956 } 962 }
957 963
958 PrefetchDataMap::iterator cache_entry = data_map->find(key); 964 PrefetchDataMap::iterator cache_entry = data_map->find(key);
959 if (cache_entry == data_map->end()) { 965 if (cache_entry == data_map->end()) {
960 if (data_map->size() >= max_data_map_size) { 966 if (data_map->size() >= max_data_map_size) {
961 // The table is full, delete an entry. 967 // The table is full, delete an entry.
962 RemoveOldestEntryInPrefetchDataMap(key_type, data_map); 968 RemoveOldestEntryInPrefetchDataMap(key_type, data_map);
963 } 969 }
964 970
965 cache_entry = data_map->insert(std::make_pair( 971 cache_entry = data_map->insert(std::make_pair(
966 key, PrefetchData(key_type, key))).first; 972 key, PrefetchData(key_type, key))).first;
967 cache_entry->second.last_visit = base::Time::Now(); 973 cache_entry->second.last_visit = base::Time::Now();
968 size_t new_resources_size = new_resources.size(); 974 size_t new_resources_size = new_resources.size();
969 std::set<GURL> resources_seen; 975 std::set<GURL> resources_seen;
970 for (size_t i = 0; i < new_resources_size; ++i) { 976 for (size_t i = 0; i < new_resources_size; ++i) {
971 if (resources_seen.find(new_resources[i].resource_url) != 977 if (resources_seen.find(new_resources[i].resource_url) !=
972 resources_seen.end()) { 978 resources_seen.end()) {
973 continue; 979 continue;
974 } 980 }
975 ResourceRow row_to_add; 981 ResourceData resource_to_add;
976 row_to_add.resource_url = new_resources[i].resource_url; 982 resource_to_add.set_resource_url(new_resources[i].resource_url.spec());
977 row_to_add.resource_type = new_resources[i].resource_type; 983 resource_to_add.set_resource_type(
978 row_to_add.number_of_hits = 1; 984 static_cast<ResourceType>(new_resources[i].resource_type));
979 row_to_add.average_position = i + 1; 985 resource_to_add.set_number_of_hits(1);
980 row_to_add.priority = new_resources[i].priority; 986 resource_to_add.set_average_position(i + 1);
981 row_to_add.has_validators = new_resources[i].has_validators; 987 resource_to_add.set_priority(
982 row_to_add.always_revalidate = new_resources[i].always_revalidate; 988 static_cast<Priority>(new_resources[i].priority));
983 cache_entry->second.resources.push_back(row_to_add); 989 resource_to_add.set_has_validators(new_resources[i].has_validators);
990 resource_to_add.set_always_revalidate(new_resources[i].always_revalidate);
991 cache_entry->second.resources.push_back(resource_to_add);
984 resources_seen.insert(new_resources[i].resource_url); 992 resources_seen.insert(new_resources[i].resource_url);
985 } 993 }
986 } else { 994 } else {
987 ResourceRows& old_resources = cache_entry->second.resources; 995 std::vector<ResourceData>& old_resources = cache_entry->second.resources;
988 cache_entry->second.last_visit = base::Time::Now(); 996 cache_entry->second.last_visit = base::Time::Now();
989 997
990 // Build indices over the data. 998 // Build indices over the data.
991 std::map<GURL, int> new_index, old_index; 999 std::map<GURL, int> new_index, old_index;
992 int new_resources_size = static_cast<int>(new_resources.size()); 1000 int new_resources_size = static_cast<int>(new_resources.size());
993 for (int i = 0; i < new_resources_size; ++i) { 1001 for (int i = 0; i < new_resources_size; ++i) {
994 const URLRequestSummary& summary = new_resources[i]; 1002 const URLRequestSummary& summary = new_resources[i];
995 // Take the first occurence of every url. 1003 // Take the first occurence of every url.
996 if (new_index.find(summary.resource_url) == new_index.end()) 1004 if (new_index.find(summary.resource_url) == new_index.end())
997 new_index[summary.resource_url] = i; 1005 new_index[summary.resource_url] = i;
998 } 1006 }
999 int old_resources_size = static_cast<int>(old_resources.size()); 1007 int old_resources_size = static_cast<int>(old_resources.size());
1000 for (int i = 0; i < old_resources_size; ++i) { 1008 for (int i = 0; i < old_resources_size; ++i) {
1001 const ResourceRow& row = old_resources[i]; 1009 const ResourceData& resource = old_resources[i];
1002 DCHECK(old_index.find(row.resource_url) == old_index.end()); 1010 GURL resource_url(resource.resource_url());
1003 old_index[row.resource_url] = i; 1011 DCHECK(old_index.find(resource_url) == old_index.end());
1012 old_index[resource_url] = i;
1004 } 1013 }
1005 1014
1006 // Go through the old urls and update their hit/miss counts. 1015 // Go through the old urls and update their hit/miss counts.
1007 for (int i = 0; i < old_resources_size; ++i) { 1016 for (int i = 0; i < old_resources_size; ++i) {
1008 ResourceRow& old_row = old_resources[i]; 1017 ResourceData& old_resource = old_resources[i];
1009 if (new_index.find(old_row.resource_url) == new_index.end()) { 1018 GURL resource_url(old_resource.resource_url());
1010 ++old_row.number_of_misses; 1019 if (new_index.find(resource_url) == new_index.end()) {
1011 ++old_row.consecutive_misses; 1020 old_resource.set_number_of_misses(old_resource.number_of_misses() + 1);
1021 old_resource.set_consecutive_misses(old_resource.consecutive_misses() +
1022 1);
1012 } else { 1023 } else {
1013 const URLRequestSummary& new_row = 1024 const URLRequestSummary& new_summary =
1014 new_resources[new_index[old_row.resource_url]]; 1025 new_resources[new_index[GURL(old_resource.resource_url())]];
1015 1026
1016 // Update the resource type since it could have changed. 1027 // Update the resource type and priority.
1017 if (new_row.resource_type != content::RESOURCE_TYPE_LAST_TYPE) 1028 if (new_summary.resource_type != content::RESOURCE_TYPE_LAST_TYPE)
1018 old_row.resource_type = new_row.resource_type; 1029 old_resource.set_resource_type(
1030 static_cast<ResourceType>(new_summary.resource_type));
1031 old_resource.set_priority(static_cast<Priority>(new_summary.priority));
1019 1032
1020 old_row.priority = new_row.priority; 1033 int position = new_index[resource_url] + 1;
1021 1034 int total =
1022 int position = new_index[old_row.resource_url] + 1; 1035 old_resource.number_of_hits() + old_resource.number_of_misses();
1023 int total = old_row.number_of_hits + old_row.number_of_misses; 1036 old_resource.set_average_position(
1024 old_row.average_position = 1037 ((old_resource.average_position() * total) + position) /
1025 ((old_row.average_position * total) + position) / (total + 1); 1038 (total + 1));
1026 ++old_row.number_of_hits; 1039 old_resource.set_number_of_hits(old_resource.number_of_hits() + 1);
1027 old_row.consecutive_misses = 0; 1040 old_resource.set_consecutive_misses(0);
1028 } 1041 }
1029 } 1042 }
1030 1043
1031 // Add the new ones that we have not seen before. 1044 // Add the new ones that we have not seen before.
1032 for (int i = 0; i < new_resources_size; ++i) { 1045 for (int i = 0; i < new_resources_size; ++i) {
1033 const URLRequestSummary& summary = new_resources[i]; 1046 const URLRequestSummary& summary = new_resources[i];
1034 if (old_index.find(summary.resource_url) != old_index.end()) 1047 if (old_index.find(summary.resource_url) != old_index.end())
1035 continue; 1048 continue;
1036 1049
1037 // Only need to add new stuff. 1050 // Only need to add new stuff.
1038 ResourceRow row_to_add; 1051 ResourceData resource_to_add;
1039 row_to_add.resource_url = summary.resource_url; 1052 resource_to_add.set_resource_url(summary.resource_url.spec());
1040 row_to_add.resource_type = summary.resource_type; 1053 resource_to_add.set_resource_type(
1041 row_to_add.number_of_hits = 1; 1054 static_cast<ResourceType>(summary.resource_type));
1042 row_to_add.average_position = i + 1; 1055 resource_to_add.set_number_of_hits(1);
1043 row_to_add.priority = summary.priority; 1056 resource_to_add.set_average_position(i + 1);
1044 row_to_add.has_validators = new_resources[i].has_validators; 1057 resource_to_add.set_priority(static_cast<Priority>(summary.priority));
1045 row_to_add.always_revalidate = new_resources[i].always_revalidate; 1058 resource_to_add.set_has_validators(new_resources[i].has_validators);
1046 old_resources.push_back(row_to_add); 1059 resource_to_add.set_always_revalidate(new_resources[i].always_revalidate);
1060 old_resources.push_back(resource_to_add);
1047 1061
1048 // To ensure we dont add the same url twice. 1062 // To ensure we dont add the same url twice.
1049 old_index[summary.resource_url] = 0; 1063 old_index[summary.resource_url] = 0;
1050 } 1064 }
1051 } 1065 }
1052 1066
1053 // Trim and sort the resources after the update. 1067 // Trim and sort the resources after the update.
1054 ResourceRows& resources = cache_entry->second.resources; 1068 std::vector<ResourceData>& resources = cache_entry->second.resources;
1055 for (ResourceRows::iterator it = resources.begin(); 1069 for (std::vector<ResourceData>::iterator it = resources.begin();
1056 it != resources.end();) { 1070 it != resources.end();) {
1057 it->UpdateScore(); 1071 ResourcePrefetchPredictorTables::UpdateResourceScore(&(*it));
1058 if (it->consecutive_misses >= config_.max_consecutive_misses) 1072 if (it->consecutive_misses() >= config_.max_consecutive_misses)
1059 it = resources.erase(it); 1073 it = resources.erase(it);
1060 else 1074 else
1061 ++it; 1075 ++it;
1062 } 1076 }
1063 ResourcePrefetchPredictorTables::SortResourceRows(&resources); 1077 ResourcePrefetchPredictorTables::SortResources(&resources);
1064 if (resources.size() > config_.max_resources_per_entry) 1078 if (resources.size() > config_.max_resources_per_entry)
1065 resources.resize(config_.max_resources_per_entry); 1079 resources.resize(config_.max_resources_per_entry);
1066 1080
1067 // If the row has no resources, remove it from the cache and delete the 1081 // If the row has no resources, remove it from the cache and delete the
1068 // entry in the database. Else update the database. 1082 // entry in the database. Else update the database.
1069 if (resources.empty()) { 1083 if (resources.empty()) {
1070 data_map->erase(key); 1084 data_map->erase(key);
1071 BrowserThread::PostTask( 1085 BrowserThread::PostTask(
1072 BrowserThread::DB, FROM_HERE, 1086 BrowserThread::DB, FROM_HERE,
1073 base::Bind(&ResourcePrefetchPredictorTables::DeleteSingleDataPoint, 1087 base::Bind(&ResourcePrefetchPredictorTables::DeleteSingleDataPoint,
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
1424 // HistoryService is already loaded. Continue with Initialization. 1438 // HistoryService is already loaded. Continue with Initialization.
1425 OnHistoryAndCacheLoaded(); 1439 OnHistoryAndCacheLoaded();
1426 return; 1440 return;
1427 } 1441 }
1428 DCHECK(!history_service_observer_.IsObserving(history_service)); 1442 DCHECK(!history_service_observer_.IsObserving(history_service));
1429 history_service_observer_.Add(history_service); 1443 history_service_observer_.Add(history_service);
1430 return; 1444 return;
1431 } 1445 }
1432 1446
1433 } // namespace predictors 1447 } // 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