Commit 76d98893 authored by Francois Doray's avatar Francois Doray Committed by Commit Bot

[blink scheduler] Disable intensive wake up throttling for timers with low nesting level.

Change description:
-------------------
This CL changes the intensive wake up throttling policy so that it does
not affect the execution of timers with nesting level < 5 :

  In a Window whose top Window has been hidden for 5 minutes and which
  is not opted out from intensive wake up throttling, a timer task can
  run:

  - on a 1-second aligned wake up if:
      - the task's nesting level is < 5, or,
      - the Window is same-origin with the top Window and at least
        1 minute has elapsed since the last timer with nesting level
        >= 5 has run in any Window in the tree that is same-origin with
        the top Window

  - on a 1-minute aligned wake up, otherwise.

Rationale:
----------
Unfortunately, limiting all timers to 1 wake up per minute caused
breakages on some sites. After reaching out to site owners, we
established that opting out timer tasks with nesting level < 5 prevents
these breakages. Local tests suggest that most timers tasks have a
nesting level >= 5. Therefore, we don't expect that this policy change
will have a significant impact on power usage.

Timers with nesting level >= 5 can run on a 1-second aligned wake up
if there hasn't been a wake up in the last minute, because we don't
want to penalize pages that have their own logic to ensure that the wake
up rate is below 1 per minute. For example, a repeating timer with a
90 seconds timeout should not be affected by intensive throttling.

Discussion:
-----------
https://groups.google.com/a/chromium.org/g/scheduler-dev/c/EWKYCZlWjpc

