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

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

Issue 2357593002: Refactor the resource_prefetch_predictor. (Closed)
Patch Set: BUILD.gn after rebase 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_tables.h" 5 #include "chrome/browser/predictors/resource_prefetch_predictor_tables.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <memory> 10 #include <memory>
11 #include <utility> 11 #include <utility>
12 12
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/metrics/histogram_macros.h" 14 #include "base/metrics/histogram_macros.h"
15 #include "base/strings/stringprintf.h" 15 #include "base/strings/stringprintf.h"
16 #include "content/public/browser/browser_thread.h" 16 #include "content/public/browser/browser_thread.h"
17 #include "sql/meta_table.h" 17 #include "sql/meta_table.h"
18 #include "sql/statement.h" 18 #include "sql/statement.h"
19 #include "sql/transaction.h" 19 #include "sql/transaction.h"
20 20
21 using content::BrowserThread; 21 using content::BrowserThread;
22 using sql::Statement; 22 using sql::Statement;
23 23
24 namespace { 24 namespace {
25 25
26 using ResourceRow = predictors::ResourcePrefetchPredictorTables::ResourceRow; 26 using ResourceData = predictors::ResourceData;
27 27
28 const char kMetadataTableName[] = "resource_prefetch_predictor_metadata"; 28 const char kMetadataTableName[] = "resource_prefetch_predictor_metadata";
29 const char kUrlResourceTableName[] = "resource_prefetch_predictor_url"; 29 const char kUrlResourceTableName[] = "resource_prefetch_predictor_url";
30 const char kUrlMetadataTableName[] = "resource_prefetch_predictor_url_metadata"; 30 const char kUrlMetadataTableName[] = "resource_prefetch_predictor_url_metadata";
31 const char kHostResourceTableName[] = "resource_prefetch_predictor_host"; 31 const char kHostResourceTableName[] = "resource_prefetch_predictor_host";
32 const char kHostMetadataTableName[] = 32 const char kHostMetadataTableName[] =
33 "resource_prefetch_predictor_host_metadata"; 33 "resource_prefetch_predictor_host_metadata";
34 34
35 const char kCreateGlobalMetadataStatementTemplate[] = 35 const char kCreateGlobalMetadataStatementTemplate[] =
36 "CREATE TABLE %s ( " 36 "CREATE TABLE %s ( "
(...skipping 10 matching lines...) Expand all
47 "main_page_url TEXT, " 47 "main_page_url TEXT, "
48 "last_visit_time INTEGER, " 48 "last_visit_time INTEGER, "
49 "PRIMARY KEY(main_page_url))"; 49 "PRIMARY KEY(main_page_url))";
50 50
51 const char kInsertResourceTableStatementTemplate[] = 51 const char kInsertResourceTableStatementTemplate[] =
52 "INSERT INTO %s (main_page_url, resource_url, proto) VALUES (?,?,?)"; 52 "INSERT INTO %s (main_page_url, resource_url, proto) VALUES (?,?,?)";
53 const char kInsertMetadataTableStatementTemplate[] = 53 const char kInsertMetadataTableStatementTemplate[] =
54 "INSERT INTO %s (main_page_url, last_visit_time) VALUES (?,?)"; 54 "INSERT INTO %s (main_page_url, last_visit_time) VALUES (?,?)";
55 const char kDeleteStatementTemplate[] = "DELETE FROM %s WHERE main_page_url=?"; 55 const char kDeleteStatementTemplate[] = "DELETE FROM %s WHERE main_page_url=?";
56 56
57 void BindResourceRowToStatement(const ResourceRow& row, 57 void BindResourceDataToStatement(const ResourceData& data,
58 const std::string& primary_key, 58 const std::string& primary_key,
59 Statement* statement) { 59 Statement* statement) {
60 chrome_browser_predictors::ResourceData proto; 60 int size = data.ByteSize();
61 row.ToProto(&proto); 61 DCHECK(size > 0);
62 int size = proto.ByteSize();
63 std::vector<char> proto_buffer(size); 62 std::vector<char> proto_buffer(size);
64 proto.SerializeToArray(&proto_buffer[0], size); 63 data.SerializeToArray(&proto_buffer[0], size);
65 64
66 statement->BindString(0, primary_key); 65 statement->BindString(0, primary_key);
67 statement->BindString(1, row.resource_url.spec()); 66 statement->BindString(1, data.resource_url());
68 statement->BindBlob(2, &proto_buffer[0], size); 67 statement->BindBlob(2, &proto_buffer[0], size);
69 } 68 }
70 69
71 bool StepAndInitializeResourceRow(Statement* statement, 70 bool StepAndInitializeResourceData(Statement* statement,
72 ResourceRow* row, 71 ResourceData* data,
73 std::string* primary_key) { 72 std::string* primary_key) {
74 if (!statement->Step()) 73 if (!statement->Step())
75 return false; 74 return false;
76 75
77 *primary_key = statement->ColumnString(0); 76 *primary_key = statement->ColumnString(0);
78 77
79 int size = statement->ColumnByteLength(2); 78 int size = statement->ColumnByteLength(2);
80 const void* data = statement->ColumnBlob(2); 79 const void* blob = statement->ColumnBlob(2);
81 DCHECK(data); 80 DCHECK(blob);
82 chrome_browser_predictors::ResourceData proto; 81 data->ParseFromArray(blob, size);
83 proto.ParseFromArray(data, size);
84 ResourceRow::FromProto(proto, row);
85 82
86 GURL resource_url(statement->ColumnString(1)); 83 std::string resource_url = statement->ColumnString(1);
87 DCHECK(resource_url == row->resource_url); 84 DCHECK(resource_url == data->resource_url());
88 85
89 return true; 86 return true;
90 } 87 }
91 88
92 } // namespace 89 } // namespace
93 90
94 namespace predictors { 91 namespace predictors {
95 92
96 ResourceRow::ResourceRow() 93 // static
97 : resource_type(content::RESOURCE_TYPE_LAST_TYPE), 94 void ResourcePrefetchPredictorTables::SortResources(
98 number_of_hits(0), 95 std::vector<ResourceData>* resources) {
99 number_of_misses(0), 96 size_t size = resources->size();
100 consecutive_misses(0), 97 std::vector<size_t> indices;
101 average_position(0.0), 98 std::vector<float> scores;
102 priority(net::IDLE), 99 indices.reserve(size);
103 has_validators(false), 100 scores.reserve(size);
104 always_revalidate(false), 101 for (size_t i = 0; i < size; ++i) {
105 score(0.0) {} 102 indices.push_back(i);
103 scores.push_back(ComputeScore((*resources)[i]));
104 }
106 105
107 ResourceRow::ResourceRow(const ResourceRow& other) 106 // Sort indices instead of ResourceData objects and then apply resulting
pasko 2016/09/21 17:38:36 Why not just this: std::sort(resources->begin(),
alexilin 2016/09/22 11:21:15 Yeah, I agree. I simply overlooked this more conve
108 : resource_url(other.resource_url), 107 // permutation to the resources.
109 resource_type(other.resource_type), 108 std::sort(indices.begin(), indices.end(),
110 number_of_hits(other.number_of_hits), 109 [&scores](size_t x, size_t y) { return scores[x] > scores[y]; });
111 number_of_misses(other.number_of_misses), 110 std::vector<ResourceData> sorted_resources;
112 consecutive_misses(other.consecutive_misses), 111 sorted_resources.reserve(size);
113 average_position(other.average_position), 112 for (size_t i : indices)
114 priority(other.priority), 113 sorted_resources.push_back((*resources)[i]);
115 has_validators(other.has_validators), 114 resources->swap(sorted_resources);
116 always_revalidate(other.always_revalidate),
117 score(other.score) {}
118
119 ResourceRow::ResourceRow(const std::string& i_resource_url,
120 content::ResourceType i_resource_type,
121 int i_number_of_hits,
122 int i_number_of_misses,
123 int i_consecutive_misses,
124 double i_average_position,
125 net::RequestPriority i_priority,
126 bool i_has_validators,
127 bool i_always_revalidate)
128 : resource_url(i_resource_url),
129 resource_type(i_resource_type),
130 number_of_hits(i_number_of_hits),
131 number_of_misses(i_number_of_misses),
132 consecutive_misses(i_consecutive_misses),
133 average_position(i_average_position),
134 priority(i_priority),
135 has_validators(i_has_validators),
136 always_revalidate(i_always_revalidate) {
137 UpdateScore();
138 }
139
140 void ResourceRow::UpdateScore() {
141 // The score is calculated so that when the rows are sorted, stylesheets,
142 // scripts and fonts appear first, sorted by position(ascending) and then the
143 // rest of the resources sorted by position (ascending).
144 static const int kMaxResourcesPerType = 100;
145 switch (resource_type) {
146 case content::RESOURCE_TYPE_STYLESHEET:
147 case content::RESOURCE_TYPE_SCRIPT:
148 case content::RESOURCE_TYPE_FONT_RESOURCE:
149 score = (2 * kMaxResourcesPerType) - average_position;
150 break;
151
152 case content::RESOURCE_TYPE_IMAGE:
153 default:
154 score = kMaxResourcesPerType - average_position;
155 break;
156 }
157 // TODO(lizeb): Take priority into account.
158 }
159
160 bool ResourceRow::operator==(const ResourceRow& rhs) const {
161 return resource_url == rhs.resource_url &&
162 resource_type == rhs.resource_type &&
163 number_of_hits == rhs.number_of_hits &&
164 number_of_misses == rhs.number_of_misses &&
165 consecutive_misses == rhs.consecutive_misses &&
166 average_position == rhs.average_position && priority == rhs.priority &&
167 has_validators == rhs.has_validators &&
168 always_revalidate == rhs.always_revalidate && score == rhs.score;
169 }
170
171 void ResourceRow::ToProto(ResourceData* resource_data) const {
172 using chrome_browser_predictors::ResourceData_Priority;
173 using chrome_browser_predictors::ResourceData_ResourceType;
174
175 resource_data->set_resource_url(resource_url.spec());
176 resource_data->set_resource_type(
177 static_cast<ResourceData_ResourceType>(resource_type));
178 resource_data->set_number_of_hits(number_of_hits);
179 resource_data->set_number_of_misses(number_of_misses);
180 resource_data->set_consecutive_misses(consecutive_misses);
181 resource_data->set_average_position(average_position);
182 resource_data->set_priority(static_cast<ResourceData_Priority>(priority));
183 resource_data->set_has_validators(has_validators);
184 resource_data->set_always_revalidate(always_revalidate);
185 }
186
187 // static
188 void ResourceRow::FromProto(const ResourceData& proto, ResourceRow* row) {
189 row->resource_url = GURL(proto.resource_url());
190 row->resource_type =
191 static_cast<content::ResourceType>(proto.resource_type());
192 row->number_of_hits = proto.number_of_hits();
193 row->number_of_misses = proto.number_of_misses();
194 row->consecutive_misses = proto.consecutive_misses();
195 row->average_position = proto.average_position();
196 row->priority = static_cast<net::RequestPriority>(proto.priority());
197 row->has_validators = proto.has_validators();
198 row->always_revalidate = proto.always_revalidate();
199 row->UpdateScore();
200 }
201
202 // static
203 void ResourcePrefetchPredictorTables::SortResourceRows(ResourceRows* rows) {
204 std::sort(rows->begin(), rows->end(),
205 [](const ResourceRow& x, const ResourceRow& y) {
206 return x.score > y.score;
207 });
208 } 115 }
209 116
210 ResourcePrefetchPredictorTables::PrefetchData::PrefetchData( 117 ResourcePrefetchPredictorTables::PrefetchData::PrefetchData(
211 PrefetchKeyType i_key_type, 118 PrefetchKeyType i_key_type,
212 const std::string& i_primary_key) 119 const std::string& i_primary_key)
213 : key_type(i_key_type), 120 : key_type(i_key_type),
214 primary_key(i_primary_key) { 121 primary_key(i_primary_key) {
215 } 122 }
216 123
217 ResourcePrefetchPredictorTables::PrefetchData::PrefetchData( 124 ResourcePrefetchPredictorTables::PrefetchData::PrefetchData(
218 const PrefetchData& other) 125 const PrefetchData& other)
219 : key_type(other.key_type), 126 : key_type(other.key_type),
220 primary_key(other.primary_key), 127 primary_key(other.primary_key),
221 last_visit(other.last_visit), 128 last_visit(other.last_visit),
222 resources(other.resources) { 129 resources(other.resources) {
223 } 130 }
224 131
225 ResourcePrefetchPredictorTables::PrefetchData::~PrefetchData() { 132 ResourcePrefetchPredictorTables::PrefetchData::~PrefetchData() {
226 } 133 }
227 134
228 bool ResourcePrefetchPredictorTables::PrefetchData::operator==(
229 const PrefetchData& rhs) const {
230 return key_type == rhs.key_type && primary_key == rhs.primary_key &&
231 resources == rhs.resources;
232 }
233
234 void ResourcePrefetchPredictorTables::GetAllData( 135 void ResourcePrefetchPredictorTables::GetAllData(
235 PrefetchDataMap* url_data_map, 136 PrefetchDataMap* url_data_map,
236 PrefetchDataMap* host_data_map) { 137 PrefetchDataMap* host_data_map) {
237 DCHECK_CURRENTLY_ON(BrowserThread::DB); 138 DCHECK_CURRENTLY_ON(BrowserThread::DB);
238 if (CantAccessDatabase()) 139 if (CantAccessDatabase())
239 return; 140 return;
240 141
241 DCHECK(url_data_map); 142 DCHECK(url_data_map);
242 DCHECK(host_data_map); 143 DCHECK(host_data_map);
243 url_data_map->clear(); 144 url_data_map->clear();
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 PrefetchDataMap* data_map, 223 PrefetchDataMap* data_map,
323 std::vector<std::string>* to_delete) { 224 std::vector<std::string>* to_delete) {
324 bool is_host = key_type == PREFETCH_KEY_TYPE_HOST; 225 bool is_host = key_type == PREFETCH_KEY_TYPE_HOST;
325 226
326 // Read the resources table and organize it per primary key. 227 // Read the resources table and organize it per primary key.
327 const char* resource_table_name = is_host ? kHostResourceTableName : 228 const char* resource_table_name = is_host ? kHostResourceTableName :
328 kUrlResourceTableName; 229 kUrlResourceTableName;
329 Statement resource_reader(DB()->GetUniqueStatement( 230 Statement resource_reader(DB()->GetUniqueStatement(
330 base::StringPrintf("SELECT * FROM %s", resource_table_name).c_str())); 231 base::StringPrintf("SELECT * FROM %s", resource_table_name).c_str()));
331 232
332 ResourceRow row; 233 ResourceData resource;
333 std::string primary_key; 234 std::string primary_key;
334 while (StepAndInitializeResourceRow(&resource_reader, &row, &primary_key)) { 235 while (StepAndInitializeResourceData(&resource_reader, &resource,
236 &primary_key)) {
335 PrefetchDataMap::iterator it = data_map->find(primary_key); 237 PrefetchDataMap::iterator it = data_map->find(primary_key);
336 if (it == data_map->end()) { 238 if (it == data_map->end()) {
337 it = data_map->insert(std::make_pair( 239 it = data_map->insert(std::make_pair(
338 primary_key, PrefetchData(key_type, primary_key))).first; 240 primary_key, PrefetchData(key_type, primary_key))).first;
339 } 241 }
340 it->second.resources.push_back(row); 242 it->second.resources.push_back(resource);
341 } 243 }
342 244
343 // Sort each of the resource row vectors by score. 245 // Sort each of the resource row vectors by score.
344 for (auto& kv : *data_map) 246 for (auto& kv : *data_map)
345 SortResourceRows(&(kv.second.resources)); 247 SortResources(&(kv.second.resources));
346 248
347 // Read the metadata and keep track of entries that have metadata, but no 249 // Read the metadata and keep track of entries that have metadata, but no
348 // resource entries, so they can be deleted. 250 // resource entries, so they can be deleted.
349 const char* metadata_table_name = is_host ? kHostMetadataTableName : 251 const char* metadata_table_name = is_host ? kHostMetadataTableName :
350 kUrlMetadataTableName; 252 kUrlMetadataTableName;
351 Statement metadata_reader(DB()->GetUniqueStatement( 253 Statement metadata_reader(DB()->GetUniqueStatement(
352 base::StringPrintf("SELECT * FROM %s", metadata_table_name).c_str())); 254 base::StringPrintf("SELECT * FROM %s", metadata_table_name).c_str()));
353 255
354 while (metadata_reader.Step()) { 256 while (metadata_reader.Step()) {
355 std::string primary_key = metadata_reader.ColumnString(0); 257 std::string primary_key = metadata_reader.ColumnString(0);
(...skipping 25 matching lines...) Expand all
381 if (!deleter->Run()) 283 if (!deleter->Run())
382 return false; 284 return false;
383 285
384 deleter.reset(data.is_host() ? GetHostMetadataDeleteStatement() : 286 deleter.reset(data.is_host() ? GetHostMetadataDeleteStatement() :
385 GetUrlMetadataDeleteStatement()); 287 GetUrlMetadataDeleteStatement());
386 deleter->BindString(0, data.primary_key); 288 deleter->BindString(0, data.primary_key);
387 if (!deleter->Run()) 289 if (!deleter->Run())
388 return false; 290 return false;
389 291
390 // Add the new data to the tables. 292 // Add the new data to the tables.
391 for (const ResourceRow& resource : data.resources) { 293 for (const ResourceData& resource : data.resources) {
392 std::unique_ptr<Statement> resource_inserter( 294 std::unique_ptr<Statement> resource_inserter(
393 data.is_host() ? GetHostResourceUpdateStatement() 295 data.is_host() ? GetHostResourceUpdateStatement()
394 : GetUrlResourceUpdateStatement()); 296 : GetUrlResourceUpdateStatement());
395 BindResourceRowToStatement(resource, data.primary_key, 297 BindResourceDataToStatement(resource, data.primary_key,
396 resource_inserter.get()); 298 resource_inserter.get());
397 if (!resource_inserter->Run()) 299 if (!resource_inserter->Run())
398 return false; 300 return false;
399 } 301 }
400 302
401 std::unique_ptr<Statement> metadata_inserter( 303 std::unique_ptr<Statement> metadata_inserter(
402 data.is_host() ? GetHostMetadataUpdateStatement() 304 data.is_host() ? GetHostMetadataUpdateStatement()
403 : GetUrlMetadataUpdateStatement()); 305 : GetUrlMetadataUpdateStatement());
404 metadata_inserter->BindString(0, data.primary_key); 306 metadata_inserter->BindString(0, data.primary_key);
405 metadata_inserter->BindInt64(1, data.last_visit.ToInternalValue()); 307 metadata_inserter->BindInt64(1, data.last_visit.ToInternalValue());
406 if (!metadata_inserter->Run()) 308 if (!metadata_inserter->Run())
(...skipping 20 matching lines...) Expand all
427 deleter->Run(); 329 deleter->Run();
428 } 330 }
429 } 331 }
430 332
431 // static 333 // static
432 bool ResourcePrefetchPredictorTables::StringsAreSmallerThanDBLimit( 334 bool ResourcePrefetchPredictorTables::StringsAreSmallerThanDBLimit(
433 const PrefetchData& data) { 335 const PrefetchData& data) {
434 if (data.primary_key.length() > kMaxStringLength) 336 if (data.primary_key.length() > kMaxStringLength)
435 return false; 337 return false;
436 338
437 for (const ResourceRow& row : data.resources) { 339 for (const ResourceData& resource : data.resources) {
438 if (row.resource_url.spec().length() > kMaxStringLength) 340 if (resource.resource_url().length() > kMaxStringLength)
439 return false; 341 return false;
440 } 342 }
441 return true; 343 return true;
442 } 344 }
443 345
444 // static 346 // static
347 float ResourcePrefetchPredictorTables::ComputeScore(const ResourceData& data) {
348 // The score is calculated so that when the rows are sorted, stylesheets,
349 // scripts and fonts appear first, sorted by position(ascending) and then the
350 // rest of the resources sorted by position (ascending).
351 static const int kMaxResourcesPerType = 100;
352 switch (data.resource_type()) {
353 case ResourceData::RESOURCE_TYPE_STYLESHEET:
354 case ResourceData::RESOURCE_TYPE_SCRIPT:
355 case ResourceData::RESOURCE_TYPE_FONT_RESOURCE:
356 return (2 * kMaxResourcesPerType) - data.average_position();
357
358 case ResourceData::RESOURCE_TYPE_IMAGE:
359 default:
360 return kMaxResourcesPerType - data.average_position();
361 }
362 // TODO(lizeb): Take priority into account.
363 }
364
365 // static
445 bool ResourcePrefetchPredictorTables::DropTablesIfOutdated( 366 bool ResourcePrefetchPredictorTables::DropTablesIfOutdated(
446 sql::Connection* db) { 367 sql::Connection* db) {
447 int version = GetDatabaseVersion(db); 368 int version = GetDatabaseVersion(db);
448 bool success = true; 369 bool success = true;
449 // Too new is also a problem. 370 // Too new is also a problem.
450 bool incompatible_version = version != kDatabaseVersion; 371 bool incompatible_version = version != kDatabaseVersion;
451 372
452 if (incompatible_version) { 373 if (incompatible_version) {
453 for (const char* table_name : 374 for (const char* table_name :
454 {kMetadataTableName, kUrlResourceTableName, kHostResourceTableName, 375 {kMetadataTableName, kUrlResourceTableName, kHostResourceTableName,
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 } 535 }
615 536
616 Statement* ResourcePrefetchPredictorTables::GetHostMetadataUpdateStatement() { 537 Statement* ResourcePrefetchPredictorTables::GetHostMetadataUpdateStatement() {
617 return new Statement(DB()->GetCachedStatement( 538 return new Statement(DB()->GetCachedStatement(
618 SQL_FROM_HERE, base::StringPrintf(kInsertMetadataTableStatementTemplate, 539 SQL_FROM_HERE, base::StringPrintf(kInsertMetadataTableStatementTemplate,
619 kHostMetadataTableName) 540 kHostMetadataTableName)
620 .c_str())); 541 .c_str()));
621 } 542 }
622 543
623 } // namespace predictors 544 } // namespace predictors
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698