Commit 62ffefbb authored by alexilin's avatar alexilin Committed by Commit bot

predictors: Add resource type to manifest.

This CL adds a new resource type field to the manifest proto.
ResourcePrefetchPredictor begins to use this field to prefetch all resources of
one resource type before another.

Also we prioritize stylesheets above scripts since this CL. Stylesheets are
almost always critical, scripts are not. It's clear win in the case if we're
fetching resources from manifests because we don't have information about
request priority in manifests. Thus we can't separate critical scripts from
non-critical ones.

BUG=699115

Review-Url: https://codereview.chromium.org/2831233004
Cr-Commit-Position: refs/heads/master@{#467742}
parent 4a9e4e47
...@@ -978,6 +978,8 @@ bool ResourcePrefetchPredictor::PopulateFromManifest( ...@@ -978,6 +978,8 @@ bool ResourcePrefetchPredictor::PopulateFromManifest(
base::Optional<std::vector<bool>> not_no_store = precache::GetResourceBitset( base::Optional<std::vector<bool>> not_no_store = precache::GetResourceBitset(
manifest, internal::kNoStoreRemovedExperiment); manifest, internal::kNoStoreRemovedExperiment);
std::vector<const precache::PrecacheResource*> filtered_resources;
bool has_prefetchable_resource = false; bool has_prefetchable_resource = false;
for (int i = 0; i < manifest.resource_size(); ++i) { for (int i = 0; i < manifest.resource_size(); ++i) {
const precache::PrecacheResource& resource = manifest.resource(i); const precache::PrecacheResource& resource = manifest.resource(i);
...@@ -987,8 +989,22 @@ bool ResourcePrefetchPredictor::PopulateFromManifest( ...@@ -987,8 +989,22 @@ bool ResourcePrefetchPredictor::PopulateFromManifest(
(!not_no_store.has_value() || not_no_store.value()[i])) { (!not_no_store.has_value() || not_no_store.value()[i])) {
has_prefetchable_resource = true; has_prefetchable_resource = true;
if (urls) if (urls)
urls->emplace_back(resource.url()); filtered_resources.push_back(&resource);
}
} }
if (urls) {
std::sort(
filtered_resources.begin(), filtered_resources.end(),
[](const precache::PrecacheResource* x,
const precache::PrecacheResource* y) {
return ResourcePrefetchPredictorTables::ComputePrecacheResourceScore(
*x) >
ResourcePrefetchPredictorTables::ComputePrecacheResourceScore(
*y);
});
for (auto* resource : filtered_resources)
urls->emplace_back(resource->url());
} }
return has_prefetchable_resource; return has_prefetchable_resource;
...@@ -1722,18 +1738,18 @@ void ResourcePrefetchPredictor::OnManifestFetched( ...@@ -1722,18 +1738,18 @@ void ResourcePrefetchPredictor::OnManifestFetched(
if (cache_entry == manifest_table_cache_->end()) { if (cache_entry == manifest_table_cache_->end()) {
if (manifest_table_cache_->size() >= config_.max_hosts_to_track) if (manifest_table_cache_->size() >= config_.max_hosts_to_track)
RemoveOldestEntryInManifestDataMap(manifest_table_cache_.get()); RemoveOldestEntryInManifestDataMap(manifest_table_cache_.get());
cache_entry = cache_entry = manifest_table_cache_->insert({host, manifest}).first;
manifest_table_cache_->insert(std::make_pair(host, manifest)).first;
} else { } else {
cache_entry->second = manifest; cache_entry->second = manifest;
} }
precache::RemoveUnknownFields(&cache_entry->second); auto& data = cache_entry->second;
precache::RemoveUnknownFields(&data);
BrowserThread::PostTask( BrowserThread::PostTask(
BrowserThread::DB, FROM_HERE, BrowserThread::DB, FROM_HERE,
base::BindOnce(&ResourcePrefetchPredictorTables::UpdateManifestData, base::BindOnce(&ResourcePrefetchPredictorTables::UpdateManifestData,
tables_, host, cache_entry->second)); tables_, host, data));
} }
void ResourcePrefetchPredictor::UpdatePrefetchDataByManifest( void ResourcePrefetchPredictor::UpdatePrefetchDataByManifest(
......
...@@ -67,17 +67,17 @@ message PrefetchData { ...@@ -67,17 +67,17 @@ message PrefetchData {
repeated ResourceData resources = 3; repeated ResourceData resources = 3;
} }
// Represents a mapping from URL or host to a list of redirect endpoints. // Represents a single redirect chain endpoint.
message RedirectData { message RedirectStat {
// Represents a single redirect chain endpoint.
message RedirectStat {
// Represents the host for RedirectData in a host-based table. // Represents the host for RedirectData in a host-based table.
optional string url = 1; optional string url = 1;
optional uint32 number_of_hits = 2; optional uint32 number_of_hits = 2;
optional uint32 number_of_misses = 3; optional uint32 number_of_misses = 3;
optional uint32 consecutive_misses = 4; optional uint32 consecutive_misses = 4;
} }
// Represents a mapping from URL or host to a list of redirect endpoints.
message RedirectData {
// Main frame URL or host. // Main frame URL or host.
optional string primary_key = 1; optional string primary_key = 1;
optional uint64 last_visit_time = 2; optional uint64 last_visit_time = 2;
......
...@@ -69,6 +69,41 @@ bool StepAndInitializeProtoData(sql::Statement* statement, ...@@ -69,6 +69,41 @@ bool StepAndInitializeProtoData(sql::Statement* statement,
return true; return true;
} }
predictors::ResourceData::ResourceType PrecacheResourceTypeToResourceType(
precache::PrecacheResource::Type resource_type) {
using precache::PrecacheResource;
using predictors::ResourceData;
switch (resource_type) {
case PrecacheResource::RESOURCE_TYPE_IMAGE:
return ResourceData::RESOURCE_TYPE_IMAGE;
case PrecacheResource::RESOURCE_TYPE_FONT:
return ResourceData::RESOURCE_TYPE_FONT_RESOURCE;
case PrecacheResource::RESOURCE_TYPE_STYLESHEET:
return ResourceData::RESOURCE_TYPE_STYLESHEET;
case PrecacheResource::RESOURCE_TYPE_SCRIPT:
return ResourceData::RESOURCE_TYPE_SCRIPT;
case PrecacheResource::RESOURCE_TYPE_OTHER:
case PrecacheResource::RESOURCE_TYPE_UNKNOWN:
default:
return ResourceData::RESOURCE_TYPE_SUB_RESOURCE;
}
}
int GetResourceTypeMultiplier(
predictors::ResourceData::ResourceType resource_type) {
switch (resource_type) {
case predictors::ResourceData::RESOURCE_TYPE_STYLESHEET:
return 4;
case predictors::ResourceData::RESOURCE_TYPE_SCRIPT:
return 3;
case predictors::ResourceData::RESOURCE_TYPE_FONT_RESOURCE:
return 2;
case predictors::ResourceData::RESOURCE_TYPE_IMAGE:
default:
return 1;
}
}
} // namespace } // namespace
namespace predictors { namespace predictors {
...@@ -310,14 +345,9 @@ void ResourcePrefetchPredictorTables::GetAllResourceDataHelper( ...@@ -310,14 +345,9 @@ void ResourcePrefetchPredictorTables::GetAllResourceDataHelper(
PrefetchData data; PrefetchData data;
std::string key; std::string key;
while (StepAndInitializeProtoData(&resource_reader, &key, &data)) { while (StepAndInitializeProtoData(&resource_reader, &key, &data)) {
data_map->insert(std::make_pair(key, data)); data_map->insert({key, data});
DCHECK_EQ(data.primary_key(), key); DCHECK_EQ(data.primary_key(), key);
} }
// Sort each of the resource vectors by score.
for (auto& kv : *data_map) {
SortResources(&(kv.second));
}
} }
void ResourcePrefetchPredictorTables::GetAllRedirectDataHelper( void ResourcePrefetchPredictorTables::GetAllRedirectDataHelper(
...@@ -331,7 +361,7 @@ void ResourcePrefetchPredictorTables::GetAllRedirectDataHelper( ...@@ -331,7 +361,7 @@ void ResourcePrefetchPredictorTables::GetAllRedirectDataHelper(
RedirectData data; RedirectData data;
std::string key; std::string key;
while (StepAndInitializeProtoData(&redirect_reader, &key, &data)) { while (StepAndInitializeProtoData(&redirect_reader, &key, &data)) {
data_map->insert(std::make_pair(key, data)); data_map->insert({key, data});
DCHECK_EQ(data.primary_key(), key); DCHECK_EQ(data.primary_key(), key);
} }
} }
...@@ -345,7 +375,7 @@ void ResourcePrefetchPredictorTables::GetAllManifestDataHelper( ...@@ -345,7 +375,7 @@ void ResourcePrefetchPredictorTables::GetAllManifestDataHelper(
precache::PrecacheManifest data; precache::PrecacheManifest data;
std::string key; std::string key;
while (StepAndInitializeProtoData(&manifest_reader, &key, &data)) { while (StepAndInitializeProtoData(&manifest_reader, &key, &data)) {
manifest_map->insert(std::make_pair(key, data)); manifest_map->insert({key, data});
} }
} }
...@@ -427,19 +457,7 @@ float ResourcePrefetchPredictorTables::ComputeResourceScore( ...@@ -427,19 +457,7 @@ float ResourcePrefetchPredictorTables::ComputeResourceScore(
break; break;
} }
int type_multiplier; int type_multiplier = GetResourceTypeMultiplier(data.resource_type());
switch (data.resource_type()) {
case ResourceData::RESOURCE_TYPE_STYLESHEET:
case ResourceData::RESOURCE_TYPE_SCRIPT:
type_multiplier = 3;
break;
case ResourceData::RESOURCE_TYPE_FONT_RESOURCE:
type_multiplier = 2;
break;
case ResourceData::RESOURCE_TYPE_IMAGE:
default:
type_multiplier = 1;
}
constexpr int kMaxResourcesPerType = 100; constexpr int kMaxResourcesPerType = 100;
return kMaxResourcesPerType * return kMaxResourcesPerType *
...@@ -447,6 +465,16 @@ float ResourcePrefetchPredictorTables::ComputeResourceScore( ...@@ -447,6 +465,16 @@ float ResourcePrefetchPredictorTables::ComputeResourceScore(
data.average_position(); data.average_position();
} }
// static
float ResourcePrefetchPredictorTables::ComputePrecacheResourceScore(
const precache::PrecacheResource& resource) {
int type_multiplier = GetResourceTypeMultiplier(
PrecacheResourceTypeToResourceType(resource.type()));
// This means a strict ordering, since the weight_ratio is in [0,1).
return type_multiplier * 10 + resource.weight_ratio();
}
// static
float ResourcePrefetchPredictorTables::ComputeOriginScore( float ResourcePrefetchPredictorTables::ComputeOriginScore(
const OriginStat& origin) { const OriginStat& origin) {
// The ranking is done by considering, in this order: // The ranking is done by considering, in this order:
......
...@@ -24,9 +24,6 @@ class Statement; ...@@ -24,9 +24,6 @@ class Statement;
namespace predictors { namespace predictors {
// From resource_prefetch_predictor.proto.
using RedirectStat = RedirectData_RedirectStat;
// Interface for database tables used by the ResourcePrefetchPredictor. // Interface for database tables used by the ResourcePrefetchPredictor.
// All methods except the constructor and destructor need to be called on the DB // All methods except the constructor and destructor need to be called on the DB
// thread. // thread.
...@@ -110,6 +107,10 @@ class ResourcePrefetchPredictorTables : public PredictorTableBase { ...@@ -110,6 +107,10 @@ class ResourcePrefetchPredictorTables : public PredictorTableBase {
// misses from |data|. // misses from |data|.
static void TrimRedirects(RedirectData* data, size_t max_consecutive_misses); static void TrimRedirects(RedirectData* data, size_t max_consecutive_misses);
// Computes score of |data|.
static float ComputePrecacheResourceScore(
const precache::PrecacheResource& data);
// Removes the origins with more than |max_consecutive_misses| consecutive // Removes the origins with more than |max_consecutive_misses| consecutive
// misses from |data|. // misses from |data|.
static void TrimOrigins(OriginData* data, size_t max_consecutive_misses); static void TrimOrigins(OriginData* data, size_t max_consecutive_misses);
...@@ -117,7 +118,7 @@ class ResourcePrefetchPredictorTables : public PredictorTableBase { ...@@ -117,7 +118,7 @@ class ResourcePrefetchPredictorTables : public PredictorTableBase {
// Sorts the origins by score, decreasing. // Sorts the origins by score, decreasing.
static void SortOrigins(OriginData* data); static void SortOrigins(OriginData* data);
// Computes score of |data|. // Computes score of |origin|.
static float ComputeOriginScore(const OriginStat& origin); static float ComputeOriginScore(const OriginStat& origin);
// The maximum length of the string that can be stored in the DB. // The maximum length of the string that can be stored in the DB.
...@@ -143,7 +144,7 @@ class ResourcePrefetchPredictorTables : public PredictorTableBase { ...@@ -143,7 +144,7 @@ class ResourcePrefetchPredictorTables : public PredictorTableBase {
// Database version. Always increment it when any change is made to the data // Database version. Always increment it when any change is made to the data
// schema (including the .proto). // schema (including the .proto).
static constexpr int kDatabaseVersion = 7; static constexpr int kDatabaseVersion = 8;
// Helper functions below help perform functions on the Url and host table // Helper functions below help perform functions on the Url and host table
// using the same code. // using the same code.
......
...@@ -316,7 +316,8 @@ void ResourcePrefetchPredictorTablesTest::TestUpdateData() { ...@@ -316,7 +316,8 @@ void ResourcePrefetchPredictorTablesTest::TestUpdateData() {
precache::PrecacheManifest theverge; precache::PrecacheManifest theverge;
InitializePrecacheResource(theverge.add_resource(), InitializePrecacheResource(theverge.add_resource(),
"https://www.theverge.com/main.js", 0.7); "https://www.theverge.com/main.js", 0.7,
precache::PrecacheResource::RESOURCE_TYPE_SCRIPT);
tables_->UpdateManifestData("theverge.com", theverge); tables_->UpdateManifestData("theverge.com", theverge);
...@@ -725,16 +726,20 @@ void ResourcePrefetchPredictorTablesTest::InitializeSampleData() { ...@@ -725,16 +726,20 @@ void ResourcePrefetchPredictorTablesTest::InitializeSampleData() {
{ // Manifest data. { // Manifest data.
precache::PrecacheManifest wikipedia; precache::PrecacheManifest wikipedia;
InitializePrecacheResource(
wikipedia.add_resource(), "https://en.wikipedia.org/script.js", 0.7,
precache::PrecacheResource::RESOURCE_TYPE_SCRIPT);
InitializePrecacheResource(wikipedia.add_resource(), InitializePrecacheResource(wikipedia.add_resource(),
"https://en.wikipedia.org/script.js", 0.7); "https://en.wikipedia.org/image.png", 0.3,
InitializePrecacheResource(wikipedia.add_resource(), precache::PrecacheResource::RESOURCE_TYPE_IMAGE);
"https://en.wikipedia.org/image.png", 0.3);
precache::PrecacheManifest youtube; precache::PrecacheManifest youtube;
InitializePrecacheResource(youtube.add_resource(), InitializePrecacheResource(youtube.add_resource(),
"https://youtube.com/photo.jpg", 0.5); "https://youtube.com/photo.jpg", 0.5,
InitializePrecacheResource(youtube.add_resource(), precache::PrecacheResource::RESOURCE_TYPE_IMAGE);
"https://youtube.com/base.js", 0.2); InitializePrecacheResource(
youtube.add_resource(), "https://youtube.com/base.js", 0.2,
precache::PrecacheResource::RESOURCE_TYPE_SCRIPT);
test_manifest_data_.clear(); test_manifest_data_.clear();
test_manifest_data_.insert(std::make_pair("en.wikipedia.org", wikipedia)); test_manifest_data_.insert(std::make_pair("en.wikipedia.org", wikipedia));
...@@ -797,13 +802,10 @@ TEST_F(ResourcePrefetchPredictorTablesTest, ComputeResourceScore) { ...@@ -797,13 +802,10 @@ TEST_F(ResourcePrefetchPredictorTablesTest, ComputeResourceScore) {
EXPECT_GT(compute_score(net::HIGHEST, content::RESOURCE_TYPE_IMAGE, 42.), EXPECT_GT(compute_score(net::HIGHEST, content::RESOURCE_TYPE_IMAGE, 42.),
compute_score(net::IDLE, content::RESOURCE_TYPE_SCRIPT, 1.)); compute_score(net::IDLE, content::RESOURCE_TYPE_SCRIPT, 1.));
// Scripts and stylesheets are equivalent. // Stylesheets are are more important than scripts, fonts and images, and the
EXPECT_NEAR( // rest.
compute_score(net::HIGHEST, content::RESOURCE_TYPE_SCRIPT, 42.), EXPECT_GT(compute_score(net::HIGHEST, content::RESOURCE_TYPE_STYLESHEET, 42.),
compute_score(net::HIGHEST, content::RESOURCE_TYPE_STYLESHEET, 42.), compute_score(net::HIGHEST, content::RESOURCE_TYPE_SCRIPT, 42.));
1e-4);
// Scripts are more important than fonts and images, and the rest.
EXPECT_GT( EXPECT_GT(
compute_score(net::HIGHEST, content::RESOURCE_TYPE_SCRIPT, 42.), compute_score(net::HIGHEST, content::RESOURCE_TYPE_SCRIPT, 42.),
compute_score(net::HIGHEST, content::RESOURCE_TYPE_FONT_RESOURCE, 42.)); compute_score(net::HIGHEST, content::RESOURCE_TYPE_FONT_RESOURCE, 42.));
...@@ -819,6 +821,33 @@ TEST_F(ResourcePrefetchPredictorTablesTest, ComputeResourceScore) { ...@@ -819,6 +821,33 @@ TEST_F(ResourcePrefetchPredictorTablesTest, ComputeResourceScore) {
compute_score(net::HIGHEST, content::RESOURCE_TYPE_SCRIPT, 42.)); compute_score(net::HIGHEST, content::RESOURCE_TYPE_SCRIPT, 42.));
} }
TEST_F(ResourcePrefetchPredictorTablesTest, ComputePrecacheResourceScore) {
auto compute_score = [](precache::PrecacheResource::Type resource_type,
float weight_ratio) {
precache::PrecacheResource resource;
InitializePrecacheResource(&resource, "", weight_ratio, resource_type);
return ResourcePrefetchPredictorTables::ComputePrecacheResourceScore(
resource);
};
// Stylesheets are the most impotant followed by scripts, fonts and images in
// this order.
EXPECT_GT(
compute_score(precache::PrecacheResource::RESOURCE_TYPE_STYLESHEET, 0.1),
compute_score(precache::PrecacheResource::RESOURCE_TYPE_SCRIPT, 0.9));
EXPECT_GT(
compute_score(precache::PrecacheResource::RESOURCE_TYPE_SCRIPT, 0.1),
compute_score(precache::PrecacheResource::RESOURCE_TYPE_FONT, 0.9));
EXPECT_GT(
compute_score(precache::PrecacheResource::RESOURCE_TYPE_FONT, 0.1),
compute_score(precache::PrecacheResource::RESOURCE_TYPE_IMAGE, 0.9));
// If resource types are equal, weight ratio matters.
EXPECT_GT(
compute_score(precache::PrecacheResource::RESOURCE_TYPE_SCRIPT, 0.7),
compute_score(precache::PrecacheResource::RESOURCE_TYPE_SCRIPT, 0.6));
}
TEST_F(ResourcePrefetchPredictorTablesTest, ComputeOriginScore) { TEST_F(ResourcePrefetchPredictorTablesTest, ComputeOriginScore) {
auto compute_score = [](int hits, int misses, double average_position, auto compute_score = [](int hits, int misses, double average_position,
bool always_access_network, bool accessed_network) { bool always_access_network, bool accessed_network) {
......
...@@ -54,9 +54,11 @@ void InitializeRedirectStat(RedirectStat* redirect, ...@@ -54,9 +54,11 @@ void InitializeRedirectStat(RedirectStat* redirect,
void InitializePrecacheResource(precache::PrecacheResource* resource, void InitializePrecacheResource(precache::PrecacheResource* resource,
const std::string& url, const std::string& url,
double weight_ratio) { double weight_ratio,
precache::PrecacheResource::Type type) {
resource->set_url(url); resource->set_url(url);
resource->set_weight_ratio(weight_ratio); resource->set_weight_ratio(weight_ratio);
resource->set_type(type);
} }
void InitializeOriginStat(OriginStat* origin_stat, void InitializeOriginStat(OriginStat* origin_stat,
......
...@@ -32,7 +32,8 @@ void InitializeRedirectStat(RedirectStat* redirect, ...@@ -32,7 +32,8 @@ void InitializeRedirectStat(RedirectStat* redirect,
void InitializePrecacheResource(precache::PrecacheResource* resource, void InitializePrecacheResource(precache::PrecacheResource* resource,
const std::string& url, const std::string& url,
double weight_ratio); double weight_ratio,
precache::PrecacheResource::Type type);
void InitializeOriginStat(OriginStat* origin_stat, void InitializeOriginStat(OriginStat* origin_stat,
const std::string& origin, const std::string& origin,
......
...@@ -26,6 +26,20 @@ message PrecacheResource { ...@@ -26,6 +26,20 @@ message PrecacheResource {
// This is a non-negative number, with higher being more important. Its value // This is a non-negative number, with higher being more important. Its value
// depends on PrecacheConfigurationSettings.resource_weight_function. // depends on PrecacheConfigurationSettings.resource_weight_function.
optional double weight = 4; optional double weight = 4;
enum Type {
RESOURCE_TYPE_UNKNOWN = 0;
RESOURCE_TYPE_IMAGE = 1;
RESOURCE_TYPE_FONT = 2;
RESOURCE_TYPE_STYLESHEET = 3;
RESOURCE_TYPE_SCRIPT = 4;
RESOURCE_TYPE_OTHER = 7;
}
// The type of resource.
optional Type type = 5;
}; };
message PrecacheManifestId { message PrecacheManifestId {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment