Commit e238d2ee authored by Francois Doray's avatar Francois Doray Committed by Commit Bot

[blink scheduler] Create a separate WakeUpBudgetPool for cross-origin frames.

With this CL, a PageScheduler has 2 WakeUpBudgetPools:
- A WakeUpBudgetPool for frames that are same-origin
  with the main frame.
- A WakeUpBudgetPool for frames that are cross-origin
  to the main frame.
A FrameScheduler moves its throttleable TaskQueues to the appropriate
WakeUpBudgetPool when its "FrameOriginType" changes.

This CL does not affect behavior. However, in an upcoming CL, the
WakeUpBudgetPool for frames that are same-origin with the main frame
will allow unaligned wake ups if there hasn't been a wake up in the
last 60 seconds.

Bug: 1075553
Change-Id: Ic45306f7d20d2fc0f4a1d9618dc6eca449e946dd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2248320
Commit-Queue: François Doray <fdoray@chromium.org>
Reviewed-by: default avatarAlexander Timin <altimin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#780262}
parent 75355920
......@@ -8,6 +8,8 @@
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
#include "base/task/sequence_manager/lazy_now.h"
#include "base/time/time.h"
#include "base/trace_event/blame_context.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h"
......@@ -264,24 +266,20 @@ void FrameSchedulerImpl::RemoveThrottleableQueueFromBudgetPools(
CPUTimeBudgetPool* cpu_time_budget_pool =
parent_page_scheduler_->background_cpu_time_budget_pool();
WakeUpBudgetPool* wake_up_budget_pool =
parent_page_scheduler_->wake_up_budget_pool();
if (!cpu_time_budget_pool && !wake_up_budget_pool)
return;
// On tests, the scheduler helper might already be shut down and tick is not
// available.
base::TimeTicks now;
if (main_thread_scheduler_->tick_clock())
now = main_thread_scheduler_->tick_clock()->NowTicks();
else
now = base::TimeTicks::Now();
base::sequence_manager::LazyNow lazy_now =
main_thread_scheduler_->tick_clock()
? base::sequence_manager::LazyNow(
main_thread_scheduler_->tick_clock())
: base::sequence_manager::LazyNow(base::TimeTicks::Now());
if (cpu_time_budget_pool)
cpu_time_budget_pool->RemoveQueue(now, task_queue);
if (wake_up_budget_pool)
wake_up_budget_pool->RemoveQueue(now, task_queue);
cpu_time_budget_pool->RemoveQueue(lazy_now.Now(), task_queue);
parent_page_scheduler_->RemoveQueueFromWakeUpBudgetPool(
task_queue, frame_origin_type_, &lazy_now);
}
void FrameSchedulerImpl::SetFrameVisible(bool frame_visible) {
......@@ -303,11 +301,40 @@ void FrameSchedulerImpl::SetCrossOriginToMainFrame(bool cross_origin) {
DCHECK(!cross_origin);
return;
}
base::sequence_manager::LazyNow lazy_now(
main_thread_scheduler_->tick_clock());
// Remove throttleable TaskQueues from their current WakeUpBudgetPool.
//
// The WakeUpBudgetPool is selected based on origin. TaskQueues are reinserted
// in the appropriate WakeUpBudgetPool at the end of this method, after the
// |frame_origin_type_| is updated.
for (const auto& task_queue_and_voter :
frame_task_queue_controller_->GetAllTaskQueuesAndVoters()) {
if (task_queue_and_voter.first->CanBeThrottled()) {
parent_page_scheduler_->RemoveQueueFromWakeUpBudgetPool(
task_queue_and_voter.first, frame_origin_type_, &lazy_now);
}
}
// Update the FrameOriginType.
if (cross_origin) {
frame_origin_type_ = FrameOriginType::kCrossOriginToMainFrame;
} else {
frame_origin_type_ = FrameOriginType::kSameOriginToMainFrame;
}
// Add throttleable TaskQueues to WakeUpBudgetPool that corresponds to the
// updated |frame_origin_type_|.
for (const auto& task_queue_and_voter :
frame_task_queue_controller_->GetAllTaskQueuesAndVoters()) {
if (task_queue_and_voter.first->CanBeThrottled()) {
parent_page_scheduler_->AddQueueToWakeUpBudgetPool(
task_queue_and_voter.first, frame_origin_type_, &lazy_now);
}
}
UpdatePolicy();
}
......@@ -1112,19 +1139,17 @@ void FrameSchedulerImpl::OnTaskQueueCreated(
UpdateQueuePolicy(task_queue, voter);
if (task_queue->CanBeThrottled()) {
base::sequence_manager::LazyNow lazy_now(
main_thread_scheduler_->tick_clock());
CPUTimeBudgetPool* cpu_time_budget_pool =
parent_page_scheduler_->background_cpu_time_budget_pool();
if (cpu_time_budget_pool) {
cpu_time_budget_pool->AddQueue(
main_thread_scheduler_->tick_clock()->NowTicks(), task_queue);
cpu_time_budget_pool->AddQueue(lazy_now.Now(), task_queue);
}
WakeUpBudgetPool* wake_up_budget_pool =
parent_page_scheduler_->wake_up_budget_pool();
if (wake_up_budget_pool) {
wake_up_budget_pool->AddQueue(
main_thread_scheduler_->tick_clock()->NowTicks(), task_queue);
}
parent_page_scheduler_->AddQueueToWakeUpBudgetPool(
task_queue, frame_origin_type_, &lazy_now);
if (task_queues_throttled_) {
UpdateTaskQueueThrottling(task_queue, true);
......
......@@ -21,6 +21,7 @@
#include "third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/page_visibility_state.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/use_case.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
......@@ -165,7 +166,8 @@ PageSchedulerImpl::PageSchedulerImpl(
are_wake_ups_intensively_throttled_(false),
keep_active_(main_thread_scheduler->SchedulerKeepActive()),
cpu_time_budget_pool_(nullptr),
wake_up_budget_pool_(nullptr),
same_origin_wake_up_budget_pool_(nullptr),
cross_origin_wake_up_budget_pool_(nullptr),
delegate_(delegate),
delay_for_background_tab_freezing_(GetDelayForBackgroundTabFreezing()),
freeze_on_network_idle_enabled_(base::FeatureList::IsEnabled(
......@@ -197,8 +199,10 @@ PageSchedulerImpl::~PageSchedulerImpl() {
if (cpu_time_budget_pool_)
cpu_time_budget_pool_->Close();
if (wake_up_budget_pool_)
wake_up_budget_pool_->Close();
if (same_origin_wake_up_budget_pool_)
same_origin_wake_up_budget_pool_->Close();
if (cross_origin_wake_up_budget_pool_)
cross_origin_wake_up_budget_pool_->Close();
}
// static
......@@ -347,7 +351,7 @@ void PageSchedulerImpl::RegisterFrameSchedulerImpl(
base::sequence_manager::LazyNow lazy_now(
main_thread_scheduler_->tick_clock());
MaybeInitializeWakeUpBudgetPool(&lazy_now);
MaybeInitializeWakeUpBudgetPools(&lazy_now);
MaybeInitializeBackgroundCPUTimeBudgetPool(&lazy_now);
frame_schedulers_.insert(frame_scheduler);
......@@ -507,7 +511,7 @@ void PageSchedulerImpl::OnAggressiveThrottlingStatusUpdated() {
base::sequence_manager::LazyNow lazy_now(
main_thread_scheduler_->tick_clock());
UpdateCPUTimeBudgetPool(&lazy_now);
UpdateWakeUpBudgetPool(&lazy_now);
UpdateWakeUpBudgetPools(&lazy_now);
}
}
......@@ -555,6 +559,36 @@ void PageSchedulerImpl::AsValueInto(
state->EndDictionary();
}
void PageSchedulerImpl::AddQueueToWakeUpBudgetPool(
MainThreadTaskQueue* task_queue,
FrameOriginType frame_origin_type,
base::sequence_manager::LazyNow* lazy_now) {
GetWakeUpBudgetPool(frame_origin_type)->AddQueue(lazy_now->Now(), task_queue);
}
void PageSchedulerImpl::RemoveQueueFromWakeUpBudgetPool(
MainThreadTaskQueue* task_queue,
FrameOriginType frame_origin_type,
base::sequence_manager::LazyNow* lazy_now) {
GetWakeUpBudgetPool(frame_origin_type)
->RemoveQueue(lazy_now->Now(), task_queue);
}
WakeUpBudgetPool* PageSchedulerImpl::GetWakeUpBudgetPool(
FrameOriginType frame_origin_type) {
switch (frame_origin_type) {
case FrameOriginType::kMainFrame:
case FrameOriginType::kSameOriginToMainFrame:
return same_origin_wake_up_budget_pool_;
break;
case FrameOriginType::kCrossOriginToMainFrame:
return cross_origin_wake_up_budget_pool_;
case FrameOriginType::kCount:
NOTREACHED();
return nullptr;
}
}
CPUTimeBudgetPool* PageSchedulerImpl::background_cpu_time_budget_pool() {
return cpu_time_budget_pool_;
}
......@@ -589,24 +623,27 @@ void PageSchedulerImpl::MaybeInitializeBackgroundCPUTimeBudgetPool(
UpdateCPUTimeBudgetPool(lazy_now);
}
WakeUpBudgetPool* PageSchedulerImpl::wake_up_budget_pool() {
return wake_up_budget_pool_;
}
void PageSchedulerImpl::MaybeInitializeWakeUpBudgetPool(
void PageSchedulerImpl::MaybeInitializeWakeUpBudgetPools(
base::sequence_manager::LazyNow* lazy_now) {
if (wake_up_budget_pool_)
DCHECK_EQ(!!same_origin_wake_up_budget_pool_,
!!cross_origin_wake_up_budget_pool_);
if (same_origin_wake_up_budget_pool_)
return;
wake_up_budget_pool_ =
same_origin_wake_up_budget_pool_ =
main_thread_scheduler_->task_queue_throttler()->CreateWakeUpBudgetPool(
"Page Wake Up Throttling - Same-Origin as Main Frame");
cross_origin_wake_up_budget_pool_ =
main_thread_scheduler_->task_queue_throttler()->CreateWakeUpBudgetPool(
"Page Wake Up Throttling");
"Page Wake Up Throttling - Cross-Origin to Main Frame");
// The Wake Up Interval is set in UpdateWakeUpBudgetPool(), based on current
// The Wake Up Interval is set in UpdateWakeUpBudgetPools(), based on current
// state. The Wake Up Duration is constant and is set here.
wake_up_budget_pool_->SetWakeUpDuration(kThrottledWakeUpDuration);
same_origin_wake_up_budget_pool_->SetWakeUpDuration(kThrottledWakeUpDuration);
cross_origin_wake_up_budget_pool_->SetWakeUpDuration(
kThrottledWakeUpDuration);
UpdateWakeUpBudgetPool(lazy_now);
UpdateWakeUpBudgetPools(lazy_now);
}
void PageSchedulerImpl::OnThrottlingReported(
......@@ -641,14 +678,14 @@ void PageSchedulerImpl::UpdateBackgroundSchedulingLifecycleState(
are_wake_ups_intensively_throttled_ = false;
do_intensively_throttle_wake_ups_callback_.Cancel();
UpdateWakeUpBudgetPool(&lazy_now);
UpdateWakeUpBudgetPools(&lazy_now);
} else {
if (cpu_time_budget_pool_) {
main_thread_scheduler_->ControlTaskRunner()->PostDelayedTask(
FROM_HERE, do_throttle_cpu_time_callback_.GetCallback(),
kThrottlingDelayAfterBackgrounding);
}
if (wake_up_budget_pool_ && IsIntensiveWakeUpThrottlingEnabled()) {
if (IsIntensiveWakeUpThrottlingEnabled()) {
main_thread_scheduler_->ControlTaskRunner()->PostDelayedTask(
FROM_HERE, do_intensively_throttle_wake_ups_callback_.GetCallback(),
GetIntensiveWakeUpThrottlingGracePeriod());
......@@ -676,7 +713,7 @@ void PageSchedulerImpl::DoIntensivelyThrottleWakeUps() {
base::sequence_manager::LazyNow lazy_now(
main_thread_scheduler_->tick_clock());
UpdateWakeUpBudgetPool(&lazy_now);
UpdateWakeUpBudgetPools(&lazy_now);
NotifyFrames();
}
......@@ -692,18 +729,25 @@ void PageSchedulerImpl::UpdateCPUTimeBudgetPool(
}
}
void PageSchedulerImpl::UpdateWakeUpBudgetPool(
void PageSchedulerImpl::UpdateWakeUpBudgetPools(
base::sequence_manager::LazyNow* lazy_now) {
if (!wake_up_budget_pool_)
DCHECK_EQ(!!same_origin_wake_up_budget_pool_,
!!cross_origin_wake_up_budget_pool_);
if (!same_origin_wake_up_budget_pool_)
return;
if (are_wake_ups_intensively_throttled_ &&
!opted_out_from_aggressive_throttling_) {
wake_up_budget_pool_->SetWakeUpInterval(
same_origin_wake_up_budget_pool_->SetWakeUpInterval(
lazy_now->Now(), GetIntensiveWakeUpThrottlingDurationBetweenWakeUps());
cross_origin_wake_up_budget_pool_->SetWakeUpInterval(
lazy_now->Now(), GetIntensiveWakeUpThrottlingDurationBetweenWakeUps());
} else {
wake_up_budget_pool_->SetWakeUpInterval(lazy_now->Now(),
kDefaultThrottledWakeUpInterval);
same_origin_wake_up_budget_pool_->SetWakeUpInterval(
lazy_now->Now(), kDefaultThrottledWakeUpInterval);
cross_origin_wake_up_budget_pool_->SetWakeUpInterval(
lazy_now->Now(), kDefaultThrottledWakeUpInterval);
}
}
......
......@@ -16,6 +16,7 @@
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h"
#include "third_party/blink/renderer/platform/scheduler/common/tracing_helper.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/page_visibility_state.h"
#include "third_party/blink/renderer/platform/scheduler/public/page_lifecycle_state.h"
#include "third_party/blink/renderer/platform/scheduler/public/page_scheduler.h"
......@@ -42,6 +43,7 @@ class
class CPUTimeBudgetPool;
class FrameSchedulerImpl;
class MainThreadSchedulerImpl;
class MainThreadTaskQueue;
class WakeUpBudgetPool;
class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
......@@ -203,12 +205,26 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
// a part of foregrounding the page.
void SetPageFrozenImpl(bool frozen, NotificationPolicy notification_policy);
CPUTimeBudgetPool* background_cpu_time_budget_pool();
void MaybeInitializeBackgroundCPUTimeBudgetPool(
// Adds or removes a |task_queue| from the WakeUpBudgetPool associated with
// |frame_origin_type|. When the FrameOriginType of a FrameScheduler changes,
// it should remove all its TaskQueues from their current WakeUpBudgetPool and
// add them back to the WakeUpBudgetPool appropriate for the new
// FrameOriginType.
void AddQueueToWakeUpBudgetPool(MainThreadTaskQueue* task_queue,
FrameOriginType frame_origin_type,
base::sequence_manager::LazyNow* lazy_now);
void RemoveQueueFromWakeUpBudgetPool(
MainThreadTaskQueue* task_queue,
FrameOriginType frame_origin_type,
base::sequence_manager::LazyNow* lazy_now);
// Returns the WakeUpBudgetPool to use for a frame with |frame_origin_type|.
WakeUpBudgetPool* GetWakeUpBudgetPool(FrameOriginType frame_origin_type);
// Initializes WakeUpBudgetPools, if not already initialized.
void MaybeInitializeWakeUpBudgetPools(
base::sequence_manager::LazyNow* lazy_now);
WakeUpBudgetPool* wake_up_budget_pool();
void MaybeInitializeWakeUpBudgetPool(
CPUTimeBudgetPool* background_cpu_time_budget_pool();
void MaybeInitializeBackgroundCPUTimeBudgetPool(
base::sequence_manager::LazyNow* lazy_now);
void OnThrottlingReported(base::TimeDelta throttling_duration);
......@@ -218,9 +234,9 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
void UpdateBackgroundSchedulingLifecycleState(
NotificationPolicy notification_policy);
// Adjusts settings of a budget pool depending on current state of the page.
// Adjusts settings of budget pools depending on current state of the page.
void UpdateCPUTimeBudgetPool(base::sequence_manager::LazyNow* lazy_now);
void UpdateWakeUpBudgetPool(base::sequence_manager::LazyNow* lazy_now);
void UpdateWakeUpBudgetPools(base::sequence_manager::LazyNow* lazy_now);
// Callback for marking page is silent after a delay since last audible
// signal.
......@@ -265,7 +281,23 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
bool are_wake_ups_intensively_throttled_;
bool keep_active_;
CPUTimeBudgetPool* cpu_time_budget_pool_;
WakeUpBudgetPool* wake_up_budget_pool_;
// Throttles wake ups in throttleable TaskQueues of frames that have the same
// origin as the main frame.
//
// This pool allows aligned wake ups and unaligned wake ups if there hasn't
// been a recent wake up.
//
// TODO(https://crbug.com/1075553): Implement unaligned wake ups if there
// hasn't been a recent wake up.
WakeUpBudgetPool* same_origin_wake_up_budget_pool_;
// 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
// recent wake ups like in |same_origin_wake_up_budget_pool_|, tasks cannot
// easily learn about tasks running in other queues in the same pool. This is
// important because this pool can have queues from different origins.
WakeUpBudgetPool* cross_origin_wake_up_budget_pool_;
PageScheduler::Delegate* delegate_;
CancelableClosureHolder do_throttle_cpu_time_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