Commit 3eb631ab authored by lizeb's avatar lizeb Committed by Commit bot

predictors: Take the priority into account for scoring resources.

This changes the way the resource score is computed in the
resource_prefetch_predictor. It takes into account the request priority
as the most important feature, then resource type, then average position.

The rationale is that resource priority surfaces the render-blocking
resources, that are the most critical to prefetch.

BUG=631966

Review-Url: https://codereview.chromium.org/2385173002
Cr-Commit-Position: refs/heads/master@{#422753}
parent 2569ec97
...@@ -134,6 +134,7 @@ void ResourcePrefetchPredictorTables::SortResources( ...@@ -134,6 +134,7 @@ void ResourcePrefetchPredictorTables::SortResources(
std::vector<ResourceData>* resources) { std::vector<ResourceData>* resources) {
std::sort(resources->begin(), resources->end(), std::sort(resources->begin(), resources->end(),
[](const ResourceData& x, const ResourceData& y) { [](const ResourceData& x, const ResourceData& y) {
// Decreasing score ordering.
return ComputeResourceScore(x) > ComputeResourceScore(y); return ComputeResourceScore(x) > ComputeResourceScore(y);
}); });
} }
...@@ -143,6 +144,7 @@ void ResourcePrefetchPredictorTables::SortRedirects( ...@@ -143,6 +144,7 @@ void ResourcePrefetchPredictorTables::SortRedirects(
std::vector<RedirectStat>* redirects) { std::vector<RedirectStat>* redirects) {
std::sort(redirects->begin(), redirects->end(), std::sort(redirects->begin(), redirects->end(),
[](const RedirectStat& x, const RedirectStat& y) { [](const RedirectStat& x, const RedirectStat& y) {
// Decreasing score ordering.
return ComputeRedirectScore(x) > ComputeRedirectScore(y); return ComputeRedirectScore(x) > ComputeRedirectScore(y);
}); });
} }
...@@ -478,21 +480,46 @@ bool ResourcePrefetchPredictorTables::StringsAreSmallerThanDBLimit( ...@@ -478,21 +480,46 @@ bool ResourcePrefetchPredictorTables::StringsAreSmallerThanDBLimit(
// static // static
float ResourcePrefetchPredictorTables::ComputeResourceScore( float ResourcePrefetchPredictorTables::ComputeResourceScore(
const ResourceData& data) { const ResourceData& data) {
// The score is calculated so that when the rows are sorted, stylesheets, // The ranking is done by considering, in this order:
// scripts and fonts appear first, sorted by position(ascending) and then the // 1. Resource Priority
// rest of the resources sorted by position (ascending). // 2. Request resource type
static const int kMaxResourcesPerType = 100; // 3. Finally, the average position, giving a higher priotity to earlier
// resources.
int priority_multiplier;
switch (data.priority()) {
case ResourceData::REQUEST_PRIORITY_HIGHEST:
priority_multiplier = 3;
break;
case ResourceData::REQUEST_PRIORITY_MEDIUM:
priority_multiplier = 2;
break;
case ResourceData::REQUEST_PRIORITY_LOW:
case ResourceData::REQUEST_PRIORITY_LOWEST:
case ResourceData::REQUEST_PRIORITY_IDLE:
default:
priority_multiplier = 1;
break;
}
int type_multiplier;
switch (data.resource_type()) { switch (data.resource_type()) {
case ResourceData::RESOURCE_TYPE_STYLESHEET: case ResourceData::RESOURCE_TYPE_STYLESHEET:
case ResourceData::RESOURCE_TYPE_SCRIPT: case ResourceData::RESOURCE_TYPE_SCRIPT:
type_multiplier = 3;
break;
case ResourceData::RESOURCE_TYPE_FONT_RESOURCE: case ResourceData::RESOURCE_TYPE_FONT_RESOURCE:
return (2 * kMaxResourcesPerType) - data.average_position(); type_multiplier = 2;
break;
case ResourceData::RESOURCE_TYPE_IMAGE: case ResourceData::RESOURCE_TYPE_IMAGE:
default: default:
return kMaxResourcesPerType - data.average_position(); type_multiplier = 1;
} }
// TODO(lizeb): Take priority into account.
constexpr int kMaxResourcesPerType = 100;
return kMaxResourcesPerType *
(priority_multiplier * 100 + type_multiplier * 10) -
data.average_position();
} }
// static // static
......
...@@ -575,33 +575,47 @@ void ResourcePrefetchPredictorTablesTest::ReopenDatabase() { ...@@ -575,33 +575,47 @@ void ResourcePrefetchPredictorTablesTest::ReopenDatabase() {
// Test cases. // Test cases.
TEST_F(ResourcePrefetchPredictorTablesTest, ComputeResourceScore) { TEST_F(ResourcePrefetchPredictorTablesTest, ComputeResourceScore) {
ResourceData js_resource = CreateResourceData( auto compute_score = [](net::RequestPriority priority,
"http://www.resources.google.com/script.js", content::ResourceType resource_type,
content::RESOURCE_TYPE_SCRIPT, 11, 0, 0, 1., net::MEDIUM, false, false); double average_position) {
ResourceData image_resource = CreateResourceData( return ResourcePrefetchPredictorTables::ComputeResourceScore(
"http://www.resources.google.com/image.jpg", content::RESOURCE_TYPE_IMAGE, CreateResourceData("", resource_type, 0, 0, 0, average_position,
11, 0, 0, 1., net::MEDIUM, false, false); priority, false, false));
ResourceData css_resource = };
CreateResourceData("http://www.resources.google.com/stylesheet.css",
content::RESOURCE_TYPE_STYLESHEET, 11, 0, 0, 1., // Priority is more important than the rest.
net::MEDIUM, false, false); EXPECT_TRUE(compute_score(net::HIGHEST, content::RESOURCE_TYPE_SCRIPT, 1.) >
ResourceData font_resource = compute_score(net::HIGHEST, content::RESOURCE_TYPE_IMAGE, 42.));
CreateResourceData("http://www.resources.google.com/font.woff",
content::RESOURCE_TYPE_FONT_RESOURCE, 11, 0, 0, 1., EXPECT_TRUE(compute_score(net::HIGHEST, content::RESOURCE_TYPE_IMAGE, 42.) >
net::MEDIUM, false, false); compute_score(net::MEDIUM, content::RESOURCE_TYPE_SCRIPT, 1.));
float js_resource_score = EXPECT_TRUE(compute_score(net::HIGHEST, content::RESOURCE_TYPE_IMAGE, 42.) >
ResourcePrefetchPredictorTables::ComputeResourceScore(js_resource); compute_score(net::LOW, content::RESOURCE_TYPE_SCRIPT, 1.));
float css_resource_score = EXPECT_TRUE(compute_score(net::HIGHEST, content::RESOURCE_TYPE_IMAGE, 42.) >
ResourcePrefetchPredictorTables::ComputeResourceScore(css_resource); compute_score(net::LOWEST, content::RESOURCE_TYPE_SCRIPT, 1.));
float font_resource_score = EXPECT_TRUE(compute_score(net::HIGHEST, content::RESOURCE_TYPE_IMAGE, 42.) >
ResourcePrefetchPredictorTables::ComputeResourceScore(font_resource); compute_score(net::IDLE, content::RESOURCE_TYPE_SCRIPT, 1.));
float image_resource_score =
ResourcePrefetchPredictorTables::ComputeResourceScore(image_resource); // Scripts and stylesheets are equivalent.
EXPECT_NEAR(
EXPECT_TRUE(js_resource_score == css_resource_score); compute_score(net::HIGHEST, content::RESOURCE_TYPE_SCRIPT, 42.),
EXPECT_TRUE(js_resource_score == font_resource_score); compute_score(net::HIGHEST, content::RESOURCE_TYPE_STYLESHEET, 42.),
EXPECT_NEAR(199., js_resource_score, 1e-4); 1e-4);
EXPECT_NEAR(99., image_resource_score, 1e-4);
// Scripts are more important than fonts and images, and the rest.
EXPECT_TRUE(
compute_score(net::HIGHEST, content::RESOURCE_TYPE_SCRIPT, 42.) >
compute_score(net::HIGHEST, content::RESOURCE_TYPE_FONT_RESOURCE, 42.));
EXPECT_TRUE(
compute_score(net::HIGHEST, content::RESOURCE_TYPE_FONT_RESOURCE, 42.) >
compute_score(net::HIGHEST, content::RESOURCE_TYPE_IMAGE, 42.));
EXPECT_TRUE(
compute_score(net::HIGHEST, content::RESOURCE_TYPE_FONT_RESOURCE, 42.) >
compute_score(net::HIGHEST, content::RESOURCE_TYPE_FAVICON, 42.));
// All else being equal, position matters.
EXPECT_TRUE(compute_score(net::HIGHEST, content::RESOURCE_TYPE_SCRIPT, 12.) >
compute_score(net::HIGHEST, content::RESOURCE_TYPE_SCRIPT, 42.));
} }
TEST_F(ResourcePrefetchPredictorTablesTest, GetAllData) { TEST_F(ResourcePrefetchPredictorTablesTest, GetAllData) {
......
...@@ -31,13 +31,23 @@ class Entry(object): ...@@ -31,13 +31,23 @@ class Entry(object):
self.score = self._Score() self.score = self._Score()
def _Score(self): def _Score(self):
"""Mirrors ResourcePrefetchPredictorTables::ResourceRow::UpdateScore.""" """Mirrors ResourcePrefetchPredictorTables::ComputeResourceScore."""
multiplier = 1 priority_multiplier = 1
type_multiplier = 1
if self.proto.priority == ResourceData.REQUEST_PRIORITY_HIGHEST:
priority_multiplier = 3
elif self.proto.priority == ResourceData.REQUEST_PRIORITY_MEDIUM:
priority_multiplier = 2
if self.proto.resource_type in (ResourceData.RESOURCE_TYPE_STYLESHEET, if self.proto.resource_type in (ResourceData.RESOURCE_TYPE_STYLESHEET,
ResourceData.RESOURCE_TYPE_SCRIPT, ResourceData.RESOURCE_TYPE_SCRIPT):
ResourceData.RESOURCE_TYPE_FONT_RESOURCE): type_multiplier = 3
multiplier = 2 elif self.proto.resource_type == ResourceData.RESOURCE_TYPE_FONT_RESOURCE:
return multiplier * 100 - self.proto.average_position type_multiplier = 2
return (100 * (priority_multiplier * 100 + type_multiplier * 10)
- self.proto.average_position)
@classmethod @classmethod
def FromRow(cls, row): def FromRow(cls, row):
......
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