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

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

Issue 2357593002: Refactor the resource_prefetch_predictor. (Closed)
Patch Set: rebase Created 4 years, 2 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()
97 : resource_type(content::RESOURCE_TYPE_LAST_TYPE),
98 number_of_hits(0),
99 number_of_misses(0),
100 consecutive_misses(0),
101 average_position(0.0),
102 priority(net::IDLE),
103 has_validators(false),
104 always_revalidate(false),
105 score(0.0) {}
106
107 ResourceRow::ResourceRow(const ResourceRow& other)
108 : resource_url(other.resource_url),
109 resource_type(other.resource_type),
110 number_of_hits(other.number_of_hits),
111 number_of_misses(other.number_of_misses),
112 consecutive_misses(other.consecutive_misses),
113 average_position(other.average_position),
114 priority(other.priority),
115 has_validators(other.has_validators),
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 93 // static
188 void ResourceRow::FromProto(const ResourceData& proto, ResourceRow* row) { 94 void ResourcePrefetchPredictorTables::SortResources(
189 row->resource_url = GURL(proto.resource_url()); 95 std::vector<ResourceData>* resources) {
190 row->resource_type = 96 // Sort indices instead of ResourceData objects and then apply resulting
191 static_cast<content::ResourceType>(proto.resource_type()); 97 // permutation to the resources.
192 row->number_of_hits = proto.number_of_hits(); 98 std::sort(resources->begin(), resources->end(),
193 row->number_of_misses = proto.number_of_misses(); 99 [](const ResourceData& x, const ResourceData& y) {
194 row->consecutive_misses = proto.consecutive_misses(); 100 return ComputeScore(x) > ComputeScore(y);
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 }); 101 });
208 } 102 }
209 103
210 ResourcePrefetchPredictorTables::PrefetchData::PrefetchData( 104 ResourcePrefetchPredictorTables::PrefetchData::PrefetchData(
211 PrefetchKeyType i_key_type, 105 PrefetchKeyType i_key_type,
212 const std::string& i_primary_key) 106 const std::string& i_primary_key)
213 : key_type(i_key_type), 107 : key_type(i_key_type),
214 primary_key(i_primary_key) { 108 primary_key(i_primary_key) {
215 } 109 }
216 110
217 ResourcePrefetchPredictorTables::PrefetchData::PrefetchData( 111 ResourcePrefetchPredictorTables::PrefetchData::PrefetchData(
218 const PrefetchData& other) 112 const PrefetchData& other)
219 : key_type(other.key_type), 113 : key_type(other.key_type),
220 primary_key(other.primary_key), 114 primary_key(other.primary_key),
221 last_visit(other.last_visit), 115 last_visit(other.last_visit),
222 resources(other.resources) { 116 resources(other.resources) {
223 } 117 }
224 118
225 ResourcePrefetchPredictorTables::PrefetchData::~PrefetchData() { 119 ResourcePrefetchPredictorTables::PrefetchData::~PrefetchData() {
226 } 120 }
227 121
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( 122 void ResourcePrefetchPredictorTables::GetAllData(
235 PrefetchDataMap* url_data_map, 123 PrefetchDataMap* url_data_map,
236 PrefetchDataMap* host_data_map) { 124 PrefetchDataMap* host_data_map) {
237 DCHECK_CURRENTLY_ON(BrowserThread::DB); 125 DCHECK_CURRENTLY_ON(BrowserThread::DB);
238 if (CantAccessDatabase()) 126 if (CantAccessDatabase())
239 return; 127 return;
240 128
241 DCHECK(url_data_map); 129 DCHECK(url_data_map);
242 DCHECK(host_data_map); 130 DCHECK(host_data_map);
243 url_data_map->clear(); 131 url_data_map->clear();
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 PrefetchDataMap* data_map, 210 PrefetchDataMap* data_map,
323 std::vector<std::string>* to_delete) { 211 std::vector<std::string>* to_delete) {
324 bool is_host = key_type == PREFETCH_KEY_TYPE_HOST; 212 bool is_host = key_type == PREFETCH_KEY_TYPE_HOST;
325 213
326 // Read the resources table and organize it per primary key. 214 // Read the resources table and organize it per primary key.
327 const char* resource_table_name = is_host ? kHostResourceTableName : 215 const char* resource_table_name = is_host ? kHostResourceTableName :
328 kUrlResourceTableName; 216 kUrlResourceTableName;
329 Statement resource_reader(DB()->GetUniqueStatement( 217 Statement resource_reader(DB()->GetUniqueStatement(
330 base::StringPrintf("SELECT * FROM %s", resource_table_name).c_str())); 218 base::StringPrintf("SELECT * FROM %s", resource_table_name).c_str()));
331 219
332 ResourceRow row; 220 ResourceData resource;
333 std::string primary_key; 221 std::string primary_key;
334 while (StepAndInitializeResourceRow(&resource_reader, &row, &primary_key)) { 222 while (StepAndInitializeResourceData(&resource_reader, &resource,
223 &primary_key)) {
335 PrefetchDataMap::iterator it = data_map->find(primary_key); 224 PrefetchDataMap::iterator it = data_map->find(primary_key);
336 if (it == data_map->end()) { 225 if (it == data_map->end()) {
337 it = data_map->insert(std::make_pair( 226 it = data_map->insert(std::make_pair(
338 primary_key, PrefetchData(key_type, primary_key))).first; 227 primary_key, PrefetchData(key_type, primary_key))).first;
339 } 228 }
340 it->second.resources.push_back(row); 229 it->second.resources.push_back(resource);
341 } 230 }
342 231
343 // Sort each of the resource row vectors by score. 232 // Sort each of the resource row vectors by score.
344 for (auto& kv : *data_map) 233 for (auto& kv : *data_map)
345 SortResourceRows(&(kv.second.resources)); 234 SortResources(&(kv.second.resources));
346 235
347 // Read the metadata and keep track of entries that have metadata, but no 236 // Read the metadata and keep track of entries that have metadata, but no
348 // resource entries, so they can be deleted. 237 // resource entries, so they can be deleted.
349 const char* metadata_table_name = is_host ? kHostMetadataTableName : 238 const char* metadata_table_name = is_host ? kHostMetadataTableName :
350 kUrlMetadataTableName; 239 kUrlMetadataTableName;
351 Statement metadata_reader(DB()->GetUniqueStatement( 240 Statement metadata_reader(DB()->GetUniqueStatement(
352 base::StringPrintf("SELECT * FROM %s", metadata_table_name).c_str())); 241 base::StringPrintf("SELECT * FROM %s", metadata_table_name).c_str()));
353 242
354 while (metadata_reader.Step()) { 243 while (metadata_reader.Step()) {
355 std::string primary_key = metadata_reader.ColumnString(0); 244 std::string primary_key = metadata_reader.ColumnString(0);
(...skipping 25 matching lines...) Expand all
381 if (!deleter->Run()) 270 if (!deleter->Run())
382 return false; 271 return false;
383 272
384 deleter.reset(data.is_host() ? GetHostMetadataDeleteStatement() : 273 deleter.reset(data.is_host() ? GetHostMetadataDeleteStatement() :
385 GetUrlMetadataDeleteStatement()); 274 GetUrlMetadataDeleteStatement());
386 deleter->BindString(0, data.primary_key); 275 deleter->BindString(0, data.primary_key);
387 if (!deleter->Run()) 276 if (!deleter->Run())
388 return false; 277 return false;
389 278
390 // Add the new data to the tables. 279 // Add the new data to the tables.
391 for (const ResourceRow& resource : data.resources) { 280 for (const ResourceData& resource : data.resources) {
392 std::unique_ptr<Statement> resource_inserter( 281 std::unique_ptr<Statement> resource_inserter(
393 data.is_host() ? GetHostResourceUpdateStatement() 282 data.is_host() ? GetHostResourceUpdateStatement()
394 : GetUrlResourceUpdateStatement()); 283 : GetUrlResourceUpdateStatement());
395 BindResourceRowToStatement(resource, data.primary_key, 284 BindResourceDataToStatement(resource, data.primary_key,
396 resource_inserter.get()); 285 resource_inserter.get());
397 if (!resource_inserter->Run()) 286 if (!resource_inserter->Run())
398 return false; 287 return false;
399 } 288 }
400 289
401 std::unique_ptr<Statement> metadata_inserter( 290 std::unique_ptr<Statement> metadata_inserter(
402 data.is_host() ? GetHostMetadataUpdateStatement() 291 data.is_host() ? GetHostMetadataUpdateStatement()
403 : GetUrlMetadataUpdateStatement()); 292 : GetUrlMetadataUpdateStatement());
404 metadata_inserter->BindString(0, data.primary_key); 293 metadata_inserter->BindString(0, data.primary_key);
405 metadata_inserter->BindInt64(1, data.last_visit.ToInternalValue()); 294 metadata_inserter->BindInt64(1, data.last_visit.ToInternalValue());
406 if (!metadata_inserter->Run()) 295 if (!metadata_inserter->Run())
(...skipping 20 matching lines...) Expand all
427 deleter->Run(); 316 deleter->Run();
428 } 317 }
429 } 318 }
430 319
431 // static 320 // static
432 bool ResourcePrefetchPredictorTables::StringsAreSmallerThanDBLimit( 321 bool ResourcePrefetchPredictorTables::StringsAreSmallerThanDBLimit(
433 const PrefetchData& data) { 322 const PrefetchData& data) {
434 if (data.primary_key.length() > kMaxStringLength) 323 if (data.primary_key.length() > kMaxStringLength)
435 return false; 324 return false;
436 325
437 for (const ResourceRow& row : data.resources) { 326 for (const ResourceData& resource : data.resources) {
438 if (row.resource_url.spec().length() > kMaxStringLength) 327 if (resource.resource_url().length() > kMaxStringLength)
439 return false; 328 return false;
440 } 329 }
441 return true; 330 return true;
442 } 331 }
443 332
444 // static 333 // static
334 float ResourcePrefetchPredictorTables::ComputeScore(const ResourceData& data) {
335 // The score is calculated so that when the rows are sorted, stylesheets,
336 // scripts and fonts appear first, sorted by position(ascending) and then the
337 // rest of the resources sorted by position (ascending).
338 static const int kMaxResourcesPerType = 100;
339 switch (data.resource_type()) {
340 case ResourceData::RESOURCE_TYPE_STYLESHEET:
341 case ResourceData::RESOURCE_TYPE_SCRIPT:
342 case ResourceData::RESOURCE_TYPE_FONT_RESOURCE:
343 return (2 * kMaxResourcesPerType) - data.average_position();
344
345 case ResourceData::RESOURCE_TYPE_IMAGE:
346 default:
347 return kMaxResourcesPerType - data.average_position();
348 }
349 // TODO(lizeb): Take priority into account.
350 }
351
352 // static
445 bool ResourcePrefetchPredictorTables::DropTablesIfOutdated( 353 bool ResourcePrefetchPredictorTables::DropTablesIfOutdated(
446 sql::Connection* db) { 354 sql::Connection* db) {
447 int version = GetDatabaseVersion(db); 355 int version = GetDatabaseVersion(db);
448 bool success = true; 356 bool success = true;
449 // Too new is also a problem. 357 // Too new is also a problem.
450 bool incompatible_version = version != kDatabaseVersion; 358 bool incompatible_version = version != kDatabaseVersion;
451 359
452 if (incompatible_version) { 360 if (incompatible_version) {
453 for (const char* table_name : 361 for (const char* table_name :
454 {kMetadataTableName, kUrlResourceTableName, kHostResourceTableName, 362 {kMetadataTableName, kUrlResourceTableName, kHostResourceTableName,
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 } 522 }
615 523
616 Statement* ResourcePrefetchPredictorTables::GetHostMetadataUpdateStatement() { 524 Statement* ResourcePrefetchPredictorTables::GetHostMetadataUpdateStatement() {
617 return new Statement(DB()->GetCachedStatement( 525 return new Statement(DB()->GetCachedStatement(
618 SQL_FROM_HERE, base::StringPrintf(kInsertMetadataTableStatementTemplate, 526 SQL_FROM_HERE, base::StringPrintf(kInsertMetadataTableStatementTemplate,
619 kHostMetadataTableName) 527 kHostMetadataTableName)
620 .c_str())); 528 .c_str()));
621 } 529 }
622 530
623 } // namespace predictors 531 } // namespace predictors
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698