Commit 299ee7d2 authored by Chris Hamilton's avatar Chris Hamilton Committed by Commit Bot

Add feature/variations for ProactiveTabDiscarding.

BUG=727353

Change-Id: I8402fcf4a28753ed75a9edabd7ee1478985312df
Reviewed-on: https://chromium-review.googlesource.com/791570
Commit-Queue: Chris Hamilton <chrisha@chromium.org>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Cr-Commit-Position: refs/heads/master@{#524478}
parent 25fb9659
...@@ -15,6 +15,17 @@ constexpr char kTabLoadTimeoutInMsParameterName[] = "tabLoadTimeoutInMs"; ...@@ -15,6 +15,17 @@ constexpr char kTabLoadTimeoutInMsParameterName[] = "tabLoadTimeoutInMs";
namespace features { namespace features {
// Enables using customized value for tab load timeout. This is used by both
// staggered background tab opening and session restore in finch experiment to
// see what timeout value is better. The default timeout is used when this
// feature is disabled.
const base::Feature kCustomizedTabLoadTimeout{
"CustomizedTabLoadTimeout", base::FEATURE_DISABLED_BY_DEFAULT};
// Enables proactive tab discarding.
const base::Feature kProactiveTabDiscarding{"ProactiveTabDiscarding",
base::FEATURE_DISABLED_BY_DEFAULT};
// Enables delaying the navigation of background tabs in order to improve // Enables delaying the navigation of background tabs in order to improve
// foreground tab's user experience. // foreground tab's user experience.
const base::Feature kStaggeredBackgroundTabOpening{ const base::Feature kStaggeredBackgroundTabOpening{
...@@ -27,17 +38,84 @@ const base::Feature kStaggeredBackgroundTabOpeningExperiment{ ...@@ -27,17 +38,84 @@ const base::Feature kStaggeredBackgroundTabOpeningExperiment{
"StaggeredBackgroundTabOpeningExperiment", "StaggeredBackgroundTabOpeningExperiment",
base::FEATURE_ENABLED_BY_DEFAULT}; base::FEATURE_ENABLED_BY_DEFAULT};
// Enables using customized value for tab load timeout. This is used by both
// staggered background tab opening and session restore in finch experiment to
// see what timeout value is better. The default timeout is used when this
// feature is disabled.
const base::Feature kCustomizedTabLoadTimeout{
"CustomizedTabLoadTimeout", base::FEATURE_DISABLED_BY_DEFAULT};
} // namespace features } // namespace features
namespace resource_coordinator { namespace resource_coordinator {
// Field-trial parameter names for proactive tab discarding.
const char kProactiveTabDiscard_LowLoadedTabCountParam[] = "LowLoadedTabCount";
const char kProactiveTabDiscard_ModerateLoadedTabsPerGbRamParam[] =
"ModerateLoadedTabsPerGbRam";
const char kProactiveTabDiscard_HighLoadedTabCountParam[] =
"HighLoadedTabCount";
const char kProactiveTabDiscard_LowOccludedTimeoutParam[] =
"LowOccludedTimeoutSeconds";
const char kProactiveTabDiscard_ModerateOccludedTimeoutParam[] =
"ModerateOccludedTimeoutSeconds";
const char kProactiveTabDiscard_HighOccludedTimeoutParam[] =
"HighOccludedTimeoutSeconds";
// Default values for ProactiveTabDiscardParams.
//
// 50% of people cap out at 4 tabs, so for them proactive discarding won't even
// be invoked. See Tabs.MaxTabsInADay.
// TODO(chrisha): This should eventually be informed by the number of tabs
// typically used over a given time horizon (metric being developed).
const uint32_t kProactiveTabDiscard_LowLoadedTabCountDefault = 4;
// Testing in the lab shows that 2GB devices suffer beyond 6 tabs, and 4GB
// devices suffer beyond about 12 tabs. As a very simple first step, we'll aim
// at allowing 3 tabs per GB of RAM on a system before proactive discarding
// kicks in. This is a system resource dependent max, which is combined with the
// DefaultMaxLoadedTabCount to determine the max on a system.
const uint32_t kProactiveTabDiscard_ModerateLoadedTabsPerGbRamDefault = 3;
// 99.9% of people cap out with fewer than this number, so only 0.1% of the
// population should ever encounter proactive discarding based on this cap.
const uint32_t kProactiveTabDiscard_HighLoadedTabCountDefault = 100;
// Current discarding uses 10 minutes as a minimum cap. This uses exponentially
// increasing timeouts beyond that.
const base::TimeDelta kProactiveTabDiscard_LowOccludedTimeoutDefault =
base::TimeDelta::FromHours(6);
const base::TimeDelta kProactiveTabDiscard_ModerateOccludedTimeoutDefault =
base::TimeDelta::FromHours(1);
const base::TimeDelta kProactiveTabDiscard_HighOccludedTimeoutDefault =
base::TimeDelta::FromMinutes(10);
void GetProactiveTabDiscardParams(ProactiveTabDiscardParams* params) {
params->low_loaded_tab_count = base::GetFieldTrialParamByFeatureAsInt(
features::kProactiveTabDiscarding,
kProactiveTabDiscard_LowLoadedTabCountParam,
kProactiveTabDiscard_LowLoadedTabCountDefault);
params->moderate_loaded_tab_count_per_gb =
base::GetFieldTrialParamByFeatureAsInt(
features::kProactiveTabDiscarding,
kProactiveTabDiscard_ModerateLoadedTabsPerGbRamParam,
kProactiveTabDiscard_ModerateLoadedTabsPerGbRamDefault);
params->high_loaded_tab_count = base::GetFieldTrialParamByFeatureAsInt(
features::kProactiveTabDiscarding,
kProactiveTabDiscard_HighLoadedTabCountParam,
kProactiveTabDiscard_HighLoadedTabCountDefault);
params->low_occluded_timeout =
base::TimeDelta::FromSeconds(base::GetFieldTrialParamByFeatureAsInt(
features::kProactiveTabDiscarding,
kProactiveTabDiscard_LowOccludedTimeoutParam,
kProactiveTabDiscard_LowOccludedTimeoutDefault.InSeconds()));
params->moderate_occluded_timeout =
base::TimeDelta::FromSeconds(base::GetFieldTrialParamByFeatureAsInt(
features::kProactiveTabDiscarding,
kProactiveTabDiscard_ModerateOccludedTimeoutParam,
kProactiveTabDiscard_ModerateOccludedTimeoutDefault.InSeconds()));
params->high_occluded_timeout =
base::TimeDelta::FromSeconds(base::GetFieldTrialParamByFeatureAsInt(
features::kProactiveTabDiscarding,
kProactiveTabDiscard_HighOccludedTimeoutParam,
kProactiveTabDiscard_HighOccludedTimeoutDefault.InSeconds()));
}
base::TimeDelta GetTabLoadTimeout(const base::TimeDelta& default_timeout) { base::TimeDelta GetTabLoadTimeout(const base::TimeDelta& default_timeout) {
int timeout_in_ms = base::GetFieldTrialParamByFeatureAsInt( int timeout_in_ms = base::GetFieldTrialParamByFeatureAsInt(
features::kCustomizedTabLoadTimeout, kTabLoadTimeoutInMsParameterName, features::kCustomizedTabLoadTimeout, kTabLoadTimeoutInMsParameterName,
......
...@@ -10,14 +10,98 @@ ...@@ -10,14 +10,98 @@
namespace features { namespace features {
extern const base::Feature kCustomizedTabLoadTimeout;
extern const base::Feature kProactiveTabDiscarding;
extern const base::Feature kStaggeredBackgroundTabOpening; extern const base::Feature kStaggeredBackgroundTabOpening;
extern const base::Feature kStaggeredBackgroundTabOpeningExperiment; extern const base::Feature kStaggeredBackgroundTabOpeningExperiment;
extern const base::Feature kCustomizedTabLoadTimeout;
} // namespace features } // namespace features
namespace resource_coordinator { namespace resource_coordinator {
// Variations parameter names related to proactive discarding.
// See ProactiveTabDiscardsParams for details.
extern const char kProactiveTabDiscard_LowLoadedTabCountParam[];
extern const char kProactiveTabDiscard_ModerateLoadedTabsPerGbRamParam[];
extern const char kProactiveTabDiscard_HighLoadedTabCountParam[];
extern const char kProactiveTabDiscard_LowOccludedTimeoutParam[];
extern const char kProactiveTabDiscard_ModerateOccludedTimeoutParam[];
extern const char kProactiveTabDiscard_HighOccludedTimeoutParam[];
// Default values of parameters related to proactive discarding.
// See ProactiveTabDiscardsParams for details.
extern const uint32_t kProactiveTabDiscard_LowLoadedTabCountDefault;
extern const uint32_t kProactiveTabDiscard_ModerateLoadedTabsPerGbRamDefault;
extern const uint32_t kProactiveTabDiscard_HighLoadedTabCountDefault;
extern const base::TimeDelta kProactiveTabDiscard_LowOccludedTimeoutDefault;
extern const base::TimeDelta
kProactiveTabDiscard_ModerateOccludedTimeoutDefault;
extern const base::TimeDelta kProactiveTabDiscard_HighOccludedTimeoutDefault;
// Parameters used by the proactive tab discarding feature.
//
// Proactive discarding has 5 key parameters:
//
// - min/max occluded timeouts
// - min/soft_max/hard_max loaded tab counts
//
// Proactive tab discarding decisions are made at two points in time:
//
// - when a new tab is created
// - when a max occluded timeout fires
//
// The following is a description of the initial simple proactive discarding
// logic. First, the number of loaded tabs is converted into one of 4 tab count
// states (LOW, MODERATE, HIGH, EXCESSIVE) using 3 simple thresholds.
//
// +-------+----------+---------+-----------+
// + LOW | MODERATE | HIGH | EXCESSIVE |
// +-------+----------+---------+-----------+
// 0 n_low n_mod n_high +inf
//
// Depending on the tab count state, tabs are eligible for proactive discarding
// at different time tresholds, where the timeout is longer for lower tab
// count states. When in the low state the timeout is effectively infinite (no
// proactive discarding will occur), and when in the excessive state the timeout
// is zero (discarding will occur immediately).
//
// This logic is independent of urgent discarding, which may embark when things
// are sufficiently bad. Similarly, manual or extension driven discards can
// override this logic. Finally, proactive discarding can only discard occluded
// tabs, so it is always possible to have arbitrarily many visible tabs.
//
// NOTE: This is extremely simplistic, and by design. We will be using this to
// do a very simple "lightspeed" experiment to determine how much possible
// savings proactive discarding can hope to achieve.
struct ProactiveTabDiscardParams {
// Tab count (inclusive) beyond which the state transitions to MODERATE.
// Intended to cover the majority of simple workflows and be small enough that
// it is very unlikely that memory pressure will be encountered with this many
// tabs loaded.
int low_loaded_tab_count;
// Tab count (inclusive) beyond which the state transitions to HIGH, expressed
// relative to system memory.
int moderate_loaded_tab_count_per_gb;
// Tab count (inclusive) beyond which the state transitions to EXCESSIVE.
// Not expressed relative to system memory, as its intended to be a hard cap
// more akin to a maximum mental model size.
int high_loaded_tab_count;
// Amount of time a tab must be occluded before eligible for proactive
// discard when the tab count state is LOW.
base::TimeDelta low_occluded_timeout;
// Amount of time a tab must be occluded before eligible for proactive
// discard when the tab count state is MODERATE.
base::TimeDelta moderate_occluded_timeout;
// Amount of time a tab must be occluded before eligible for proactive
// discard when the tab count state is HIGH.
base::TimeDelta high_occluded_timeout;
};
// Gets parameters for the proactive tab discarding feature. This does no
// parameter validation, and sets the default values if the feature is not
// enabled.
void GetProactiveTabDiscardParams(ProactiveTabDiscardParams* params);
base::TimeDelta GetTabLoadTimeout(const base::TimeDelta& default_timeout); base::TimeDelta GetTabLoadTimeout(const base::TimeDelta& default_timeout);
} // namespace resource_coordinator } // namespace resource_coordinator
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/resource_coordinator/tab_manager_features.h"
#include "base/macros.h"
#include "base/metrics/field_trial.h"
#include "base/strings/string_piece.h"
#include "components/variations/variations_params_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace resource_coordinator {
namespace {
class TabManagerFeaturesTest : public testing::Test {
public:
// Enables the proactive tab discarding feature, and sets up the associated
// variations parameter values.
void EnableProactiveTabDiscarding() {
std::set<std::string> features;
features.insert(features::kProactiveTabDiscarding.name);
variations_manager_.SetVariationParamsWithFeatureAssociations(
"DummyTrial", params_, features);
}
void SetParam(base::StringPiece key, base::StringPiece value) {
params_[key.as_string()] = value.as_string();
}
void ExpectProactiveTabDiscardingParams(
int low_loaded_tab_count,
int moderate_loaded_tab_count_per_gb,
int high_loaded_tab_count,
base::TimeDelta low_occluded_timeout,
base::TimeDelta moderate_occluded_timeout,
base::TimeDelta high_occluded_timeout) {
ProactiveTabDiscardParams params = {};
GetProactiveTabDiscardParams(&params);
EXPECT_EQ(low_loaded_tab_count, params.low_loaded_tab_count);
EXPECT_EQ(moderate_loaded_tab_count_per_gb,
params.moderate_loaded_tab_count_per_gb);
EXPECT_EQ(high_loaded_tab_count, params.high_loaded_tab_count);
EXPECT_EQ(low_occluded_timeout, params.low_occluded_timeout);
EXPECT_EQ(moderate_occluded_timeout, params.moderate_occluded_timeout);
EXPECT_EQ(high_occluded_timeout, params.high_occluded_timeout);
}
void ExpectDefaultProactiveTabDiscardParams() {
ExpectProactiveTabDiscardingParams(
kProactiveTabDiscard_LowLoadedTabCountDefault,
kProactiveTabDiscard_ModerateLoadedTabsPerGbRamDefault,
kProactiveTabDiscard_HighLoadedTabCountDefault,
kProactiveTabDiscard_LowOccludedTimeoutDefault,
kProactiveTabDiscard_ModerateOccludedTimeoutDefault,
kProactiveTabDiscard_HighOccludedTimeoutDefault);
}
private:
std::map<std::string, std::string> params_;
variations::testing::VariationParamsManager variations_manager_;
};
} // namespace
TEST_F(TabManagerFeaturesTest,
GetProactiveTabDiscardParamsDisabledFeatureGoesToDefault) {
// Do not enable the proactive tab discarding feature.
ExpectDefaultProactiveTabDiscardParams();
}
TEST_F(TabManagerFeaturesTest, GetProactiveTabDiscardParamsNoneGoesToDefault) {
EnableProactiveTabDiscarding();
ExpectDefaultProactiveTabDiscardParams();
}
TEST_F(TabManagerFeaturesTest,
GetProactiveTabDiscardParamsInvalidGoesToDefault) {
SetParam(kProactiveTabDiscard_LowLoadedTabCountParam, "ab");
SetParam(kProactiveTabDiscard_ModerateLoadedTabsPerGbRamParam, "27.8");
SetParam(kProactiveTabDiscard_HighLoadedTabCountParam, "4e8");
SetParam(kProactiveTabDiscard_LowOccludedTimeoutParam, "---");
SetParam(kProactiveTabDiscard_ModerateOccludedTimeoutParam, " ");
SetParam(kProactiveTabDiscard_HighOccludedTimeoutParam, "");
EnableProactiveTabDiscarding();
ExpectDefaultProactiveTabDiscardParams();
}
TEST_F(TabManagerFeaturesTest, GetProactiveTabDiscardParams) {
SetParam(kProactiveTabDiscard_LowLoadedTabCountParam, "7");
SetParam(kProactiveTabDiscard_ModerateLoadedTabsPerGbRamParam, "19");
SetParam(kProactiveTabDiscard_HighLoadedTabCountParam, "42");
// These are expressed in seconds.
SetParam(kProactiveTabDiscard_LowOccludedTimeoutParam, "60");
SetParam(kProactiveTabDiscard_ModerateOccludedTimeoutParam, "120");
SetParam(kProactiveTabDiscard_HighOccludedTimeoutParam, "247");
EnableProactiveTabDiscarding();
ExpectProactiveTabDiscardingParams(
7, 19, 42, base::TimeDelta::FromSeconds(60),
base::TimeDelta::FromSeconds(120), base::TimeDelta::FromSeconds(247));
}
} // namespace resource_coordinator
...@@ -2783,6 +2783,7 @@ test("unit_tests") { ...@@ -2783,6 +2783,7 @@ test("unit_tests") {
"../browser/resource_coordinator/tab_lifecycle_unit_source_unittest.cc", "../browser/resource_coordinator/tab_lifecycle_unit_source_unittest.cc",
"../browser/resource_coordinator/tab_lifecycle_unit_unittest.cc", "../browser/resource_coordinator/tab_lifecycle_unit_unittest.cc",
"../browser/resource_coordinator/tab_manager_delegate_chromeos_unittest.cc", "../browser/resource_coordinator/tab_manager_delegate_chromeos_unittest.cc",
"../browser/resource_coordinator/tab_manager_features_unittest.cc",
"../browser/resource_coordinator/tab_manager_stats_collector_unittest.cc", "../browser/resource_coordinator/tab_manager_stats_collector_unittest.cc",
"../browser/resource_coordinator/tab_manager_unittest.cc", "../browser/resource_coordinator/tab_manager_unittest.cc",
"../browser/resource_coordinator/tab_manager_web_contents_data_unittest.cc", "../browser/resource_coordinator/tab_manager_web_contents_data_unittest.cc",
......
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