Bug: 1075553
Change-Id: I90d553608b9e3e64a9e6456112d5f4454d51bf1d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2417293Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarSami Kyöstilä <skyostil@chromium.org>
Commit-Queue: François Doray <fdoray@chromium.org>
Cr-Commit-Position: refs/heads/master@{#811281}
parent 524ea367
...@@ -121,5 +121,23 @@ base::TimeDelta GetTimeToInhibitIntensiveThrottlingOnTitleOrFaviconUpdate() { ...@@ -121,5 +121,23 @@ base::TimeDelta GetTimeToInhibitIntensiveThrottlingOnTitleOrFaviconUpdate() {
return base::TimeDelta::FromSeconds(seconds); return base::TimeDelta::FromSeconds(seconds);
} }
bool CanIntensivelyThrottleLowNestingLevel() {
DCHECK(IsIntensiveWakeUpThrottlingEnabled());
static const base::FeatureParam<bool> kFeatureParam{
&features::kIntensiveWakeUpThrottling,
kIntensiveWakeUpThrottling_CanIntensivelyThrottleLowNestingLevel_Name,
kIntensiveWakeUpThrottling_CanIntensivelyThrottleLowNestingLevel_Default};
bool value =
kIntensiveWakeUpThrottling_CanIntensivelyThrottleLowNestingLevel_Default;
if (GetIntensiveWakeUpThrottlingPolicyOverride() ==
PolicyOverride::NO_OVERRIDE) {
value = kFeatureParam.Get();
}
return value;
}
} // namespace scheduler } // namespace scheduler
} // namespace blink } // namespace blink
...@@ -181,10 +181,12 @@ const base::Feature kPrioritizeCompositingAfterInput{ ...@@ -181,10 +181,12 @@ const base::Feature kPrioritizeCompositingAfterInput{
const base::Feature kHighPriorityDatabaseTaskType{ const base::Feature kHighPriorityDatabaseTaskType{
"HighPriorityDatabaseTaskType", base::FEATURE_DISABLED_BY_DEFAULT}; "HighPriorityDatabaseTaskType", base::FEATURE_DISABLED_BY_DEFAULT};
// When features::kIntensiveWakeUpThrottling is enabled, wake ups from // When features::kIntensiveWakeUpThrottling is enabled, wake ups from timers
// throttleable TaskQueues are limited to 1 per // with a high nesting level are limited to 1 per
// GetIntensiveWakeUpThrottlingDurationBetweenWakeUp() in a page that has been // GetIntensiveWakeUpThrottlingDurationBetweenWakeUp() in a page that has been
// backgrounded for GetIntensiveWakeUpThrottlingGracePeriod(). // backgrounded for GetIntensiveWakeUpThrottlingGracePeriod(). If
// CanIntensivelyThrottleLowNestingLevel() is true, this policy is also applied
// to timers with a non-zero delay and a low nesting level.
// //
// Intensive wake up throttling is enforced in addition to other throttling // Intensive wake up throttling is enforced in addition to other throttling
// mechanisms: // mechanisms:
...@@ -193,7 +195,6 @@ const base::Feature kHighPriorityDatabaseTaskType{ ...@@ -193,7 +195,6 @@ const base::Feature kHighPriorityDatabaseTaskType{
// //
// Feature tracking bug: https://crbug.com/1075553 // Feature tracking bug: https://crbug.com/1075553
// //
//
// Note that features::kIntensiveWakeUpThrottling should not be read from; // Note that features::kIntensiveWakeUpThrottling should not be read from;
// rather the provided accessors should be used, which also take into account // rather the provided accessors should be used, which also take into account
// the managed policy override of the feature. // the managed policy override of the feature.
...@@ -204,8 +205,13 @@ constexpr int kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds_Default = ...@@ -204,8 +205,13 @@ constexpr int kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds_Default =
constexpr const char* constexpr const char*
kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds_Name = kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds_Name =
"duration_between_wake_ups_seconds"; "duration_between_wake_ups_seconds";
constexpr int kIntensiveWakeUpThrottling_GracePeriodSeconds_Default = 5 * 60; constexpr int kIntensiveWakeUpThrottling_GracePeriodSeconds_Default = 5 * 60;
constexpr const char*
kIntensiveWakeUpThrottling_CanIntensivelyThrottleLowNestingLevel_Name =
"can_intensively_throttle_low_nesting_level";
constexpr const bool
kIntensiveWakeUpThrottling_CanIntensivelyThrottleLowNestingLevel_Default =
false;
// Exposed so that multiple tests can tinker with the policy override. // Exposed so that multiple tests can tinker with the policy override.
PLATFORM_EXPORT void PLATFORM_EXPORT void
...@@ -224,6 +230,9 @@ PLATFORM_EXPORT base::TimeDelta GetIntensiveWakeUpThrottlingGracePeriod(); ...@@ -224,6 +230,9 @@ PLATFORM_EXPORT base::TimeDelta GetIntensiveWakeUpThrottlingGracePeriod();
// that updating the title or favicon has no effect on intensive throttling. // that updating the title or favicon has no effect on intensive throttling.
PLATFORM_EXPORT base::TimeDelta PLATFORM_EXPORT base::TimeDelta
GetTimeToInhibitIntensiveThrottlingOnTitleOrFaviconUpdate(); GetTimeToInhibitIntensiveThrottlingOnTitleOrFaviconUpdate();
// Whether timers with a non-zero delay and a low nesting level can be
// intensively throttled.
PLATFORM_EXPORT bool CanIntensivelyThrottleLowNestingLevel();
// Per-agent scheduling experiments. // Per-agent scheduling experiments.
constexpr base::Feature kPerAgentSchedulingExperiments{ constexpr base::Feature kPerAgentSchedulingExperiments{
......
...@@ -376,9 +376,17 @@ QueueTraits FrameSchedulerImpl::CreateQueueTraitsForTaskType(TaskType type) { ...@@ -376,9 +376,17 @@ QueueTraits FrameSchedulerImpl::CreateQueueTraitsForTaskType(TaskType type) {
return ThrottleableTaskQueueTraits().SetPrioritisationType( return ThrottleableTaskQueueTraits().SetPrioritisationType(
QueueTraits::PrioritisationType::kBestEffort); QueueTraits::PrioritisationType::kBestEffort);
case TaskType::kJavascriptTimerDelayedLowNesting: case TaskType::kJavascriptTimerDelayedLowNesting:
return ThrottleableTaskQueueTraits()
.SetPrioritisationType(
QueueTraits::PrioritisationType::kJavaScriptTimer)
.SetCanBeIntensivelyThrottled(
IsIntensiveWakeUpThrottlingEnabled() &&
CanIntensivelyThrottleLowNestingLevel());
case TaskType::kJavascriptTimerDelayedHighNesting: case TaskType::kJavascriptTimerDelayedHighNesting:
return ThrottleableTaskQueueTraits().SetPrioritisationType( return ThrottleableTaskQueueTraits()
QueueTraits::PrioritisationType::kJavaScriptTimer); .SetPrioritisationType(
QueueTraits::PrioritisationType::kJavaScriptTimer)
.SetCanBeIntensivelyThrottled(IsIntensiveWakeUpThrottlingEnabled());
case TaskType::kJavascriptTimerImmediate: { case TaskType::kJavascriptTimerImmediate: {
return DeferrableTaskQueueTraits() return DeferrableTaskQueueTraits()
.SetPrioritisationType( .SetPrioritisationType(
......
...@@ -104,6 +104,7 @@ class PLATFORM_EXPORT MainThreadTaskQueue ...@@ -104,6 +104,7 @@ class PLATFORM_EXPORT MainThreadTaskQueue
QueueTraits() QueueTraits()
: can_be_deferred(false), : can_be_deferred(false),
can_be_throttled(false), can_be_throttled(false),
can_be_intensively_throttled(false),
can_be_paused(false), can_be_paused(false),
can_be_frozen(false), can_be_frozen(false),
can_run_in_background(true), can_run_in_background(true),
...@@ -150,6 +151,11 @@ class PLATFORM_EXPORT MainThreadTaskQueue ...@@ -150,6 +151,11 @@ class PLATFORM_EXPORT MainThreadTaskQueue
return *this; return *this;
} }
QueueTraits SetCanBeIntensivelyThrottled(bool value) {
can_be_intensively_throttled = value;
return *this;
}
QueueTraits SetCanBePaused(bool value) { QueueTraits SetCanBePaused(bool value) {
can_be_paused = value; can_be_paused = value;
return *this; return *this;
...@@ -183,6 +189,8 @@ class PLATFORM_EXPORT MainThreadTaskQueue ...@@ -183,6 +189,8 @@ class PLATFORM_EXPORT MainThreadTaskQueue
bool operator==(const QueueTraits& other) const { bool operator==(const QueueTraits& other) const {
return can_be_deferred == other.can_be_deferred && return can_be_deferred == other.can_be_deferred &&
can_be_throttled == other.can_be_throttled && can_be_throttled == other.can_be_throttled &&
can_be_intensively_throttled ==
other.can_be_intensively_throttled &&
can_be_paused == other.can_be_paused && can_be_paused == other.can_be_paused &&
can_be_frozen == other.can_be_frozen && can_be_frozen == other.can_be_frozen &&
can_run_in_background == other.can_run_in_background && can_run_in_background == other.can_run_in_background &&
...@@ -201,6 +209,7 @@ class PLATFORM_EXPORT MainThreadTaskQueue ...@@ -201,6 +209,7 @@ class PLATFORM_EXPORT MainThreadTaskQueue
int key = 1 << (offset++); int key = 1 << (offset++);
key |= can_be_deferred << (offset++); key |= can_be_deferred << (offset++);
key |= can_be_throttled << (offset++); key |= can_be_throttled << (offset++);
key |= can_be_intensively_throttled << (offset++);
key |= can_be_paused << (offset++); key |= can_be_paused << (offset++);
key |= can_be_frozen << (offset++); key |= can_be_frozen << (offset++);
key |= can_run_in_background << (offset++); key |= can_run_in_background << (offset++);
...@@ -213,6 +222,7 @@ class PLATFORM_EXPORT MainThreadTaskQueue ...@@ -213,6 +222,7 @@ class PLATFORM_EXPORT MainThreadTaskQueue
bool can_be_deferred : 1; bool can_be_deferred : 1;
bool can_be_throttled : 1; bool can_be_throttled : 1;
bool can_be_intensively_throttled : 1;
bool can_be_paused : 1; bool can_be_paused : 1;
bool can_be_frozen : 1; bool can_be_frozen : 1;
bool can_run_in_background : 1; bool can_run_in_background : 1;
...@@ -341,6 +351,10 @@ class PLATFORM_EXPORT MainThreadTaskQueue ...@@ -341,6 +351,10 @@ class PLATFORM_EXPORT MainThreadTaskQueue
bool CanBeThrottled() const { return queue_traits_.can_be_throttled; } bool CanBeThrottled() const { return queue_traits_.can_be_throttled; }
bool CanBeIntensivelyThrottled() const {
return queue_traits_.can_be_intensively_throttled;
}
bool CanBePaused() const { return queue_traits_.can_be_paused; } bool CanBePaused() const { return queue_traits_.can_be_paused; }
// Used for WebView's pauseTimers API. This API expects layout, parsing, and // Used for WebView's pauseTimers API. This API expects layout, parsing, and
......
...@@ -189,9 +189,6 @@ PageSchedulerImpl::PageSchedulerImpl( ...@@ -189,9 +189,6 @@ PageSchedulerImpl::PageSchedulerImpl(
keep_active_( keep_active_(
agent_group_scheduler.GetMainThreadScheduler().SchedulerKeepActive()), agent_group_scheduler.GetMainThreadScheduler().SchedulerKeepActive()),
had_recent_title_or_favicon_update_(false), had_recent_title_or_favicon_update_(false),
cpu_time_budget_pool_(nullptr),
same_origin_wake_up_budget_pool_(nullptr),
cross_origin_wake_up_budget_pool_(nullptr),
delegate_(delegate), delegate_(delegate),
delay_for_background_tab_freezing_(GetDelayForBackgroundTabFreezing()), delay_for_background_tab_freezing_(GetDelayForBackgroundTabFreezing()),
freeze_on_network_idle_enabled_(base::FeatureList::IsEnabled( freeze_on_network_idle_enabled_(base::FeatureList::IsEnabled(
...@@ -226,10 +223,12 @@ PageSchedulerImpl::~PageSchedulerImpl() { ...@@ -226,10 +223,12 @@ PageSchedulerImpl::~PageSchedulerImpl() {
if (cpu_time_budget_pool_) if (cpu_time_budget_pool_)
cpu_time_budget_pool_->Close(); cpu_time_budget_pool_->Close();
if (same_origin_wake_up_budget_pool_) if (HasWakeUpBudgetPools()) {
same_origin_wake_up_budget_pool_->Close(); for (WakeUpBudgetPool* pool : AllWakeUpBudgetPools()) {
if (cross_origin_wake_up_budget_pool_) DCHECK(pool);
cross_origin_wake_up_budget_pool_->Close(); pool->Close();
}
}
} }
// static // static
...@@ -633,26 +632,30 @@ void PageSchedulerImpl::AddQueueToWakeUpBudgetPool( ...@@ -633,26 +632,30 @@ void PageSchedulerImpl::AddQueueToWakeUpBudgetPool(
MainThreadTaskQueue* task_queue, MainThreadTaskQueue* task_queue,
FrameOriginType frame_origin_type, FrameOriginType frame_origin_type,
base::sequence_manager::LazyNow* lazy_now) { base::sequence_manager::LazyNow* lazy_now) {
GetWakeUpBudgetPool(frame_origin_type)->AddQueue(lazy_now->Now(), task_queue); GetWakeUpBudgetPool(task_queue, frame_origin_type)
->AddQueue(lazy_now->Now(), task_queue);
} }
void PageSchedulerImpl::RemoveQueueFromWakeUpBudgetPool( void PageSchedulerImpl::RemoveQueueFromWakeUpBudgetPool(
MainThreadTaskQueue* task_queue, MainThreadTaskQueue* task_queue,
FrameOriginType frame_origin_type, FrameOriginType frame_origin_type,
base::sequence_manager::LazyNow* lazy_now) { base::sequence_manager::LazyNow* lazy_now) {
GetWakeUpBudgetPool(frame_origin_type) GetWakeUpBudgetPool(task_queue, frame_origin_type)
->RemoveQueue(lazy_now->Now(), task_queue); ->RemoveQueue(lazy_now->Now(), task_queue);
} }
WakeUpBudgetPool* PageSchedulerImpl::GetWakeUpBudgetPool( WakeUpBudgetPool* PageSchedulerImpl::GetWakeUpBudgetPool(
MainThreadTaskQueue* task_queue,
FrameOriginType frame_origin_type) { FrameOriginType frame_origin_type) {
if (!task_queue->CanBeIntensivelyThrottled())
return normal_wake_up_budget_pool_;
switch (frame_origin_type) { switch (frame_origin_type) {
case FrameOriginType::kMainFrame: case FrameOriginType::kMainFrame:
case FrameOriginType::kSameOriginToMainFrame: case FrameOriginType::kSameOriginToMainFrame:
return same_origin_wake_up_budget_pool_; return same_origin_intensive_wake_up_budget_pool_;
break;
case FrameOriginType::kCrossOriginToMainFrame: case FrameOriginType::kCrossOriginToMainFrame:
return cross_origin_wake_up_budget_pool_; return cross_origin_intensive_wake_up_budget_pool_;
case FrameOriginType::kCount: case FrameOriginType::kCount:
NOTREACHED(); NOTREACHED();
return nullptr; return nullptr;
...@@ -695,29 +698,30 @@ void PageSchedulerImpl::MaybeInitializeBackgroundCPUTimeBudgetPool( ...@@ -695,29 +698,30 @@ void PageSchedulerImpl::MaybeInitializeBackgroundCPUTimeBudgetPool(
void PageSchedulerImpl::MaybeInitializeWakeUpBudgetPools( void PageSchedulerImpl::MaybeInitializeWakeUpBudgetPools(
base::sequence_manager::LazyNow* lazy_now) { base::sequence_manager::LazyNow* lazy_now) {
DCHECK_EQ(!!same_origin_wake_up_budget_pool_, if (HasWakeUpBudgetPools())
!!cross_origin_wake_up_budget_pool_);
if (same_origin_wake_up_budget_pool_)
return; return;
same_origin_wake_up_budget_pool_ = normal_wake_up_budget_pool_ =
main_thread_scheduler_->task_queue_throttler()->CreateWakeUpBudgetPool(
"Page - Normal Wake Up Throttling");
same_origin_intensive_wake_up_budget_pool_ =
main_thread_scheduler_->task_queue_throttler()->CreateWakeUpBudgetPool( main_thread_scheduler_->task_queue_throttler()->CreateWakeUpBudgetPool(
"Page Wake Up Throttling - Same-Origin as Main Frame"); "Page - Intensive Wake Up Throttling - Same-Origin as Main Frame");
cross_origin_wake_up_budget_pool_ = cross_origin_intensive_wake_up_budget_pool_ =
main_thread_scheduler_->task_queue_throttler()->CreateWakeUpBudgetPool( main_thread_scheduler_->task_queue_throttler()->CreateWakeUpBudgetPool(
"Page Wake Up Throttling - Cross-Origin to Main Frame"); "Page - Intensive Wake Up Throttling - Cross-Origin to Main Frame");
// The Wake Up Duration and Unaligned Wake Ups Allowance are constant and set // The Wake Up Duration and Unaligned Wake Ups Allowance are constant and set
// here. The Wake Up Interval is set in UpdateWakeUpBudgetPools(), based on // here. The Wake Up Interval is set in UpdateWakeUpBudgetPools(), based on
// current state. // current state.
same_origin_wake_up_budget_pool_->SetWakeUpDuration(kThrottledWakeUpDuration); for (WakeUpBudgetPool* pool : AllWakeUpBudgetPools())
pool->SetWakeUpDuration(kThrottledWakeUpDuration);
if (IsIntensiveWakeUpThrottlingEnabled()) { if (IsIntensiveWakeUpThrottlingEnabled()) {
same_origin_wake_up_budget_pool_->AllowUnalignedWakeUpIfNoRecentWakeUp(); same_origin_intensive_wake_up_budget_pool_
->AllowUnalignedWakeUpIfNoRecentWakeUp();
} }
cross_origin_wake_up_budget_pool_->SetWakeUpDuration(
kThrottledWakeUpDuration);
UpdateWakeUpBudgetPools(lazy_now); UpdateWakeUpBudgetPools(lazy_now);
} }
...@@ -805,7 +809,7 @@ void PageSchedulerImpl::UpdateCPUTimeBudgetPool( ...@@ -805,7 +809,7 @@ void PageSchedulerImpl::UpdateCPUTimeBudgetPool(
} }
void PageSchedulerImpl::OnTitleOrFaviconUpdated() { void PageSchedulerImpl::OnTitleOrFaviconUpdated() {
if (!same_origin_wake_up_budget_pool_) if (!HasWakeUpBudgetPools())
return; return;
if (are_wake_ups_intensively_throttled_ && if (are_wake_ups_intensively_throttled_ &&
...@@ -860,15 +864,12 @@ base::TimeDelta PageSchedulerImpl::GetIntensiveWakeUpThrottlingDuration( ...@@ -860,15 +864,12 @@ base::TimeDelta PageSchedulerImpl::GetIntensiveWakeUpThrottlingDuration(
void PageSchedulerImpl::UpdateWakeUpBudgetPools( void PageSchedulerImpl::UpdateWakeUpBudgetPools(
base::sequence_manager::LazyNow* lazy_now) { base::sequence_manager::LazyNow* lazy_now) {
DCHECK_EQ(!!same_origin_wake_up_budget_pool_, if (!same_origin_intensive_wake_up_budget_pool_)
!!cross_origin_wake_up_budget_pool_);
if (!same_origin_wake_up_budget_pool_)
return; return;
same_origin_wake_up_budget_pool_->SetWakeUpInterval( same_origin_intensive_wake_up_budget_pool_->SetWakeUpInterval(
lazy_now->Now(), GetIntensiveWakeUpThrottlingDuration(true)); lazy_now->Now(), GetIntensiveWakeUpThrottlingDuration(true));
cross_origin_wake_up_budget_pool_->SetWakeUpInterval( cross_origin_intensive_wake_up_budget_pool_->SetWakeUpInterval(
lazy_now->Now(), GetIntensiveWakeUpThrottlingDuration(false)); lazy_now->Now(), GetIntensiveWakeUpThrottlingDuration(false));
} }
...@@ -1055,6 +1056,23 @@ WebScopedVirtualTimePauser PageSchedulerImpl::CreateWebScopedVirtualTimePauser( ...@@ -1055,6 +1056,23 @@ WebScopedVirtualTimePauser PageSchedulerImpl::CreateWebScopedVirtualTimePauser(
return WebScopedVirtualTimePauser(main_thread_scheduler_, duration, name); return WebScopedVirtualTimePauser(main_thread_scheduler_, duration, name);
} }
bool PageSchedulerImpl::HasWakeUpBudgetPools() const {
// All WakeUpBudgetPools should be initialized together.
DCHECK_EQ(!!normal_wake_up_budget_pool_,
!!same_origin_intensive_wake_up_budget_pool_);
DCHECK_EQ(!!normal_wake_up_budget_pool_,
!!cross_origin_intensive_wake_up_budget_pool_);
return !!normal_wake_up_budget_pool_;
}
std::array<WakeUpBudgetPool*, PageSchedulerImpl::kNumWakeUpBudgetPools>
PageSchedulerImpl::AllWakeUpBudgetPools() {
return {normal_wake_up_budget_pool_,
same_origin_intensive_wake_up_budget_pool_,
cross_origin_intensive_wake_up_budget_pool_};
}
// static // static
const char PageSchedulerImpl::kHistogramPageLifecycleStateTransition[] = const char PageSchedulerImpl::kHistogramPageLifecycleStateTransition[] =
"PageScheduler.PageLifecycleStateTransition"; "PageScheduler.PageLifecycleStateTransition";
......
...@@ -236,8 +236,10 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler { ...@@ -236,8 +236,10 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
MainThreadTaskQueue* task_queue, MainThreadTaskQueue* task_queue,
FrameOriginType frame_origin_type, FrameOriginType frame_origin_type,
base::sequence_manager::LazyNow* lazy_now); base::sequence_manager::LazyNow* lazy_now);
// Returns the WakeUpBudgetPool to use for a frame with |frame_origin_type|. // Returns the WakeUpBudgetPool to use for |task_queue| which belongs to a
WakeUpBudgetPool* GetWakeUpBudgetPool(FrameOriginType frame_origin_type); // frame with |frame_origin_type|.
WakeUpBudgetPool* GetWakeUpBudgetPool(MainThreadTaskQueue* task_queue,
FrameOriginType frame_origin_type);
// Initializes WakeUpBudgetPools, if not already initialized. // Initializes WakeUpBudgetPools, if not already initialized.
void MaybeInitializeWakeUpBudgetPools( void MaybeInitializeWakeUpBudgetPools(
base::sequence_manager::LazyNow* lazy_now); base::sequence_manager::LazyNow* lazy_now);
...@@ -285,6 +287,13 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler { ...@@ -285,6 +287,13 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
// be freezable. // be freezable.
void DoFreezePage(); void DoFreezePage();
// Returns true if WakeUpBudgetPools were initialized.
bool HasWakeUpBudgetPools() const;
// Returns all WakeUpBudgetPools owned by this PageSchedulerImpl.
static constexpr int kNumWakeUpBudgetPools = 3;
std::array<WakeUpBudgetPool*, kNumWakeUpBudgetPools> AllWakeUpBudgetPools();
TraceableVariableController tracing_controller_; TraceableVariableController tracing_controller_;
HashSet<FrameSchedulerImpl*> frame_schedulers_; HashSet<FrameSchedulerImpl*> frame_schedulers_;
MainThreadSchedulerImpl* main_thread_scheduler_; MainThreadSchedulerImpl* main_thread_scheduler_;
...@@ -303,21 +312,31 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler { ...@@ -303,21 +312,31 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
bool are_wake_ups_intensively_throttled_; bool are_wake_ups_intensively_throttled_;
bool keep_active_; bool keep_active_;
bool had_recent_title_or_favicon_update_; bool had_recent_title_or_favicon_update_;
CPUTimeBudgetPool* cpu_time_budget_pool_; CPUTimeBudgetPool* cpu_time_budget_pool_ = nullptr;
// Throttles wake ups in throttleable TaskQueues of frames that have the same
// origin as the main frame. // Wake up budget pools for each throttling scenario:
// //
// This pool allows aligned wake ups and unaligned wake ups if there hasn't // Same-origin frame Cross-origin frame
// been a recent wake up. // Normal throttling only 1 1
WakeUpBudgetPool* same_origin_wake_up_budget_pool_; // Normal and intensive throttling 2 3
// Throttles wake ups in throttleable TaskQueues of frames that are
// cross-origin with the main frame.
// //
// This pool only allows aligned wake ups. Because wake ups do not depend on // 1: This pool allows 1-second aligned wake ups.
// recent wake ups like in |same_origin_wake_up_budget_pool_|, tasks cannot WakeUpBudgetPool* normal_wake_up_budget_pool_ = nullptr;
// easily learn about tasks running in other queues in the same pool. This is // 2: This pool allows 1-second aligned wake ups if the page is not
// important because this pool can have queues from different origins. // intensively throttled of if there hasn't been a wake up in the last
WakeUpBudgetPool* cross_origin_wake_up_budget_pool_; // minute. Otherwise, it allows 1-minute aligned wake ups.
WakeUpBudgetPool* same_origin_intensive_wake_up_budget_pool_ = nullptr;
// 3: This pool allows 1-second aligned wake ups if the page is not
// intensively throttled. Otherwise, it allows 1-minute aligned wake ups.
//
// Unlike |same_origin_intensive_wake_up_budget_pool_|, this pool does not
// allow a 1-second aligned wake up when there hasn't been a wake up in the
// last minute. This is to prevent frames from different origins from
// learning about each other. Concretely, this means that
// MaybeInitializeWakeUpBudgetPools() does not invoke
// AllowUnalignedWakeUpIfNoRecentWakeUp() on this pool.
WakeUpBudgetPool* cross_origin_intensive_wake_up_budget_pool_ = nullptr;
PageScheduler::Delegate* delegate_; PageScheduler::Delegate* delegate_;
CancelableClosureHolder do_throttle_cpu_time_callback_; CancelableClosureHolder do_throttle_cpu_time_callback_;
CancelableClosureHolder do_intensively_throttle_wake_ups_callback_; CancelableClosureHolder do_intensively_throttle_wake_ups_callback_;
......
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