Commit 99792c43 authored by Robert Ogden's avatar Robert Ogden Committed by Commit Bot

Add actual prediction triggering to NavPredictor Renderer Warmup

Bug: 1115259
Change-Id: I3e352ce08e93609e047f13f519dede7f9f7296ce
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2358035Reviewed-by: default avatarRyan Sturm <ryansturm@chromium.org>
Commit-Queue: Robert Ogden <robertogden@chromium.org>
Cr-Commit-Position: refs/heads/master@{#799306}
parent bf466ac4
...@@ -37,6 +37,23 @@ NavigationPredictorRendererWarmupClient:: ...@@ -37,6 +37,23 @@ NavigationPredictorRendererWarmupClient::
kNavigationPredictorRendererWarmup, kNavigationPredictorRendererWarmup,
"mem_threshold_mb", "mem_threshold_mb",
1024)), 1024)),
warmup_on_dse_(base::GetFieldTrialParamByFeatureAsBool(
kNavigationPredictorRendererWarmup,
"warmup_on_dse",
true)),
use_navigation_predictions_(base::GetFieldTrialParamByFeatureAsBool(
kNavigationPredictorRendererWarmup,
"use_navigation_predictions",
true)),
examine_top_n_predictions_(base::GetFieldTrialParamByFeatureAsInt(
kNavigationPredictorRendererWarmup,
"examine_top_n_predictions",
10)),
prediction_crosss_origin_threshold_(
base::GetFieldTrialParamByFeatureAsDouble(
kNavigationPredictorRendererWarmup,
"prediction_crosss_origin_threshold",
0.5)),
cooldown_duration_(base::TimeDelta::FromMilliseconds( cooldown_duration_(base::TimeDelta::FromMilliseconds(
base::GetFieldTrialParamByFeatureAsInt( base::GetFieldTrialParamByFeatureAsInt(
kNavigationPredictorRendererWarmup, kNavigationPredictorRendererWarmup,
...@@ -74,9 +91,10 @@ void NavigationPredictorRendererWarmupClient::OnPredictionUpdated( ...@@ -74,9 +91,10 @@ void NavigationPredictorRendererWarmupClient::OnPredictionUpdated(
return; return;
} }
// TODO(robertogden): Actually use the predicted URLs. if (IsEligibleForCrossNavigationWarmup(*prediction) ||
IsEligibleForDSEWarmup(*prediction)) {
RecordMetricsAndMaybeDoWarmup(); RecordMetricsAndMaybeDoWarmup();
}
} }
void NavigationPredictorRendererWarmupClient::DoRendererWarmpup() { void NavigationPredictorRendererWarmupClient::DoRendererWarmpup() {
...@@ -117,6 +135,61 @@ bool NavigationPredictorRendererWarmupClient:: ...@@ -117,6 +135,61 @@ bool NavigationPredictorRendererWarmupClient::
return true; return true;
} }
bool NavigationPredictorRendererWarmupClient::
IsEligibleForCrossNavigationWarmup(
const NavigationPredictorKeyedService::Prediction& prediction) const {
if (!use_navigation_predictions_) {
return false;
}
url::Origin src_origin =
url::Origin::Create(prediction.source_document_url().value());
const std::vector<GURL> urls = prediction.sorted_predicted_urls();
size_t examine_n_urls =
std::min(urls.size(), static_cast<size_t>(examine_top_n_predictions_));
if (examine_n_urls == 0) {
return false;
}
int cross_origin_count = 0;
for (size_t i = 0; i < examine_n_urls; ++i) {
const GURL& url = urls[i];
if (!url.is_valid()) {
continue;
}
if (!url.SchemeIsHTTPOrHTTPS()) {
continue;
}
url::Origin url_origin = url::Origin::Create(url);
if (!url_origin.IsSameOriginWith(src_origin)) {
cross_origin_count++;
}
}
// Just in case there's very few links on a page, check against the threshold
// as a ratio. This may be helpful on redirector sites, like Cloudflare's DDoS
// checker.
double cross_origin_ratio = static_cast<double>(cross_origin_count) /
static_cast<double>(examine_n_urls);
return cross_origin_ratio >= prediction_crosss_origin_threshold_;
}
bool NavigationPredictorRendererWarmupClient::IsEligibleForDSEWarmup(
const NavigationPredictorKeyedService::Prediction& prediction) const {
if (!warmup_on_dse_) {
return false;
}
return TemplateURLServiceFactory::GetForProfile(profile_)
->IsSearchResultsPageFromDefaultSearchProvider(
prediction.source_document_url().value());
}
void NavigationPredictorRendererWarmupClient::RecordMetricsAndMaybeDoWarmup() { void NavigationPredictorRendererWarmupClient::RecordMetricsAndMaybeDoWarmup() {
last_warmup_time_ = tick_clock_->NowTicks(); last_warmup_time_ = tick_clock_->NowTicks();
......
...@@ -43,6 +43,16 @@ class NavigationPredictorRendererWarmupClient ...@@ -43,6 +43,16 @@ class NavigationPredictorRendererWarmupClient
// renderer too recently. // renderer too recently.
bool IsEligibleForWarmupOnCommonCriteria() const; bool IsEligibleForWarmupOnCommonCriteria() const;
// Checks if the |prediction| is eligible to trigger a renderer warmup based
// on the number of predicted origins.
bool IsEligibleForCrossNavigationWarmup(
const NavigationPredictorKeyedService::Prediction& prediction) const;
// Checks if the |prediction| is eligible to trigger a renderer warmup based
// on the current page being search results for the default search engine.
bool IsEligibleForDSEWarmup(
const NavigationPredictorKeyedService::Prediction& prediction) const;
// Records class state and metrics before checking |counterfactual_| and then // Records class state and metrics before checking |counterfactual_| and then
// calling |DoRendererWarmpup| if |counterfactual_| is false. // calling |DoRendererWarmpup| if |counterfactual_| is false.
void RecordMetricsAndMaybeDoWarmup(); void RecordMetricsAndMaybeDoWarmup();
...@@ -57,6 +67,18 @@ class NavigationPredictorRendererWarmupClient ...@@ -57,6 +67,18 @@ class NavigationPredictorRendererWarmupClient
// renderer warmup. // renderer warmup.
const int mem_threshold_mb_; const int mem_threshold_mb_;
// Whether to initiate a renderer warmup on a search result page for the
// default search engine.
const bool warmup_on_dse_;
// Whether to initiate a renderer warmup based on the top N predictions being
// cross origin.
const bool use_navigation_predictions_;
// How many prediction urls to examine.
const int examine_top_n_predictions_;
// The threshold ratio of how many of the top urls need to be cross-origin.
const double prediction_crosss_origin_threshold_;
// The tick clock used within this class. // The tick clock used within this class.
const base::TickClock* tick_clock_; const base::TickClock* tick_clock_;
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
namespace { namespace {
constexpr char kGoogleSearchURL[] = "https://www.google.com/search?q=test"; constexpr char kGoogleSearchURL[] = "https://www.google.com/search?q=test";
constexpr char kOriginA[] = "https://a.test";
constexpr char kOriginB[] = "https://b.test";
const base::Feature kNavigationPredictorRendererWarmup{ const base::Feature kNavigationPredictorRendererWarmup{
"NavigationPredictorRendererWarmup", base::FEATURE_DISABLED_BY_DEFAULT}; "NavigationPredictorRendererWarmup", base::FEATURE_DISABLED_BY_DEFAULT};
...@@ -87,28 +89,57 @@ class NavigationPredictorRendererWarmupClientTest ...@@ -87,28 +89,57 @@ class NavigationPredictorRendererWarmupClientTest
std::unique_ptr<TestNavigationPredictorRendererWarmupClient> client_; std::unique_ptr<TestNavigationPredictorRendererWarmupClient> client_;
}; };
TEST_F(NavigationPredictorRendererWarmupClientTest, SuccessCase) { TEST_F(NavigationPredictorRendererWarmupClientTest, SuccessCase_Search) {
base::test::ScopedFeatureList scoped_feature_list; base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeatureWithParameters( scoped_feature_list.InitAndEnableFeatureWithParameters(
kNavigationPredictorRendererWarmup, { kNavigationPredictorRendererWarmup,
{"counterfactual", "false"}, {
{"mem_threshold_mb", "0"}, {"counterfactual", "false"},
{"cooldown_duration_ms", "60000"}, {"mem_threshold_mb", "0"},
}); {"warmup_on_dse", "true"},
{"use_navigation_predictions", "true"},
{"examine_top_n_predictions", "10"},
{"prediction_crosss_origin_threshold", "0.5"},
{"cooldown_duration_ms", "60000"},
});
client()->OnPredictionUpdated( client()->OnPredictionUpdated(
CreateValidPrediction(GURL(kGoogleSearchURL), {})); CreateValidPrediction(GURL(kGoogleSearchURL), {}));
EXPECT_TRUE(client()->DidDoRendererWarmup()); EXPECT_TRUE(client()->DidDoRendererWarmup());
} }
TEST_F(NavigationPredictorRendererWarmupClientTest, SuccessCase_CrossOrigin) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeatureWithParameters(
kNavigationPredictorRendererWarmup,
{
{"counterfactual", "false"},
{"mem_threshold_mb", "0"},
{"warmup_on_dse", "true"},
{"use_navigation_predictions", "true"},
{"examine_top_n_predictions", "10"},
{"prediction_crosss_origin_threshold", "0.5"},
{"cooldown_duration_ms", "60000"},
});
client()->OnPredictionUpdated(
CreateValidPrediction(GURL(kOriginA), {GURL(kOriginB)}));
EXPECT_TRUE(client()->DidDoRendererWarmup());
}
TEST_F(NavigationPredictorRendererWarmupClientTest, SuccessCase_AfterCooldown) { TEST_F(NavigationPredictorRendererWarmupClientTest, SuccessCase_AfterCooldown) {
base::test::ScopedFeatureList scoped_feature_list; base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeatureWithParameters( scoped_feature_list.InitAndEnableFeatureWithParameters(
kNavigationPredictorRendererWarmup, { kNavigationPredictorRendererWarmup,
{"counterfactual", "false"}, {
{"mem_threshold_mb", "0"}, {"counterfactual", "false"},
{"cooldown_duration_ms", "100"}, {"mem_threshold_mb", "0"},
}); {"warmup_on_dse", "true"},
{"use_navigation_predictions", "true"},
{"examine_top_n_predictions", "10"},
{"prediction_crosss_origin_threshold", "0.5"},
{"cooldown_duration_ms", "100"},
});
client()->OnPredictionUpdated( client()->OnPredictionUpdated(
CreateValidPrediction(GURL(kGoogleSearchURL), {})); CreateValidPrediction(GURL(kGoogleSearchURL), {}));
...@@ -126,11 +157,16 @@ TEST_F(NavigationPredictorRendererWarmupClientTest, SuccessCase_AfterCooldown) { ...@@ -126,11 +157,16 @@ TEST_F(NavigationPredictorRendererWarmupClientTest, SuccessCase_AfterCooldown) {
TEST_F(NavigationPredictorRendererWarmupClientTest, NullPrediction) { TEST_F(NavigationPredictorRendererWarmupClientTest, NullPrediction) {
base::test::ScopedFeatureList scoped_feature_list; base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeatureWithParameters( scoped_feature_list.InitAndEnableFeatureWithParameters(
kNavigationPredictorRendererWarmup, { kNavigationPredictorRendererWarmup,
{"counterfactual", "false"}, {
{"mem_threshold_mb", "0"}, {"counterfactual", "false"},
{"cooldown_duration_ms", "60000"}, {"mem_threshold_mb", "0"},
}); {"warmup_on_dse", "true"},
{"use_navigation_predictions", "true"},
{"examine_top_n_predictions", "10"},
{"prediction_crosss_origin_threshold", "0.5"},
{"cooldown_duration_ms", "60000"},
});
client()->OnPredictionUpdated(base::nullopt); client()->OnPredictionUpdated(base::nullopt);
EXPECT_FALSE(client()->DidDoRendererWarmup()); EXPECT_FALSE(client()->DidDoRendererWarmup());
...@@ -139,11 +175,16 @@ TEST_F(NavigationPredictorRendererWarmupClientTest, NullPrediction) { ...@@ -139,11 +175,16 @@ TEST_F(NavigationPredictorRendererWarmupClientTest, NullPrediction) {
TEST_F(NavigationPredictorRendererWarmupClientTest, BadPredictionSrc) { TEST_F(NavigationPredictorRendererWarmupClientTest, BadPredictionSrc) {
base::test::ScopedFeatureList scoped_feature_list; base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeatureWithParameters( scoped_feature_list.InitAndEnableFeatureWithParameters(
kNavigationPredictorRendererWarmup, { kNavigationPredictorRendererWarmup,
{"counterfactual", "false"}, {
{"mem_threshold_mb", "0"}, {"counterfactual", "false"},
{"cooldown_duration_ms", "60000"}, {"mem_threshold_mb", "0"},
}); {"warmup_on_dse", "true"},
{"use_navigation_predictions", "true"},
{"examine_top_n_predictions", "10"},
{"prediction_crosss_origin_threshold", "0.5"},
{"cooldown_duration_ms", "60000"},
});
client()->OnPredictionUpdated(NavigationPredictorKeyedService::Prediction( client()->OnPredictionUpdated(NavigationPredictorKeyedService::Prediction(
nullptr, base::nullopt, std::vector<std::string>{""}, nullptr, base::nullopt, std::vector<std::string>{""},
...@@ -155,11 +196,16 @@ TEST_F(NavigationPredictorRendererWarmupClientTest, BadPredictionSrc) { ...@@ -155,11 +196,16 @@ TEST_F(NavigationPredictorRendererWarmupClientTest, BadPredictionSrc) {
TEST_F(NavigationPredictorRendererWarmupClientTest, CoolDown) { TEST_F(NavigationPredictorRendererWarmupClientTest, CoolDown) {
base::test::ScopedFeatureList scoped_feature_list; base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeatureWithParameters( scoped_feature_list.InitAndEnableFeatureWithParameters(
kNavigationPredictorRendererWarmup, { kNavigationPredictorRendererWarmup,
{"counterfactual", "false"}, {
{"mem_threshold_mb", "0"}, {"counterfactual", "false"},
{"cooldown_duration_ms", "60000"}, {"mem_threshold_mb", "0"},
}); {"warmup_on_dse", "true"},
{"use_navigation_predictions", "true"},
{"examine_top_n_predictions", "10"},
{"prediction_crosss_origin_threshold", "0.5"},
{"cooldown_duration_ms", "60000"},
});
client()->OnPredictionUpdated( client()->OnPredictionUpdated(
CreateValidPrediction(GURL(kGoogleSearchURL), {})); CreateValidPrediction(GURL(kGoogleSearchURL), {}));
...@@ -175,11 +221,16 @@ TEST_F(NavigationPredictorRendererWarmupClientTest, CoolDown) { ...@@ -175,11 +221,16 @@ TEST_F(NavigationPredictorRendererWarmupClientTest, CoolDown) {
TEST_F(NavigationPredictorRendererWarmupClientTest, HasSpareRenderer) { TEST_F(NavigationPredictorRendererWarmupClientTest, HasSpareRenderer) {
base::test::ScopedFeatureList scoped_feature_list; base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeatureWithParameters( scoped_feature_list.InitAndEnableFeatureWithParameters(
kNavigationPredictorRendererWarmup, { kNavigationPredictorRendererWarmup,
{"counterfactual", "false"}, {
{"mem_threshold_mb", "0"}, {"counterfactual", "false"},
{"cooldown_duration_ms", "60000"}, {"mem_threshold_mb", "0"},
}); {"warmup_on_dse", "true"},
{"use_navigation_predictions", "true"},
{"examine_top_n_predictions", "10"},
{"prediction_crosss_origin_threshold", "0.5"},
{"cooldown_duration_ms", "60000"},
});
client()->SetBrowserHasSpareRenderer(true); client()->SetBrowserHasSpareRenderer(true);
client()->OnPredictionUpdated( client()->OnPredictionUpdated(
...@@ -196,14 +247,134 @@ TEST_F(NavigationPredictorRendererWarmupClientTest, FeatureOff) { ...@@ -196,14 +247,134 @@ TEST_F(NavigationPredictorRendererWarmupClientTest, FeatureOff) {
EXPECT_FALSE(client()->DidDoRendererWarmup()); EXPECT_FALSE(client()->DidDoRendererWarmup());
} }
TEST_F(NavigationPredictorRendererWarmupClientTest, DSEWarmupNotEnabled) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeatureWithParameters(
kNavigationPredictorRendererWarmup,
{
{"counterfactual", "false"},
{"mem_threshold_mb", "0"},
{"warmup_on_dse", "false"},
{"use_navigation_predictions", "true"},
{"examine_top_n_predictions", "10"},
{"prediction_crosss_origin_threshold", "0.5"},
{"cooldown_duration_ms", "60000"},
});
client()->OnPredictionUpdated(
CreateValidPrediction(GURL(kGoogleSearchURL), {}));
EXPECT_FALSE(client()->DidDoRendererWarmup());
}
TEST_F(NavigationPredictorRendererWarmupClientTest, NotSearchURL) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeatureWithParameters(
kNavigationPredictorRendererWarmup,
{
{"counterfactual", "false"},
{"mem_threshold_mb", "0"},
{"warmup_on_dse", "true"},
{"use_navigation_predictions", "true"},
{"examine_top_n_predictions", "10"},
{"prediction_crosss_origin_threshold", "0.5"},
{"cooldown_duration_ms", "60000"},
});
client()->OnPredictionUpdated(
CreateValidPrediction(GURL("http://test.com/"), {}));
EXPECT_FALSE(client()->DidDoRendererWarmup());
}
TEST_F(NavigationPredictorRendererWarmupClientTest, InvalidCrossOrigins) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeatureWithParameters(
kNavigationPredictorRendererWarmup,
{
{"counterfactual", "false"},
{"mem_threshold_mb", "0"},
{"warmup_on_dse", "true"},
{"use_navigation_predictions", "true"},
{"examine_top_n_predictions", "10"},
{"prediction_crosss_origin_threshold", "0.5"},
{"cooldown_duration_ms", "60000"},
});
client()->OnPredictionUpdated(
CreateValidPrediction(GURL(kOriginA), {GURL()}));
EXPECT_FALSE(client()->DidDoRendererWarmup());
}
TEST_F(NavigationPredictorRendererWarmupClientTest, NonHTTPCrossOrigins) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeatureWithParameters(
kNavigationPredictorRendererWarmup,
{
{"counterfactual", "false"},
{"mem_threshold_mb", "0"},
{"warmup_on_dse", "true"},
{"use_navigation_predictions", "true"},
{"examine_top_n_predictions", "10"},
{"prediction_crosss_origin_threshold", "0.5"},
{"cooldown_duration_ms", "60000"},
});
client()->OnPredictionUpdated(
CreateValidPrediction(GURL(kOriginA), {GURL("ftp://test.com")}));
EXPECT_FALSE(client()->DidDoRendererWarmup());
}
TEST_F(NavigationPredictorRendererWarmupClientTest,
CrossOriginsBelowThreshold) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeatureWithParameters(
kNavigationPredictorRendererWarmup,
{
{"counterfactual", "false"},
{"mem_threshold_mb", "0"},
{"warmup_on_dse", "true"},
{"use_navigation_predictions", "true"},
{"examine_top_n_predictions", "10"},
{"prediction_crosss_origin_threshold", "0.5"},
{"cooldown_duration_ms", "60000"},
});
client()->OnPredictionUpdated(CreateValidPrediction(
GURL(kOriginA), {GURL(kOriginA), GURL(kOriginA), GURL(kOriginB)}));
EXPECT_FALSE(client()->DidDoRendererWarmup());
}
TEST_F(NavigationPredictorRendererWarmupClientTest, CrossOriginNotEnabled) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeatureWithParameters(
kNavigationPredictorRendererWarmup,
{
{"counterfactual", "false"},
{"mem_threshold_mb", "0"},
{"warmup_on_dse", "true"},
{"use_navigation_predictions", "false"},
{"examine_top_n_predictions", "10"},
{"prediction_crosss_origin_threshold", "0.5"},
{"cooldown_duration_ms", "60000"},
});
client()->OnPredictionUpdated(
CreateValidPrediction(GURL(kOriginA), {GURL(kOriginB)}));
EXPECT_FALSE(client()->DidDoRendererWarmup());
}
TEST_F(NavigationPredictorRendererWarmupClientTest, Counterfactual) { TEST_F(NavigationPredictorRendererWarmupClientTest, Counterfactual) {
base::test::ScopedFeatureList scoped_feature_list; base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeatureWithParameters( scoped_feature_list.InitAndEnableFeatureWithParameters(
kNavigationPredictorRendererWarmup, { kNavigationPredictorRendererWarmup,
{"counterfactual", "true"}, {
{"mem_threshold_mb", "0"}, {"counterfactual", "true"},
{"cooldown_duration_ms", "60000"}, {"mem_threshold_mb", "0"},
}); {"warmup_on_dse", "true"},
{"use_navigation_predictions", "true"},
{"examine_top_n_predictions", "10"},
{"prediction_crosss_origin_threshold", "0.5"},
{"cooldown_duration_ms", "60000"},
});
client()->OnPredictionUpdated( client()->OnPredictionUpdated(
CreateValidPrediction(GURL(kGoogleSearchURL), {})); CreateValidPrediction(GURL(kGoogleSearchURL), {}));
...@@ -217,6 +388,10 @@ TEST_F(NavigationPredictorRendererWarmupClientTest, MemThreshold) { ...@@ -217,6 +388,10 @@ TEST_F(NavigationPredictorRendererWarmupClientTest, MemThreshold) {
{ {
{"counterfactual", "true"}, {"counterfactual", "true"},
{"mem_threshold_mb", "99999999999"}, {"mem_threshold_mb", "99999999999"},
{"warmup_on_dse", "true"},
{"use_navigation_predictions", "true"},
{"examine_top_n_predictions", "10"},
{"prediction_crosss_origin_threshold", "0.5"},
{"cooldown_duration_ms", "60000"}, {"cooldown_duration_ms", "60000"},
}); });
......
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