diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-10-26 13:57:00 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-11-02 11:31:01 +0000 |
commit | 1943b3c2a1dcee36c233724fc4ee7613d71b9cf6 (patch) | |
tree | 8c1b5f12357025c197da5427ae02cfdc2f3570d6 /chromium/third_party/blink/renderer/platform/scheduler | |
parent | 21ba0c5d4bf8fba15dddd97cd693bad2358b77fd (diff) | |
download | qtwebengine-chromium-1943b3c2a1dcee36c233724fc4ee7613d71b9cf6.tar.gz |
BASELINE: Update Chromium to 94.0.4606.111
Change-Id: I924781584def20fc800bedf6ff41fdb96c438193
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/scheduler')
124 files changed, 2777 insertions, 4631 deletions
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/BUILD.gn b/chromium/third_party/blink/renderer/platform/scheduler/BUILD.gn index 9b6541592a9..b659b98bec2 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/BUILD.gn +++ b/chromium/third_party/blink/renderer/platform/scheduler/BUILD.gn @@ -7,8 +7,6 @@ import("//third_party/blink/renderer/platform/platform.gni") import("//third_party/protobuf/proto_library.gni") blink_platform_sources("scheduler") { - configs += [ "//build/config/compiler:noshadowing" ] - sources = [ "common/cancelable_closure_holder.cc", "common/cancelable_closure_holder.h", @@ -43,13 +41,10 @@ blink_platform_sources("scheduler") { "common/thread_type.cc", "common/throttling/budget_pool.cc", "common/throttling/budget_pool.h", - "common/throttling/budget_pool_controller.h", "common/throttling/cpu_time_budget_pool.cc", "common/throttling/cpu_time_budget_pool.h", "common/throttling/task_queue_throttler.cc", "common/throttling/task_queue_throttler.h", - "common/throttling/throttled_time_domain.cc", - "common/throttling/throttled_time_domain.h", "common/throttling/wake_up_budget_pool.cc", "common/throttling/wake_up_budget_pool.h", "common/tracing_helper.cc", @@ -59,12 +54,11 @@ blink_platform_sources("scheduler") { "common/unprioritized_resource_loading_task_runner_handle.cc", "common/unprioritized_resource_loading_task_runner_handle.h", "common/web_resource_loading_task_runner_handle.cc", + "common/web_scheduling_priority.cc", "common/web_thread_scheduler.cc", "common/worker_pool.cc", "main_thread/agent_group_scheduler_impl.cc", "main_thread/agent_group_scheduler_impl.h", - "main_thread/agent_scheduling_strategy.cc", - "main_thread/agent_scheduling_strategy.h", "main_thread/attribution_group.h", "main_thread/auto_advancing_virtual_time_domain.cc", "main_thread/auto_advancing_virtual_time_domain.h", @@ -93,6 +87,8 @@ blink_platform_sources("scheduler") { "main_thread/main_thread_scheduler_impl.h", "main_thread/main_thread_task_queue.cc", "main_thread/main_thread_task_queue.h", + "main_thread/main_thread_web_scheduling_task_queue_impl.cc", + "main_thread/main_thread_web_scheduling_task_queue_impl.h", "main_thread/memory_purge_manager.cc", "main_thread/memory_purge_manager.h", "main_thread/non_waking_time_domain.cc", @@ -113,9 +109,6 @@ blink_platform_sources("scheduler") { "main_thread/user_model.cc", "main_thread/user_model.h", "main_thread/web_render_widget_scheduling_state.cc", - "main_thread/web_scheduling_priority.cc", - "main_thread/web_scheduling_task_queue_impl.cc", - "main_thread/web_scheduling_task_queue_impl.h", "main_thread/web_scoped_virtual_time_pauser.cc", "main_thread/widget_scheduler.cc", "main_thread/widget_scheduler.h", @@ -154,6 +147,8 @@ blink_platform_sources("scheduler") { "worker/non_main_thread_scheduler_impl.h", "worker/non_main_thread_task_queue.cc", "worker/non_main_thread_task_queue.h", + "worker/non_main_thread_web_scheduling_task_queue_impl.cc", + "worker/non_main_thread_web_scheduling_task_queue_impl.h", "worker/worker_metrics_helper.cc", "worker/worker_metrics_helper.h", "worker/worker_scheduler.cc", @@ -233,7 +228,6 @@ source_set("unit_tests") { "common/tracing_helper_unittest.cc", "common/ukm_task_sampler_unittest.cc", "common/worker_pool_unittest.cc", - "main_thread/agent_scheduling_strategy_unittest.cc", "main_thread/auto_advancing_virtual_time_domain_unittest.cc", "main_thread/deadline_task_runner_unittest.cc", "main_thread/frame_scheduler_impl_unittest.cc", diff --git a/chromium/third_party/blink/renderer/platform/scheduler/DEPS b/chromium/third_party/blink/renderer/platform/scheduler/DEPS index 61de10d0719..f3923c230ac 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/DEPS +++ b/chromium/third_party/blink/renderer/platform/scheduler/DEPS @@ -53,7 +53,6 @@ include_rules = [ "+components/scheduling_metrics", "+services/metrics", - "+third_party/abseil-cpp/absl/types/optional.h", "+third_party/blink/renderer/platform/back_forward_cache_utils.h", "+third_party/blink/renderer/platform/bindings/parkable_string_manager.h", "+third_party/blink/renderer/platform/instrumentation", diff --git a/chromium/third_party/blink/renderer/platform/scheduler/OWNERS b/chromium/third_party/blink/renderer/platform/scheduler/OWNERS index a3f384b76b0..9f21b467660 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/OWNERS +++ b/chromium/third_party/blink/renderer/platform/scheduler/OWNERS @@ -1,7 +1,6 @@ # LON scheduling team altimin@chromium.org carlscab@google.com -rmcilroy@chromium.org skyostil@chromium.org # MTV web scheduling API team @@ -9,3 +8,6 @@ shaseley@chromium.org # TOK scheduling team kouhei@chromium.org + +# MON Catan team +fdoray@chromium.org diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h b/chromium/third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h index fccee47080b..309052a02f9 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h @@ -6,7 +6,6 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_CANCELABLE_CLOSURE_HOLDER_H_ #include "base/cancelable_callback.h" -#include "base/macros.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" namespace blink { @@ -19,6 +18,8 @@ class CancelableClosureHolder { public: CancelableClosureHolder(); + CancelableClosureHolder(const CancelableClosureHolder&) = delete; + CancelableClosureHolder& operator=(const CancelableClosureHolder&) = delete; ~CancelableClosureHolder(); // Resets the closure to be wrapped by the cancelable callback. Cancels any @@ -35,8 +36,6 @@ class CancelableClosureHolder { private: base::RepeatingClosure callback_; base::CancelableRepeatingClosure cancelable_callback_; - - DISALLOW_COPY_AND_ASSIGN(CancelableClosureHolder); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/cooperative_scheduling_manager.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/cooperative_scheduling_manager.cc index f6a029de1f6..3586b8e341a 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/cooperative_scheduling_manager.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/cooperative_scheduling_manager.cc @@ -71,13 +71,8 @@ void CooperativeSchedulingManager::SafepointSlow() { return; // TODO(keishi): Also bail if V8 EnteredContextCount is more than 1 - // This task slice completes here. - Thread::MainThread()->Scheduler()->OnSafepointEntered(); RunNestedLoop(); - - // A new task slice starts here. - Thread::MainThread()->Scheduler()->OnSafepointExited(); } void CooperativeSchedulingManager::RunNestedLoop() { diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc index 67982ca4bd0..bcefbdf09ca 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc @@ -62,6 +62,7 @@ class DummyFrameScheduler : public FrameScheduler { void DidCommitProvisionalLoad(bool, FrameScheduler::NavigationType) override { } void OnFirstContentfulPaintInMainFrame() override {} + void OnDomContentLoaded() override {} void OnFirstMeaningfulPaint() override {} void OnLoad() override {} bool IsExemptFromBudgetBasedThrottling() const override { return false; } @@ -122,7 +123,6 @@ class DummyPageScheduler : public PageScheduler { void SetPageVisible(bool) override {} void SetPageFrozen(bool) override {} void SetPageBackForwardCached(bool) override {} - void OnFocusChanged(bool focused) override {} void SetKeepActive(bool) override {} bool IsMainFrameLocal() const override { return true; } void SetIsMainFrameLocal(bool) override {} @@ -131,7 +131,6 @@ class DummyPageScheduler : public PageScheduler { void DisableVirtualTimeForTesting() override {} bool VirtualTimeAllowedToAdvance() const override { return true; } void SetInitialVirtualTime(base::Time) override {} - void SetInitialVirtualTimeOffset(base::TimeDelta) override {} void SetVirtualTimePolicy(VirtualTimePolicy) override {} void GrantVirtualTimeBudget(base::TimeDelta, base::OnceClosure) override {} void SetMaxVirtualTimeTaskStarvationCount(int) override {} diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/features.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/features.cc index 3671d7a7d9b..dc69dfc189b 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/features.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/features.cc @@ -63,29 +63,7 @@ bool IsIntensiveWakeUpThrottlingEnabled() { // that admins get consistent behaviour that clients can't override. Otherwise // use the base::FeatureParams. -base::TimeDelta GetIntensiveWakeUpThrottlingDurationBetweenWakeUps() { - DCHECK(IsIntensiveWakeUpThrottlingEnabled()); - - // Controls the period during which at most 1 wake up from throttleable - // TaskQueues in a page can take place. - static const base::FeatureParam<int> - kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds{ - &features::kIntensiveWakeUpThrottling, - kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds_Name, - kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds_Default}; - - int seconds = - kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds_Default; - if (GetIntensiveWakeUpThrottlingPolicyOverride() == - PolicyOverride::NO_OVERRIDE) { - seconds = kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds.Get(); - } - return base::TimeDelta::FromSeconds(seconds); -} - base::TimeDelta GetIntensiveWakeUpThrottlingGracePeriod() { - DCHECK(IsIntensiveWakeUpThrottlingEnabled()); - // Controls the time that elapses after a page is backgrounded before the // throttling policy takes effect. static const base::FeatureParam<int> @@ -102,41 +80,34 @@ base::TimeDelta GetIntensiveWakeUpThrottlingGracePeriod() { return base::TimeDelta::FromSeconds(seconds); } -base::TimeDelta GetTimeToInhibitIntensiveThrottlingOnTitleOrFaviconUpdate() { - DCHECK(IsIntensiveWakeUpThrottlingEnabled()); +const base::Feature kThrottleForegroundTimers{ + "ThrottleForegroundTimers", base::FEATURE_DISABLED_BY_DEFAULT}; - constexpr int kDefaultSeconds = 3; - - static const base::FeatureParam<int> kFeatureParam{ - &features::kIntensiveWakeUpThrottling, - "inhibit_seconds_on_title_or_favicon_update_seconds", kDefaultSeconds}; - - int seconds = kDefaultSeconds; - if (GetIntensiveWakeUpThrottlingPolicyOverride() == - PolicyOverride::NO_OVERRIDE) { - seconds = kFeatureParam.Get(); - } - - 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; +base::TimeDelta GetForegroundTimersThrottledWakeUpInterval() { + constexpr int kForegroundTimersThrottling_WakeUpIntervalMillis_Default = 100; + static const base::FeatureParam<int> + kForegroundTimersThrottledWakeUpIntervalMills{ + &kThrottleForegroundTimers, + "ForegroundTimersThrottledWakeUpIntervalMills", + kForegroundTimersThrottling_WakeUpIntervalMillis_Default}; + return base::TimeDelta::FromMilliseconds( + kForegroundTimersThrottledWakeUpIntervalMills.Get()); } +const base::Feature kDeprioritizeDOMTimersDuringPageLoading{ + "DeprioritizeDOMTimersDuringPageLoading", + base::FEATURE_DISABLED_BY_DEFAULT}; + +const base::FeatureParam<DeprioritizeDOMTimersPhase>::Option + kDeprioritizeDOMTimersPhaseOptions[] = { + {DeprioritizeDOMTimersPhase::kOnDOMContentLoaded, "ondomcontentloaded"}, + {DeprioritizeDOMTimersPhase::kFirstContentfulPaint, "fcp"}, + {DeprioritizeDOMTimersPhase::kOnLoad, "onload"}}; + +const base::FeatureParam<DeprioritizeDOMTimersPhase> + kDeprioritizeDOMTimersPhase{&kDeprioritizeDOMTimersDuringPageLoading, + "phase", + DeprioritizeDOMTimersPhase::kOnDOMContentLoaded, + &kDeprioritizeDOMTimersPhaseOptions}; } // namespace scheduler } // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/features.h b/chromium/third_party/blink/renderer/platform/scheduler/common/features.h index 2fc871df670..25580f735fe 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/features.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/features.h @@ -54,26 +54,6 @@ const base::Feature kVeryHighPriorityForCompositingAfterDelay{ constexpr base::FeatureParam<int> kCompositingDelayLength{ &kVeryHighPriorityForCompositingAfterDelay, "CompositingDelayLength", 100}; -// If enabled, compositor priority will be set to kVeryHighPriority until -// a budget has been exhausted. Once the budget runs out, the priority will -// be set to kNormalPriority until there is enough budget to reprioritize. -const base::Feature kVeryHighPriorityForCompositingBudget{ - "BlinkSchedulerVeryHighPriorityForCompositingBudget", - base::FEATURE_DISABLED_BY_DEFAULT}; - -// Param for kVeryHighPriorityForCompositingBudget experiment. This param -// controls how much CPU time the compositor will be prioritized for, its -// budget. Measured in ms. -constexpr base::FeatureParam<int> kInitialCompositorBudgetInMilliseconds{ - &kVeryHighPriorityForCompositingBudget, - "InitialCompositorBudgetInMilliseconds", 250}; - -// Param for kVeryHighPriorityForCompositingBudget experiment. This param -// controls the rate at which the budget is recovered. -constexpr base::FeatureParam<double> kCompositorBudgetRecoveryRate{ - &kVeryHighPriorityForCompositingBudget, "CompositorBudgetRecoveryRate", - 0.25}; - // This feature functions as an experiment parameter for the // VeryHighPriorityForCompositing alternating, delay, and budget experiments. // When enabled, it does nothing unless one of these experiments is also @@ -182,11 +162,8 @@ const base::Feature kHighPriorityDatabaseTaskType{ "HighPriorityDatabaseTaskType", base::FEATURE_DISABLED_BY_DEFAULT}; // When features::kIntensiveWakeUpThrottling is enabled, wake ups from timers -// with a high nesting level are limited to 1 per -// GetIntensiveWakeUpThrottlingDurationBetweenWakeUp() in a page that has been -// backgrounded for GetIntensiveWakeUpThrottlingGracePeriod(). If -// CanIntensivelyThrottleLowNestingLevel() is true, this policy is also applied -// to timers with a non-zero delay and a low nesting level. +// with a high nesting level are limited to 1 per minute on a page that has been +// backgrounded for GetIntensiveWakeUpThrottlingGracePeriod(). // // Intensive wake up throttling is enforced in addition to other throttling // mechanisms: @@ -200,18 +177,7 @@ const base::Feature kHighPriorityDatabaseTaskType{ // the managed policy override of the feature. // // Parameter name and default values, exposed for testing. -constexpr int kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds_Default = - 60; -constexpr const char* - kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds_Name = - "duration_between_wake_ups_seconds"; 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. PLATFORM_EXPORT void @@ -219,87 +185,9 @@ ClearIntensiveWakeUpThrottlingPolicyOverrideCacheForTesting(); // Determines if the feature is enabled, taking into account base::Feature // settings and policy overrides. PLATFORM_EXPORT bool IsIntensiveWakeUpThrottlingEnabled(); -// Duration between wake ups for the kIntensiveWakeUpThrottling feature. -PLATFORM_EXPORT base::TimeDelta -GetIntensiveWakeUpThrottlingDurationBetweenWakeUps(); // Grace period after hiding a page during which there is no intensive wake up // throttling for the kIntensiveWakeUpThrottling feature. PLATFORM_EXPORT base::TimeDelta GetIntensiveWakeUpThrottlingGracePeriod(); -// The duration for which intensive throttling should be inhibited for -// same-origin frames when the page title or favicon is updated. 0 seconds means -// that updating the title or favicon has no effect on intensive throttling. -PLATFORM_EXPORT base::TimeDelta -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. -constexpr base::Feature kPerAgentSchedulingExperiments{ - "BlinkSchedulerPerAgentSchedulingExperiments", - base::FEATURE_DISABLED_BY_DEFAULT}; - -// Queues the per-agent scheduling experiment should affect. -enum class PerAgentAffectedQueues { - // Strategy only applies to non-main agent timer queues. These can be safely - // disabled/deprioritized without causing any known issues. - kTimerQueues, - // Strategy applies to all non-main agent queues. This may cause some task - // ordering issues. - kAllQueues, -}; - -constexpr base::FeatureParam<PerAgentAffectedQueues>::Option - kPerAgentQueuesOptions[] = { - {PerAgentAffectedQueues::kTimerQueues, "timer-queues"}, - {PerAgentAffectedQueues::kAllQueues, "all-queues"}}; - -constexpr base::FeatureParam<PerAgentAffectedQueues> kPerAgentQueues{ - &kPerAgentSchedulingExperiments, "queues", - PerAgentAffectedQueues::kTimerQueues, &kPerAgentQueuesOptions}; - -// Effect the per-agent scheduling strategy should have. -enum class PerAgentSlowDownMethod { - // Affected queues will be disabled. - kDisable, - // Affected queues will have their priority reduced to |kBestEffortPriority|. - kBestEffort, -}; - -constexpr base::FeatureParam<PerAgentSlowDownMethod>::Option - kPerAgentMethodOptions[] = { - {PerAgentSlowDownMethod::kDisable, "disable"}, - {PerAgentSlowDownMethod::kBestEffort, "best-effort"}}; - -constexpr base::FeatureParam<PerAgentSlowDownMethod> kPerAgentMethod{ - &kPerAgentSchedulingExperiments, "method", PerAgentSlowDownMethod::kDisable, - &kPerAgentMethodOptions}; - -// Delay to wait after the signal is reached, before "stopping" the strategy. -constexpr base::FeatureParam<int> kPerAgentDelayMs{ - &kPerAgentSchedulingExperiments, "delay_ms", 0}; - -// Signal the per-agent scheduling strategy should wait for. -enum class PerAgentSignal { - // Strategy will be active until all main frames reach First Meaningful Paint - // (+delay, if set). - kFirstMeaningfulPaint, - // Strategy will be active until all main frames finish loading (+delay, if - // set). - kOnLoad, - // Strategy will be active until the delay has passed since all main frames - // were created (or navigated). - kDelayOnly, -}; - -constexpr base::FeatureParam<PerAgentSignal>::Option kPerAgentSignalOptions[] = - {{PerAgentSignal::kFirstMeaningfulPaint, "fmp"}, - {PerAgentSignal::kOnLoad, "onload"}, - {PerAgentSignal::kDelayOnly, "delay"}}; - -constexpr base::FeatureParam<PerAgentSignal> kPerAgentSignal{ - &kPerAgentSchedulingExperiments, "signal", - PerAgentSignal::kFirstMeaningfulPaint, &kPerAgentSignalOptions}; // If enabled, base::ThreadTaskRunnerHandle::Get() and // base::SequencedTaskRunnerHandle::Get() returns the current active @@ -313,8 +201,37 @@ const base::Feature kMbiCompositorTaskRunnerPerAgentSchedulingGroup{ "MbiCompositorTaskRunnerPerAgentSchedulingGroup", base::FEATURE_DISABLED_BY_DEFAULT}; -const base::Feature kThrottleVisibleNotFocusedTimers{ - "ThrottleVisibleNotFocusedTimers", base::FEATURE_DISABLED_BY_DEFAULT}; +// If enabled, Javascript timers are throttled to 1 wake up per +// GetForegroundTimersThrottledWakeUpInterval() on foreground pages. +PLATFORM_EXPORT extern const base::Feature kThrottleForegroundTimers; +PLATFORM_EXPORT base::TimeDelta GetForegroundTimersThrottledWakeUpInterval(); + +// Deprioritizes JS timer tasks during a particular phase of page loading. +PLATFORM_EXPORT extern const base::Feature + kDeprioritizeDOMTimersDuringPageLoading; + +// The phase in which we deprioritize JS timer tasks. +enum class DeprioritizeDOMTimersPhase { + // Until the DOMContentLoaded event is fired. + kOnDOMContentLoaded, + // Until First Contentful Paint is reached. + kFirstContentfulPaint, + // Until the load event is fired. + kOnLoad, +}; + +PLATFORM_EXPORT extern const base::FeatureParam< + DeprioritizeDOMTimersPhase>::Option kDeprioritizeDOMTimersPhaseOptions[]; + +PLATFORM_EXPORT extern const base::FeatureParam<DeprioritizeDOMTimersPhase> + kDeprioritizeDOMTimersPhase; + +// Killswitch for prioritizing cross-process postMessage forwarding. +// +// TODO(crbug.com/1212894): Remove after M95. +const base::Feature kDisablePrioritizedPostMessageForwarding{ + "DisablePrioritizedPostMessageForwarding", + base::FEATURE_DISABLED_BY_DEFAULT}; } // namespace scheduler } // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc index cdb59dea0f4..66ca41194df 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc @@ -100,7 +100,7 @@ IdleHelper::IdlePeriodState IdleHelper::ComputeNewLongIdlePeriodState( if (long_idle_period_duration >= base::TimeDelta::FromMilliseconds(kMinimumIdlePeriodDurationMillis)) { *next_long_idle_period_delay_out = long_idle_period_duration; - if (!idle_queue_->HasTaskToRunImmediately()) + if (!idle_queue_->HasTaskToRunImmediatelyOrReadyDelayedTask()) return IdlePeriodState::kInLongIdlePeriodPaused; if (long_idle_period_duration == max_long_idle_period_duration) return IdlePeriodState::kInLongIdlePeriodWithMaxDeadline; @@ -248,7 +248,7 @@ void IdleHelper::UpdateLongIdlePeriodStateAfterIdleTask() { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "UpdateLongIdlePeriodStateAfterIdleTask"); - if (!idle_queue_->HasTaskToRunImmediately()) { + if (!idle_queue_->HasTaskToRunImmediatelyOrReadyDelayedTask()) { // If there are no more idle tasks then pause long idle period ticks until a // new idle task is posted. state_.UpdateState(IdlePeriodState::kInLongIdlePeriodPaused, diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.h index 51c7593d95e..678417abcd2 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.h @@ -5,7 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_IDLE_HELPER_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_IDLE_HELPER_H_ -#include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/task/task_observer.h" #include "third_party/blink/renderer/platform/platform_export.h" @@ -48,6 +47,8 @@ class PLATFORM_EXPORT IdleHelper : public base::TaskObserver, class PLATFORM_EXPORT Delegate { public: Delegate(); + Delegate(const Delegate&) = delete; + Delegate& operator=(const Delegate&) = delete; virtual ~Delegate(); // If it's ok to enter a long idle period, return true. Otherwise return @@ -69,9 +70,6 @@ class PLATFORM_EXPORT IdleHelper : public base::TaskObserver, // Signals that the task list has changed. virtual void OnPendingTasksChanged(bool has_tasks) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(Delegate); }; // Keep IdleHelper::IdlePeriodStateToString in sync with this enum. @@ -97,6 +95,8 @@ class PLATFORM_EXPORT IdleHelper : public base::TaskObserver, const char* idle_period_tracing_name, base::TimeDelta required_quiescence_duration_before_long_idle_period, scoped_refptr<base::sequence_manager::TaskQueue> idle_queue); + IdleHelper(const IdleHelper&) = delete; + IdleHelper& operator=(const IdleHelper&) = delete; ~IdleHelper() override; // Prevents any further idle tasks from running. @@ -166,6 +166,8 @@ class PLATFORM_EXPORT IdleHelper : public base::TaskObserver, State(SchedulerHelper* helper, Delegate* delegate, const char* idle_period_tracing_name); + State(const State&) = delete; + State& operator=(const State&) = delete; virtual ~State(); void UpdateState(IdlePeriodState new_state, @@ -196,8 +198,6 @@ class PLATFORM_EXPORT IdleHelper : public base::TaskObserver, bool running_idle_task_for_tracing_; const char* idle_period_tracing_name_; const char* last_sub_trace_event_name_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(State); }; // The minimum duration of an idle period. @@ -242,8 +242,6 @@ class PLATFORM_EXPORT IdleHelper : public base::TaskObserver, base::WeakPtr<IdleHelper> weak_idle_helper_ptr_; base::WeakPtrFactory<IdleHelper> weak_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(IdleHelper); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc index 2017943ad50..16821873f5e 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc @@ -8,7 +8,6 @@ #include "base/bind.h" #include "base/callback.h" -#include "base/macros.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/task/sequence_manager/sequence_manager.h" @@ -192,6 +191,8 @@ class BaseIdleHelperTest : public testing::Test { base::TimeDelta::FromMicroseconds(5000)); } + BaseIdleHelperTest(const BaseIdleHelperTest&) = delete; + BaseIdleHelperTest& operator=(const BaseIdleHelperTest&) = delete; ~BaseIdleHelperTest() override = default; void SetUp() override { @@ -269,18 +270,15 @@ class BaseIdleHelperTest : public testing::Test { scoped_refptr<base::sequence_manager::TaskQueue> default_task_queue_; scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_; scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_; - - DISALLOW_COPY_AND_ASSIGN(BaseIdleHelperTest); }; class IdleHelperTest : public BaseIdleHelperTest { public: IdleHelperTest() : BaseIdleHelperTest(base::TimeDelta()) {} + IdleHelperTest(const IdleHelperTest&) = delete; + IdleHelperTest& operator=(const IdleHelperTest&) = delete; ~IdleHelperTest() override = default; - - private: - DISALLOW_COPY_AND_ASSIGN(IdleHelperTest); }; TEST_F(IdleHelperTest, TestPostIdleTask) { @@ -387,6 +385,10 @@ class IdleHelperTestWithIdlePeriodObserver : public BaseIdleHelperTest { public: IdleHelperTestWithIdlePeriodObserver() : BaseIdleHelperTest(base::TimeDelta()) {} + IdleHelperTestWithIdlePeriodObserver( + const IdleHelperTestWithIdlePeriodObserver&) = delete; + IdleHelperTestWithIdlePeriodObserver& operator=( + const IdleHelperTestWithIdlePeriodObserver&) = delete; ~IdleHelperTestWithIdlePeriodObserver() override = default; @@ -403,9 +405,6 @@ class IdleHelperTestWithIdlePeriodObserver : public BaseIdleHelperTest { EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(cardinality); EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(cardinality); } - - private: - DISALLOW_COPY_AND_ASSIGN(IdleHelperTestWithIdlePeriodObserver); }; TEST_F(IdleHelperTestWithIdlePeriodObserver, TestEnterButNotExitIdlePeriod) { @@ -764,6 +763,10 @@ TEST_F(IdleHelperTest, CanExceedIdleDeadlineIfRequired) { class IdleHelperWithQuiescencePeriodTest : public BaseIdleHelperTest { public: + IdleHelperWithQuiescencePeriodTest( + const IdleHelperWithQuiescencePeriodTest&) = delete; + IdleHelperWithQuiescencePeriodTest& operator=( + const IdleHelperWithQuiescencePeriodTest&) = delete; enum { kQuiescenceDelayMs = 100, kLongIdlePeriodMs = 50, @@ -792,7 +795,6 @@ class IdleHelperWithQuiescencePeriodTest : public BaseIdleHelperTest { } private: - DISALLOW_COPY_AND_ASSIGN(IdleHelperWithQuiescencePeriodTest); }; class IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver @@ -801,16 +803,17 @@ class IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver() : IdleHelperWithQuiescencePeriodTest() {} + IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver( + const IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver&) = delete; + IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver& operator=( + const IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver&) = delete; + ~IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver() override = default; void SetUp() override { EXPECT_CALL(*idle_helper_, OnPendingTasksChanged(_)).Times(AnyNumber()); } - - private: - DISALLOW_COPY_AND_ASSIGN( - IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver); }; TEST_F(IdleHelperWithQuiescencePeriodTest, diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.cc index 6b936e32dba..5494aff5008 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.cc @@ -42,9 +42,6 @@ scheduling_metrics::ThreadType ConvertBlinkThreadType(ThreadType thread_type) { case ThreadType::kRealtimeAudioWorkletThread: case ThreadType::kSemiRealtimeAudioWorkletThread: return scheduling_metrics::ThreadType::kRendererOtherBlinkThread; - case ThreadType::kCount: - NOTREACHED(); - return scheduling_metrics::ThreadType::kCount; } } diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.h index 97f0bc31566..c6d89d0cde6 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.h @@ -9,7 +9,6 @@ #include "components/scheduling_metrics/task_duration_metric_reporter.h" #include "components/scheduling_metrics/thread_metrics.h" #include "components/scheduling_metrics/total_duration_metric_reporter.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_type.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" @@ -39,6 +38,8 @@ class PLATFORM_EXPORT MetricsHelper { public: MetricsHelper(ThreadType thread_type, bool has_cpu_timing_for_each_task); + MetricsHelper(const MetricsHelper&) = delete; + MetricsHelper& operator=(const MetricsHelper&) = delete; ~MetricsHelper(); protected: @@ -69,8 +70,6 @@ class PLATFORM_EXPORT MetricsHelper { background_thread_task_duration_reporter_; scheduling_metrics::TaskDurationMetricReporter<ThreadType> background_thread_task_cpu_duration_reporter_; - - DISALLOW_COPY_AND_ASSIGN(MetricsHelper); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h b/chromium/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h index 1fdd4a2eefb..06d0e59e76d 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h @@ -6,7 +6,6 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_POLLABLE_THREAD_SAFE_FLAG_H_ #include "base/atomicops.h" -#include "base/macros.h" #include "base/synchronization/lock.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" @@ -21,6 +20,8 @@ class PollableThreadSafeFlag { public: explicit PollableThreadSafeFlag(base::Lock* write_lock); + PollableThreadSafeFlag(const PollableThreadSafeFlag&) = delete; + PollableThreadSafeFlag& operator=(const PollableThreadSafeFlag&) = delete; // Set the flag. May only be called if |write_lock| is held. void SetWhileLocked(bool value); @@ -31,8 +32,6 @@ class PollableThreadSafeFlag { private: base::subtle::Atomic32 flag_; base::Lock* write_lock_; // Not owned. - - DISALLOW_COPY_AND_ASSIGN(PollableThreadSafeFlag); }; #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_POLLABLE_THREAD_SAFE_FLAG_H_ diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/post_cancellable_task.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/post_cancellable_task.cc index dd7838db9da..bb6a96550a5 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/post_cancellable_task.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/post_cancellable_task.cc @@ -13,6 +13,8 @@ namespace blink { class TaskHandle::Runner : public WTF::ThreadSafeRefCounted<Runner> { public: explicit Runner(base::OnceClosure task) : task_(std::move(task)) {} + Runner(const Runner&) = delete; + Runner& operator=(const Runner&) = delete; base::WeakPtr<Runner> AsWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); } @@ -50,8 +52,6 @@ class TaskHandle::Runner : public WTF::ThreadSafeRefCounted<Runner> { private: base::OnceClosure task_; base::WeakPtrFactory<Runner> weak_ptr_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(Runner); }; } // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h index a020067758a..68acd4521dd 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h @@ -8,7 +8,6 @@ #include <stddef.h> #include "base/logging.h" -#include "base/macros.h" #include "base/task/sequence_manager/sequence_manager.h" #include "base/task/simple_task_executor.h" #include "base/threading/thread_checker.h" @@ -33,6 +32,8 @@ class PLATFORM_EXPORT SchedulerHelper // object is destroyed. explicit SchedulerHelper( base::sequence_manager::SequenceManager* sequence_manager); + SchedulerHelper(const SchedulerHelper&) = delete; + SchedulerHelper& operator=(const SchedulerHelper&) = delete; ~SchedulerHelper() override; // Must be invoked before running any task from the scheduler, on the thread @@ -142,8 +143,6 @@ class PLATFORM_EXPORT SchedulerHelper UkmTaskSampler ukm_task_sampler_; absl::optional<base::SimpleTaskExecutor> simple_task_executor_; - - DISALLOW_COPY_AND_ASSIGN(SchedulerHelper); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc index bb6c5f7f8cd..ece7c549d2e 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc @@ -6,7 +6,6 @@ #include "base/bind.h" #include "base/callback.h" -#include "base/macros.h" #include "base/single_thread_task_runner.h" #include "base/task/sequence_manager/lazy_now.h" #include "base/task/sequence_manager/task_queue.h" @@ -63,6 +62,8 @@ class SchedulerHelperTest : public testing::Test { default_task_runner_ = scheduler_helper_->DefaultTaskRunner(); } + SchedulerHelperTest(const SchedulerHelperTest&) = delete; + SchedulerHelperTest& operator=(const SchedulerHelperTest&) = delete; ~SchedulerHelperTest() override = default; void TearDown() override { @@ -87,8 +88,6 @@ class SchedulerHelperTest : public testing::Test { sequence_manager_; std::unique_ptr<NonMainThreadSchedulerHelper> scheduler_helper_; scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_; - - DISALLOW_COPY_AND_ASSIGN(SchedulerHelperTest); }; TEST_F(SchedulerHelperTest, TestPostDefaultTask) { diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc index c17e32eca01..6b7c95cfd32 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc @@ -41,7 +41,6 @@ bool SchedulingPolicy::IsFeatureSticky(SchedulingPolicy::Feature feature) { case Feature::kResumeEventListener: case Feature::kContainsPlugins: case Feature::kDocumentLoaded: - case Feature::kRequestedGeolocationPermission: case Feature::kRequestedNotificationsPermission: case Feature::kRequestedMIDIPermission: case Feature::kRequestedAudioCapturePermission: diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h index 6b806262b25..519c26d3bd4 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h @@ -7,7 +7,6 @@ #include <memory> -#include "base/macros.h" #include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" @@ -27,6 +26,8 @@ namespace scheduler { class SimpleThreadScheduler : public ThreadScheduler { public: SimpleThreadScheduler(); + SimpleThreadScheduler(const SimpleThreadScheduler&) = delete; + SimpleThreadScheduler& operator=(const SimpleThreadScheduler&) = delete; ~SimpleThreadScheduler() override; // Do nothing. @@ -80,9 +81,6 @@ class SimpleThreadScheduler : public ThreadScheduler { NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() override; void SetV8Isolate(v8::Isolate* isolate) override {} - - private: - DISALLOW_COPY_AND_ASSIGN(SimpleThreadScheduler); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/single_thread_idle_task_runner.h b/chromium/third_party/blink/renderer/platform/scheduler/common/single_thread_idle_task_runner.h index c6e83f09478..72eb4bbf479 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/single_thread_idle_task_runner.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/single_thread_idle_task_runner.h @@ -10,7 +10,6 @@ #include "base/bind.h" #include "base/callback.h" -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" @@ -47,6 +46,8 @@ class SingleThreadIdleTaskRunner class PLATFORM_EXPORT Delegate { public: Delegate(); + Delegate(const Delegate&) = delete; + Delegate& operator=(const Delegate&) = delete; virtual ~Delegate(); // Signals that an idle task has been posted. This will be called on the @@ -63,9 +64,6 @@ class SingleThreadIdleTaskRunner // Returns the current time. virtual base::TimeTicks NowTicks() = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(Delegate); }; // NOTE Category strings must have application lifetime (statics or @@ -73,6 +71,9 @@ class SingleThreadIdleTaskRunner SingleThreadIdleTaskRunner( scoped_refptr<base::SingleThreadTaskRunner> idle_priority_task_runner, Delegate* delegate); + SingleThreadIdleTaskRunner(const SingleThreadIdleTaskRunner&) = delete; + SingleThreadIdleTaskRunner& operator=(const SingleThreadIdleTaskRunner&) = + delete; virtual void PostIdleTask(const base::Location& from_here, IdleTask idle_task); @@ -110,7 +111,6 @@ class SingleThreadIdleTaskRunner base::trace_event::BlameContext* blame_context_; // Not owned. base::WeakPtr<SingleThreadIdleTaskRunner> weak_scheduler_ptr_; base::WeakPtrFactory<SingleThreadIdleTaskRunner> weak_factory_{this}; - DISALLOW_COPY_AND_ASSIGN(SingleThreadIdleTaskRunner); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/thread_cpu_throttler.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/thread_cpu_throttler.cc index 4be57405fb4..d09e0877911 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/thread_cpu_throttler.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/thread_cpu_throttler.cc @@ -8,7 +8,6 @@ #include "base/atomicops.h" #include "base/logging.h" -#include "base/macros.h" #include "base/memory/singleton.h" #include "base/synchronization/atomic_flag.h" #include "base/threading/platform_thread.h" @@ -32,6 +31,8 @@ class ThreadCPUThrottler::ThrottlingThread final : public base::PlatformThread::Delegate { public: explicit ThrottlingThread(double rate); + ThrottlingThread(const ThrottlingThread&) = delete; + ThrottlingThread& operator=(const ThrottlingThread&) = delete; ~ThrottlingThread() override; void SetThrottlingRate(double rate); @@ -61,8 +62,6 @@ class ThreadCPUThrottler::ThrottlingThread final base::PlatformThreadHandle throttled_thread_handle_; base::PlatformThreadHandle throttling_thread_handle_; base::AtomicFlag cancellation_flag_; - - DISALLOW_COPY_AND_ASSIGN(ThrottlingThread); }; #ifdef USE_SIGNALS diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/thread_load_tracker.h b/chromium/third_party/blink/renderer/platform/scheduler/common/thread_load_tracker.h index 6bf13f31146..d68d4eb7d92 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/thread_load_tracker.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/thread_load_tracker.h @@ -6,7 +6,6 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THREAD_LOAD_TRACKER_H_ #include "base/callback.h" -#include "base/macros.h" #include "base/time/time.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h index f6fa54a39e9..5bc618b69b3 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h @@ -7,8 +7,6 @@ #include "third_party/blink/renderer/platform/platform_export.h" -#include <random> - #include "base/single_thread_task_runner.h" #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" #include "third_party/blink/renderer/platform/scheduler/common/single_thread_idle_task_runner.h" diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/thread_type.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/thread_type.cc index cd1298b02eb..95cb2e01531 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/thread_type.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/thread_type.cc @@ -47,9 +47,6 @@ const char* GetNameForThreadType(ThreadType thread_type) { return "Realtime AudioWorklet thread"; case ThreadType::kSemiRealtimeAudioWorkletThread: return "Semi-Realtime AudioWorklet thread"; - case ThreadType::kCount: - NOTREACHED(); - return nullptr; } return nullptr; } diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.cc index 9c6a39003da..5c32a8d8fb4 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.cc @@ -7,7 +7,6 @@ #include <cstdint> #include "third_party/abseil-cpp/absl/types/optional.h" -#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_controller.h" #include "third_party/blink/renderer/platform/scheduler/common/tracing_helper.h" namespace blink { @@ -15,43 +14,42 @@ namespace scheduler { using base::sequence_manager::TaskQueue; -BudgetPool::BudgetPool(const char* name, - BudgetPoolController* budget_pool_controller) - : name_(name), - budget_pool_controller_(budget_pool_controller), - is_enabled_(true) {} +BudgetPool::BudgetPool(const char* name) : name_(name), is_enabled_(true) {} -BudgetPool::~BudgetPool() = default; +BudgetPool::~BudgetPool() { + for (auto* throttler : associated_throttlers_) { + throttler->RemoveBudgetPool(this); + } +} const char* BudgetPool::Name() const { return name_; } -void BudgetPool::AddQueue(base::TimeTicks now, TaskQueue* queue) { - budget_pool_controller_->AddQueueToBudgetPool(queue, this); - associated_task_queues_.insert(queue); +void BudgetPool::AddThrottler(base::TimeTicks now, + TaskQueueThrottler* throttler) { + throttler->AddBudgetPool(this); + associated_throttlers_.insert(throttler); if (!is_enabled_) return; - budget_pool_controller_->UpdateQueueSchedulingLifecycleState(now, queue); + + throttler->UpdateQueueState(now); } -void BudgetPool::UnregisterQueue(TaskQueue* queue) { - DissociateQueue(queue); +void BudgetPool::UnregisterThrottler(TaskQueueThrottler* throttler) { + associated_throttlers_.erase(throttler); } -void BudgetPool::RemoveQueue(base::TimeTicks now, TaskQueue* queue) { - DissociateQueue(queue); +void BudgetPool::RemoveThrottler(base::TimeTicks now, + TaskQueueThrottler* throttler) { + throttler->RemoveBudgetPool(this); + associated_throttlers_.erase(throttler); if (!is_enabled_) return; - budget_pool_controller_->UpdateQueueSchedulingLifecycleState(now, queue); -} - -void BudgetPool::DissociateQueue(TaskQueue* queue) { - budget_pool_controller_->RemoveQueueFromBudgetPool(queue, this); - associated_task_queues_.erase(queue); + throttler->UpdateQueueState(now); } void BudgetPool::EnableThrottling(base::sequence_manager::LazyNow* lazy_now) { @@ -61,7 +59,7 @@ void BudgetPool::EnableThrottling(base::sequence_manager::LazyNow* lazy_now) { TRACE_EVENT0("renderer.scheduler", "BudgetPool_EnableThrottling"); - UpdateThrottlingStateForAllQueues(lazy_now->Now()); + UpdateStateForAllThrottlers(lazy_now->Now()); } void BudgetPool::DisableThrottling(base::sequence_manager::LazyNow* lazy_now) { @@ -71,10 +69,7 @@ void BudgetPool::DisableThrottling(base::sequence_manager::LazyNow* lazy_now) { TRACE_EVENT0("renderer.scheduler", "BudgetPool_DisableThrottling"); - for (TaskQueue* queue : associated_task_queues_) { - budget_pool_controller_->UpdateQueueSchedulingLifecycleState( - lazy_now->Now(), queue); - } + UpdateStateForAllThrottlers(lazy_now->Now()); // TODO(altimin): We need to disable TimeBudgetQueues here or they will // regenerate extra time budget when they are disabled. @@ -85,14 +80,12 @@ bool BudgetPool::IsThrottlingEnabled() const { } void BudgetPool::Close() { - DCHECK_EQ(0u, associated_task_queues_.size()); - - budget_pool_controller_->UnregisterBudgetPool(this); + DCHECK_EQ(0u, associated_throttlers_.size()); } -void BudgetPool::UpdateThrottlingStateForAllQueues(base::TimeTicks now) { - for (TaskQueue* queue : associated_task_queues_) - budget_pool_controller_->UpdateQueueSchedulingLifecycleState(now, queue); +void BudgetPool::UpdateStateForAllThrottlers(base::TimeTicks now) { + for (TaskQueueThrottler* throttler : associated_throttlers_) + throttler->UpdateQueueState(now); } } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h index 5ed038f7a76..2a4ce8ace1f 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h @@ -6,20 +6,15 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THROTTLING_BUDGET_POOL_H_ #include "base/callback.h" -#include "base/macros.h" #include "base/task/sequence_manager/lazy_now.h" -#include "base/task/sequence_manager/task_queue.h" #include "base/time/time.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #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/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/hash_set.h" #include "third_party/perfetto/include/perfetto/tracing/traced_value_forward.h" namespace base { -namespace sequence_manager { -class TaskQueue; -} namespace trace_event { class TracedValue; } @@ -28,7 +23,6 @@ class TracedValue; namespace blink { namespace scheduler { -class BudgetPoolController; enum class QueueBlockType; // BudgetPool represents a group of task queues which share a limit @@ -43,28 +37,21 @@ class PLATFORM_EXPORT BudgetPool { const char* Name() const; // Report task run time to the budget pool. - virtual void RecordTaskRunTime(base::sequence_manager::TaskQueue* queue, - base::TimeTicks start_time, + virtual void RecordTaskRunTime(base::TimeTicks start_time, base::TimeTicks end_time) = 0; - // Returns the earliest time when the next pump can be scheduled to run + // Returns the earliest time when the next wake-up can be scheduled to run // new tasks. virtual base::TimeTicks GetNextAllowedRunTime( base::TimeTicks desired_run_time) const = 0; // Returns true if a task can run at the given time. - virtual bool CanRunTasksAt(base::TimeTicks moment, bool is_wake_up) const = 0; + virtual bool CanRunTasksAt(base::TimeTicks moment) const = 0; // Returns a point in time until which tasks are allowed to run. // base::TimeTicks::Max() means that there are no known limits. - virtual base::TimeTicks GetTimeTasksCanRunUntil(base::TimeTicks now, - bool is_wake_up) const = 0; - - // Notifies budget pool that queue has work with desired run time. - virtual void OnQueueNextWakeUpChanged( - base::sequence_manager::TaskQueue* queue, - base::TimeTicks now, - base::TimeTicks desired_run_time) = 0; + virtual base::TimeTicks GetTimeTasksCanRunUntil( + base::TimeTicks now) const = 0; // Invoked as part of a global wake up if any of the task queues associated // with the budget pool has reached its next allowed run time. The next @@ -79,27 +66,24 @@ class PLATFORM_EXPORT BudgetPool { virtual void WriteIntoTrace(perfetto::TracedValue context, base::TimeTicks now) const = 0; - // Adds |queue| to given pool. If the pool restriction does not allow - // a task to be run immediately and |queue| is throttled, |queue| becomes - // disabled. - void AddQueue(base::TimeTicks now, base::sequence_manager::TaskQueue* queue); + // Adds |throttler| to given pool and invokes + // TaskQueueThrottler::UpdateQueueState(). + void AddThrottler(base::TimeTicks now, TaskQueueThrottler* throttler); - // Removes |queue| from given pool. If it is throttled, it does not - // become enabled immediately, but a wake-up is scheduled if needed. - void RemoveQueue(base::TimeTicks now, - base::sequence_manager::TaskQueue* queue); + // Removes |throttler| from given pool and invokes + // TaskQueueThrottler::UpdateQueueState(). + void RemoveThrottler(base::TimeTicks now, TaskQueueThrottler* throttler); - // Unlike RemoveQueue, does not schedule a new wake-up for the queue. - void UnregisterQueue(base::sequence_manager::TaskQueue* queue); + // Unlike RemoveThrottler, does not update the queue's state. + void UnregisterThrottler(TaskQueueThrottler* throttler); - // Enables this time budget pool. Queues from this pool will be - // throttled based on their run time. + // Enables this budget pool, allowing it to enforce its policies on its + // queues. void EnableThrottling(base::sequence_manager::LazyNow* now); - // Disables with time budget pool. Queues from this pool will not be - // throttled based on their run time. A call to |PumpThrottledTasks| - // will be scheduled to enable this queues back again and respect - // timer alignment. Internal budget level will not regenerate with time. + // Disables this budget pool, stopping it from enforcing its policies on its + // queues. UpdateQueueState() is invoked on all queues to update their wake up + // times and fences. void DisableThrottling(base::sequence_manager::LazyNow* now); bool IsThrottlingEnabled() const; @@ -107,23 +91,18 @@ class PLATFORM_EXPORT BudgetPool { // All queues should be removed before calling Close(). void Close(); - // Ensures that a pump is scheduled and that a fence is installed for all + // Ensures that a wake-up is scheduled and that a fence is installed for all // queues in this pool, based on state of those queues and latest values from // CanRunTasksAt/GetTimeTasksCanRunUntil/GetNextAllowedRunTime. - void UpdateThrottlingStateForAllQueues(base::TimeTicks now); + void UpdateStateForAllThrottlers(base::TimeTicks now); protected: - BudgetPool(const char* name, BudgetPoolController* budget_pool_controller); + explicit BudgetPool(const char* name); const char* name_; // NOT OWNED - BudgetPoolController* budget_pool_controller_; - - HashSet<base::sequence_manager::TaskQueue*> associated_task_queues_; + HashSet<TaskQueueThrottler*> associated_throttlers_; bool is_enabled_; - - private: - void DissociateQueue(base::sequence_manager::TaskQueue* queue); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_controller.h b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_controller.h deleted file mode 100644 index 4115e97e5f3..00000000000 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_controller.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2019 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THROTTLING_BUDGET_POOL_CONTROLLER_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THROTTLING_BUDGET_POOL_CONTROLLER_H_ - -#include "base/time/time.h" - -namespace blink { -namespace scheduler { - -class BudgetPool; - -// Interface for BudgetPool to interact with TaskQueueThrottler. -class PLATFORM_EXPORT BudgetPoolController { - public: - virtual ~BudgetPoolController() = default; - - // To be used by BudgetPool only, use BudgetPool::{Add,Remove}Queue - // methods instead. - virtual void AddQueueToBudgetPool(base::sequence_manager::TaskQueue* queue, - BudgetPool* budget_pool) = 0; - virtual void RemoveQueueFromBudgetPool( - base::sequence_manager::TaskQueue* queue, - BudgetPool* budget_pool) = 0; - - // Deletes the budget pool. - virtual void UnregisterBudgetPool(BudgetPool* budget_pool) = 0; - - // Ensure that an appropriate type of the fence is installed and schedule - // a pump for this queue when needed. - virtual void UpdateQueueSchedulingLifecycleState( - base::TimeTicks now, - base::sequence_manager::TaskQueue* queue) = 0; - - // Returns true if the |queue| is throttled (i.e. added to TaskQueueThrottler - // and throttling is not disabled). - virtual bool IsThrottled(base::sequence_manager::TaskQueue* queue) const = 0; -}; - -} // namespace scheduler -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THROTTLING_BUDGET_POOL_CONTROLLER_H_" diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_unittest.cc index 8bbefcec551..876f309944e 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_unittest.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_unittest.cc @@ -9,7 +9,6 @@ #include <memory> #include "base/callback.h" -#include "base/macros.h" #include "base/task/sequence_manager/test/sequence_manager_for_test.h" #include "base/test/null_task_runner.h" #include "base/test/simple_test_tick_clock.h" @@ -26,24 +25,16 @@ namespace scheduler { class BudgetPoolTest : public testing::Test { public: BudgetPoolTest() = default; + BudgetPoolTest(const BudgetPoolTest&) = delete; + BudgetPoolTest& operator=(const BudgetPoolTest&) = delete; ~BudgetPoolTest() override = default; void SetUp() override { clock_.Advance(base::TimeDelta::FromMicroseconds(5000)); null_task_runner_ = base::MakeRefCounted<base::NullTaskRunner>(); - scheduler_ = std::make_unique<MainThreadSchedulerImpl>( - base::sequence_manager::SequenceManagerForTest::Create( - nullptr, null_task_runner_, &clock_), - absl::nullopt); - task_queue_throttler_ = scheduler_->task_queue_throttler(); start_time_ = clock_.NowTicks(); } - void TearDown() override { - scheduler_->Shutdown(); - scheduler_.reset(); - } - base::TimeTicks MillisecondsAfterStart(int milliseconds) { return start_time_ + base::TimeDelta::FromMilliseconds(milliseconds); } @@ -55,99 +46,58 @@ class BudgetPoolTest : public testing::Test { protected: base::SimpleTestTickClock clock_; scoped_refptr<base::NullTaskRunner> null_task_runner_; - std::unique_ptr<MainThreadSchedulerImpl> scheduler_; - TaskQueueThrottler* task_queue_throttler_; // NOT OWNED + TraceableVariableController tracing_controller_; base::TimeTicks start_time_; - - DISALLOW_COPY_AND_ASSIGN(BudgetPoolTest); }; TEST_F(BudgetPoolTest, CPUTimeBudgetPool) { - CPUTimeBudgetPool* pool = - task_queue_throttler_->CreateCPUTimeBudgetPool("test"); + std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>( + "test", &tracing_controller_, start_time_); pool->SetTimeBudgetRecoveryRate(SecondsAfterStart(0), 0.1); - EXPECT_TRUE(pool->CanRunTasksAt(SecondsAfterStart(0), false)); + EXPECT_TRUE(pool->CanRunTasksAt(SecondsAfterStart(0))); EXPECT_EQ(SecondsAfterStart(0), pool->GetNextAllowedRunTime(SecondsAfterStart(0))); // Run an expensive task and make sure that we're throttled. - pool->RecordTaskRunTime(nullptr, SecondsAfterStart(0), - MillisecondsAfterStart(100)); + pool->RecordTaskRunTime(SecondsAfterStart(0), MillisecondsAfterStart(100)); - EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(500), false)); + EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(500))); EXPECT_EQ(MillisecondsAfterStart(1000), pool->GetNextAllowedRunTime(SecondsAfterStart(0))); - EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(1000), false)); + EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(1000))); // Run a cheap task and make sure that it doesn't affect anything. - EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(2000), false)); - pool->RecordTaskRunTime(nullptr, MillisecondsAfterStart(2000), + EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(2000))); + pool->RecordTaskRunTime(MillisecondsAfterStart(2000), MillisecondsAfterStart(2020)); - EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(2020), false)); + EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(2020))); EXPECT_EQ(MillisecondsAfterStart(2020), pool->GetNextAllowedRunTime(SecondsAfterStart(0))); - - pool->Close(); -} - -TEST_F(BudgetPoolTest, CPUTimeBudgetPoolMinBudgetLevelToRun) { - CPUTimeBudgetPool* pool = - task_queue_throttler_->CreateCPUTimeBudgetPool("test"); - - pool->SetMinBudgetLevelToRun(SecondsAfterStart(0), - base::TimeDelta::FromMilliseconds(10)); - pool->SetTimeBudgetRecoveryRate(SecondsAfterStart(0), 0.1); - - EXPECT_TRUE(pool->CanRunTasksAt(SecondsAfterStart(0), false)); - EXPECT_EQ(SecondsAfterStart(0), - pool->GetNextAllowedRunTime(SecondsAfterStart(0))); - - pool->RecordTaskRunTime(nullptr, SecondsAfterStart(0), - MillisecondsAfterStart(10)); - EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(15), false)); - EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(150), false)); - // We need to wait extra 100ms to get budget of 10ms. - EXPECT_EQ(MillisecondsAfterStart(200), - pool->GetNextAllowedRunTime(SecondsAfterStart(0))); - - pool->RecordTaskRunTime(nullptr, MillisecondsAfterStart(200), - MillisecondsAfterStart(205)); - // We can run when budget is non-negative even when it less than 10ms. - EXPECT_EQ(MillisecondsAfterStart(205), - pool->GetNextAllowedRunTime(SecondsAfterStart(0))); - - pool->RecordTaskRunTime(nullptr, MillisecondsAfterStart(205), - MillisecondsAfterStart(215)); - EXPECT_EQ(MillisecondsAfterStart(350), - pool->GetNextAllowedRunTime(SecondsAfterStart(0))); } TEST_F(BudgetPoolTest, WakeUpBudgetPool) { - WakeUpBudgetPool* pool = - task_queue_throttler_->CreateWakeUpBudgetPool("test"); - - scoped_refptr<base::sequence_manager::TaskQueue> queue = - scheduler_->NewTaskQueueForTest(); + std::unique_ptr<WakeUpBudgetPool> pool = + std::make_unique<WakeUpBudgetPool>("test"); pool->SetWakeUpInterval(base::TimeTicks(), base::TimeDelta::FromSeconds(10)); pool->SetWakeUpDuration(base::TimeDelta::FromMilliseconds(10)); // Can't run tasks until a wake-up. - EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(0), false)); - EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(5), false)); - EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(9), false)); - EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(10), false)); - EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(11), false)); + EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(0))); + EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(5))); + EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(9))); + EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(10))); + EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(11))); pool->OnWakeUp(MillisecondsAfterStart(0)); - EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(0), false)); - EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(5), false)); - EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(9), false)); - EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(10), false)); - EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(11), false)); + EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(0))); + EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(5))); + EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(9))); + EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(10))); + EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(11))); // GetNextAllowedRunTime should return the desired time when in the // wakeup window and return the next wakeup otherwise. @@ -155,28 +105,27 @@ TEST_F(BudgetPoolTest, WakeUpBudgetPool) { EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSeconds(10), pool->GetNextAllowedRunTime(MillisecondsAfterStart(15))); - pool->RecordTaskRunTime(queue.get(), MillisecondsAfterStart(5), - MillisecondsAfterStart(7)); + pool->RecordTaskRunTime(MillisecondsAfterStart(5), MillisecondsAfterStart(7)); // Make sure that nothing changes after a task inside wakeup window. - EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(0), false)); - EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(5), false)); - EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(9), false)); - EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(10), false)); - EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(11), false)); + EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(0))); + EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(5))); + EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(9))); + EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(10))); + EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(11))); EXPECT_EQ(start_time_, pool->GetNextAllowedRunTime(start_time_)); EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSeconds(10), pool->GetNextAllowedRunTime(MillisecondsAfterStart(15))); pool->OnWakeUp(MillisecondsAfterStart(12005)); - pool->RecordTaskRunTime(queue.get(), MillisecondsAfterStart(12005), + pool->RecordTaskRunTime(MillisecondsAfterStart(12005), MillisecondsAfterStart(12007)); - EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(12005), false)); - EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(12007), false)); - EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(12014), false)); - EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(12015), false)); - EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(12016), false)); + EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(12005))); + EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(12007))); + EXPECT_TRUE(pool->CanRunTasksAt(MillisecondsAfterStart(12014))); + EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(12015))); + EXPECT_FALSE(pool->CanRunTasksAt(MillisecondsAfterStart(12016))); EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSeconds(20), pool->GetNextAllowedRunTime(SecondsAfterStart(13))); } diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc index f1a3d4f20f8..1d5f1bc699e 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc @@ -17,10 +17,9 @@ using base::sequence_manager::TaskQueue; CPUTimeBudgetPool::CPUTimeBudgetPool( const char* name, - BudgetPoolController* budget_pool_controller, TraceableVariableController* tracing_controller, base::TimeTicks now) - : BudgetPool(name, budget_pool_controller), + : BudgetPool(name), current_budget_level_(base::TimeDelta(), "RendererScheduler.BackgroundBudgetMs", tracing_controller, @@ -50,13 +49,6 @@ void CPUTimeBudgetPool::SetMaxThrottlingDelay( EnforceBudgetLevelRestrictions(); } -void CPUTimeBudgetPool::SetMinBudgetLevelToRun( - base::TimeTicks now, - base::TimeDelta min_budget_level_to_run) { - Advance(now); - min_budget_level_to_run_ = min_budget_level_to_run; -} - void CPUTimeBudgetPool::SetTimeBudgetRecoveryRate(base::TimeTicks now, double cpu_percentage) { Advance(now); @@ -76,30 +68,38 @@ void CPUTimeBudgetPool::SetReportingCallback( reporting_callback_ = reporting_callback; } -bool CPUTimeBudgetPool::CanRunTasksAt(base::TimeTicks moment, - bool is_wake_up) const { - return moment >= GetNextAllowedRunTime(moment); +bool CPUTimeBudgetPool::CanRunTasksAt(base::TimeTicks moment) const { + if (!is_enabled_) + return true; + if (current_budget_level_->InMicroseconds() >= 0) + return true; + base::TimeDelta time_to_recover_budget = + -current_budget_level_ / cpu_percentage_; + if (moment - last_checkpoint_ >= time_to_recover_budget) { + return true; + } + + return false; } base::TimeTicks CPUTimeBudgetPool::GetTimeTasksCanRunUntil( - base::TimeTicks now, - bool is_wake_up) const { - if (CanRunTasksAt(now, is_wake_up)) + base::TimeTicks now) const { + if (CanRunTasksAt(now)) return base::TimeTicks::Max(); return base::TimeTicks(); } base::TimeTicks CPUTimeBudgetPool::GetNextAllowedRunTime( base::TimeTicks desired_run_time) const { - if (!is_enabled_ || current_budget_level_->InMicroseconds() >= 0) + if (!is_enabled_ || current_budget_level_->InMicroseconds() >= 0) { return last_checkpoint_; + } // Subtract because current_budget is negative. - return last_checkpoint_ + - (-current_budget_level_ + min_budget_level_to_run_) / cpu_percentage_; + return std::max(desired_run_time, last_checkpoint_ + (-current_budget_level_ / + cpu_percentage_)); } -void CPUTimeBudgetPool::RecordTaskRunTime(TaskQueue* queue, - base::TimeTicks start_time, +void CPUTimeBudgetPool::RecordTaskRunTime(base::TimeTicks start_time, base::TimeTicks end_time) { DCHECK_LE(start_time, end_time); Advance(end_time); @@ -115,14 +115,7 @@ void CPUTimeBudgetPool::RecordTaskRunTime(TaskQueue* queue, } if (current_budget_level_->InSecondsF() < 0) - UpdateThrottlingStateForAllQueues(end_time); -} - -void CPUTimeBudgetPool::OnQueueNextWakeUpChanged( - TaskQueue* queue, - base::TimeTicks now, - base::TimeTicks desired_run_time) { - budget_pool_controller_->UpdateQueueSchedulingLifecycleState(now, queue); + UpdateStateForAllThrottlers(end_time); } void CPUTimeBudgetPool::OnWakeUp(base::TimeTicks now) {} @@ -137,8 +130,6 @@ void CPUTimeBudgetPool::WriteIntoTrace(perfetto::TracedValue context, dict.Add("last_checkpoint_seconds_ago", (now - last_checkpoint_).InSecondsF()); dict.Add("is_enabled", is_enabled_); - dict.Add("min_budget_level_to_run_in_seconds", - min_budget_level_to_run_.InSecondsF()); if (max_throttling_delay_) { dict.Add("max_throttling_delay_in_seconds", diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h index 35e6485de62..e9e6721570a 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h @@ -8,7 +8,6 @@ #include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h" #include "base/gtest_prod_util.h" -#include "base/macros.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/renderer/platform/scheduler/common/tracing_helper.h" @@ -20,9 +19,10 @@ namespace scheduler { class PLATFORM_EXPORT CPUTimeBudgetPool : public BudgetPool { public: CPUTimeBudgetPool(const char* name, - BudgetPoolController* budget_pool_controller, TraceableVariableController* tracing_controller, base::TimeTicks now); + CPUTimeBudgetPool(const CPUTimeBudgetPool&) = delete; + CPUTimeBudgetPool& operator=(const CPUTimeBudgetPool&) = delete; ~CPUTimeBudgetPool() override; @@ -39,21 +39,6 @@ class PLATFORM_EXPORT CPUTimeBudgetPool : public BudgetPool { base::TimeTicks now, absl::optional<base::TimeDelta> max_throttling_delay); - // Set minimal budget level required to run a task. If budget pool was - // exhausted, it needs to accumulate at least |min_budget_to_run| time units - // to unblock and run tasks again. When unblocked, it still can run tasks - // when budget is positive but less than this level until being blocked - // until being blocked when budget reaches zero. - // This is needed for integration with WakeUpBudgetPool to prevent a situation - // when wake-up happened but time budget pool allows only one task to run at - // the moment. - // It is recommended to use the same value for this and WakeUpBudgetPool's - // wake-up window length. - // NOTE: This does not have an immediate effect and does not call - // BudgetPoolController::UnblockQueue. - void SetMinBudgetLevelToRun(base::TimeTicks now, - base::TimeDelta min_budget_level_to_run); - // Throttle task queues from this time budget pool if tasks are running // for more than |cpu_percentage| per cent of wall time. // This function does not affect internal time budget level. @@ -70,17 +55,12 @@ class PLATFORM_EXPORT CPUTimeBudgetPool : public BudgetPool { base::RepeatingCallback<void(base::TimeDelta)> reporting_callback); // BudgetPool implementation: - void RecordTaskRunTime(base::sequence_manager::TaskQueue* queue, - base::TimeTicks start_time, + void RecordTaskRunTime(base::TimeTicks start_time, base::TimeTicks end_time) final; - bool CanRunTasksAt(base::TimeTicks moment, bool is_wake_up) const final; - base::TimeTicks GetTimeTasksCanRunUntil(base::TimeTicks now, - bool is_wake_up) const final; + bool CanRunTasksAt(base::TimeTicks moment) const final; + base::TimeTicks GetTimeTasksCanRunUntil(base::TimeTicks now) const final; base::TimeTicks GetNextAllowedRunTime( base::TimeTicks desired_run_time) const final; - void OnQueueNextWakeUpChanged(base::sequence_manager::TaskQueue* queue, - base::TimeTicks now, - base::TimeTicks desired_run_time) final; void OnWakeUp(base::TimeTicks now) final; void WriteIntoTrace(perfetto::TracedValue context, base::TimeTicks) const final; @@ -111,8 +91,6 @@ class PLATFORM_EXPORT CPUTimeBudgetPool : public BudgetPool { // after desired run time + max throttling duration, but a guarantee // that at least one task will be run every max_throttling_delay. absl::optional<base::TimeDelta> max_throttling_delay_; - // See CPUTimeBudgetPool::SetMinBudgetLevelToRun. - base::TimeDelta min_budget_level_to_run_; TraceableCounter<base::TimeDelta, TracingCategoryName::kInfo> current_budget_level_; @@ -120,8 +98,6 @@ class PLATFORM_EXPORT CPUTimeBudgetPool : public BudgetPool { double cpu_percentage_; base::RepeatingCallback<void(base::TimeDelta)> reporting_callback_; - - DISALLOW_COPY_AND_ASSIGN(CPUTimeBudgetPool); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc index 45ead45baf6..43c602d4649 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc @@ -13,10 +13,7 @@ #include "base/memory/ptr_util.h" #include "base/time/tick_clock.h" #include "third_party/abseil-cpp/absl/types/optional.h" -#include "third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h" #include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h" -#include "third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.h" -#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h" #include "third_party/blink/renderer/platform/wtf/hash_set.h" namespace blink { @@ -25,380 +22,183 @@ namespace scheduler { using base::sequence_manager::LazyNow; using base::sequence_manager::TaskQueue; -namespace { - -absl::optional<base::TimeTicks> NextTaskRunTime(LazyNow* lazy_now, - TaskQueue* queue) { - if (queue->HasTaskToRunImmediately()) - return lazy_now->Now(); - return queue->GetNextScheduledWakeUp(); -} - -} // namespace - TaskQueueThrottler::TaskQueueThrottler( - ThreadSchedulerImpl* thread_scheduler, - TraceableVariableController* tracing_controller) - : control_task_runner_(thread_scheduler->ControlTaskRunner()), - thread_scheduler_(thread_scheduler), - tracing_controller_(tracing_controller), - tick_clock_(thread_scheduler->GetTickClock()), - time_domain_(new ThrottledTimeDomain()), - allow_throttling_(true) { - pump_throttled_tasks_closure_.Reset(base::BindRepeating( - &TaskQueueThrottler::PumpThrottledTasks, weak_factory_.GetWeakPtr())); - forward_immediate_work_callback_ = - base::BindRepeating(&TaskQueueThrottler::OnQueueNextWakeUpChanged, - weak_factory_.GetWeakPtr()); - - thread_scheduler_->RegisterTimeDomain(time_domain_.get()); -} + base::sequence_manager::TaskQueue* task_queue, + const base::TickClock* tick_clock) + : task_queue_(task_queue), tick_clock_(tick_clock) {} TaskQueueThrottler::~TaskQueueThrottler() { - // It's possible for queues to be still throttled, so we need to tidy up - // before unregistering the time domain. - for (const TaskQueueMap::value_type& map_entry : queue_details_) { - TaskQueue* task_queue = map_entry.key; - if (IsThrottled(task_queue)) { - task_queue->SetTimeDomain(thread_scheduler_->GetActiveTimeDomain()); - task_queue->RemoveFence(); - } - } + if (IsThrottled()) + DisableThrottling(); - thread_scheduler_->UnregisterTimeDomain(time_domain_.get()); + for (BudgetPool* budget_pool : budget_pools_) { + budget_pool->UnregisterThrottler(this); + } } -void TaskQueueThrottler::IncreaseThrottleRefCount(TaskQueue* task_queue) { - auto insert_result = queue_details_.insert( - task_queue, std::make_unique<Metadata>(task_queue, this)); - if (!insert_result.stored_value->value->IncrementRefCount()) +void TaskQueueThrottler::IncreaseThrottleRefCount() { + if (throttling_ref_count_++ != 0) return; // Task queue is newly throttled. TRACE_EVENT1("renderer.scheduler", "TaskQueueThrottler_TaskQueueThrottled", - "task_queue", static_cast<void*>(task_queue)); + "task_queue", static_cast<void*>(task_queue_)); - if (!allow_throttling_) + task_queue_->SetThrottler(this); + if (!task_queue_->IsQueueEnabled()) return; - task_queue->SetTimeDomain(time_domain_.get()); - // This blocks any tasks from |task_queue| until PumpThrottledTasks() to - // enforce task alignment. - task_queue->InsertFence(TaskQueue::InsertFencePosition::kBeginningOfTime); - - if (!task_queue->IsQueueEnabled()) - return; - - if (!task_queue->IsEmpty()) { - LazyNow lazy_now(tick_clock_); - OnQueueNextWakeUpChanged(task_queue, - NextTaskRunTime(&lazy_now, task_queue).value()); - } + UpdateQueueState(tick_clock_->NowTicks()); } -void TaskQueueThrottler::DecreaseThrottleRefCount(TaskQueue* task_queue) { - TaskQueueMap::iterator iter = queue_details_.find(task_queue); - - if (iter == queue_details_.end()) - return; - if (!iter->value->DecrementRefCount()) +void TaskQueueThrottler::DecreaseThrottleRefCount() { + DCHECK_GT(throttling_ref_count_, 0U); + if (--throttling_ref_count_ != 0) return; TRACE_EVENT1("renderer.scheduler", "TaskQueueThrottler_TaskQueueUnthrottled", - "task_queue", static_cast<void*>(task_queue)); - - MaybeDeleteQueueMetadata(iter); - - if (!allow_throttling_) - return; - - task_queue->SetTimeDomain(thread_scheduler_->GetActiveTimeDomain()); - task_queue->RemoveFence(); -} - -bool TaskQueueThrottler::IsThrottled(TaskQueue* task_queue) const { - if (!allow_throttling_) - return false; - - auto find_it = queue_details_.find(task_queue); - if (find_it == queue_details_.end()) - return false; - return find_it->value->throttling_ref_count() > 0; -} - -void TaskQueueThrottler::ShutdownTaskQueue(TaskQueue* task_queue) { - auto find_it = queue_details_.find(task_queue); - if (find_it == queue_details_.end()) - return; - - // Reset a time domain reference to a valid domain, otherwise it's possible - // to get a stale reference when deleting queue. - task_queue->SetTimeDomain(thread_scheduler_->GetActiveTimeDomain()); - task_queue->RemoveFence(); - - // Copy intended. - auto budget_pools = find_it->value->budget_pools(); - for (BudgetPool* budget_pool : budget_pools) { - budget_pool->UnregisterQueue(task_queue); - } - - // Iterator may have been deleted by BudgetPool::RemoveQueue, so don't - // use it here. - queue_details_.erase(task_queue); - - // NOTE: Observer is automatically unregistered when unregistering task queue. -} - -void TaskQueueThrottler::OnQueueNextWakeUpChanged( - TaskQueue* queue, - base::TimeTicks next_wake_up) { - if (!control_task_runner_->RunsTasksInCurrentSequence()) { - control_task_runner_->PostTask( - FROM_HERE, base::BindOnce(forward_immediate_work_callback_, - base::RetainedRef(queue), next_wake_up)); - return; - } - - TRACE_EVENT0("renderer.scheduler", - "TaskQueueThrottler::OnQueueNextWakeUpChanged"); - - // We don't expect this to get called for disabled queues, but we can't DCHECK - // because of the above thread hop. Just bail out if the queue is disabled. - if (!queue->IsQueueEnabled()) - return; - - base::TimeTicks now = tick_clock_->NowTicks(); - next_wake_up = std::max(now, next_wake_up); - - auto find_it = queue_details_.find(queue); - if (find_it == queue_details_.end()) - return; - - for (BudgetPool* budget_pool : find_it->value->budget_pools()) { - budget_pool->OnQueueNextWakeUpChanged(queue, now, next_wake_up); - } - - // TODO(altimin): This probably can be removed —- budget pools should - // schedule this. - base::TimeTicks next_allowed_run_time = - UpdateNextAllowedRunTime(queue, next_wake_up); - MaybeSchedulePumpThrottledTasks( - FROM_HERE, now, std::max(next_wake_up, next_allowed_run_time)); -} - -void TaskQueueThrottler::PumpThrottledTasks() { - TRACE_EVENT0("renderer.scheduler", "TaskQueueThrottler::PumpThrottledTasks"); - pending_pump_throttled_tasks_runtime_.reset(); - - LazyNow lazy_now(tick_clock_); - - // Collect BudgetPools for which at least one queue has reached its next - // granted run time. - HashSet<BudgetPool*> budget_pools_at_next_granted_run_time; - for (const TaskQueueMap::value_type& map_entry : queue_details_) { - const base::TimeTicks next_granted_run_time = - map_entry.value->next_granted_run_time(); - if (next_granted_run_time <= lazy_now.Now()) { - budget_pools_at_next_granted_run_time.ReserveCapacityForSize( - map_entry.value->budget_pools().size()); - for (BudgetPool* budget_pool : map_entry.value->budget_pools()) - budget_pools_at_next_granted_run_time.insert(budget_pool); + "task_queue", static_cast<void*>(task_queue_)); + DisableThrottling(); +} + +bool TaskQueueThrottler::IsThrottled() const { + return throttling_ref_count_ > 0; +} + +absl::optional<base::sequence_manager::DelayedWakeUp> +TaskQueueThrottler::GetNextAllowedWakeUpImpl( + LazyNow* lazy_now, + absl::optional<base::sequence_manager::DelayedWakeUp> next_wake_up, + bool has_ready_task) { + DCHECK(IsThrottled()); + DCHECK(task_queue_->IsQueueEnabled()); + + if (has_ready_task) { + base::TimeTicks allowed_run_time = GetNextAllowedRunTime(lazy_now->Now()); + // If |allowed_run_time| is null, immediate tasks can run immediately and + // they don't require a delayed wake up (a delayed wake up might be required + // for delayed tasks, see below). Otherwise, schedule a delayed wake up to + // update the fence in the future. + if (!allowed_run_time.is_null()) { + // WakeUpResolution::kLow is always used for throttled tasks since those + // tasks can tolerate having their execution being delayed. + return base::sequence_manager::DelayedWakeUp{ + allowed_run_time, base::sequence_manager::WakeUpResolution::kLow}; } } + if (!next_wake_up.has_value()) + return absl::nullopt; - // Notify BudgetPools for which at least one queue has reached its next - // granted run time about the wake up. - for (BudgetPool* budget_pool : budget_pools_at_next_granted_run_time) - budget_pool->OnWakeUp(lazy_now.Now()); + base::TimeTicks desired_run_time = + std::max(next_wake_up->time, lazy_now->Now()); + base::TimeTicks allowed_run_time = GetNextAllowedRunTime(desired_run_time); + if (allowed_run_time.is_null()) + allowed_run_time = desired_run_time; - // Update throttling state for all queues. - for (const TaskQueueMap::value_type& map_entry : queue_details_) { - TaskQueue* task_queue = map_entry.key; - UpdateQueueSchedulingLifecycleStateInternal(lazy_now.Now(), task_queue, - true); - } + return base::sequence_manager::DelayedWakeUp{ + allowed_run_time, base::sequence_manager::WakeUpResolution::kLow}; } -/* static */ -base::TimeTicks TaskQueueThrottler::AlignedThrottledRunTime( - base::TimeTicks unthrottled_runtime) { - const base::TimeDelta one_second = base::TimeDelta::FromSeconds(1); - return unthrottled_runtime + one_second - - ((unthrottled_runtime - base::TimeTicks()) % one_second); -} +void TaskQueueThrottler::OnHasImmediateTask() { + DCHECK(IsThrottled()); + DCHECK(task_queue_->IsQueueEnabled()); -void TaskQueueThrottler::MaybeSchedulePumpThrottledTasks( - const base::Location& from_here, - base::TimeTicks now, - base::TimeTicks unaligned_runtime) { - if (!allow_throttling_) - return; + TRACE_EVENT0("renderer.scheduler", "TaskQueueThrottler::OnHasImmediateTask"); - // TODO(altimin): Consider removing alignment here. - base::TimeTicks runtime = - std::max(now, unaligned_runtime) - .SnappedToNextTick(base::TimeTicks(), - base::TimeDelta::FromSeconds(1)); - DCHECK_LE(now, runtime); - - // If there is a pending call to PumpThrottledTasks and it's sooner than - // |runtime| then return. - if (pending_pump_throttled_tasks_runtime_ && - runtime >= pending_pump_throttled_tasks_runtime_.value()) { - return; + LazyNow lazy_now(tick_clock_); + if (CanRunTasksAt(lazy_now.Now())) { + UpdateFence(lazy_now.Now()); + } else { + task_queue_->UpdateDelayedWakeUp(&lazy_now); } - - pending_pump_throttled_tasks_runtime_ = runtime; - - pump_throttled_tasks_closure_.Cancel(); - - base::TimeDelta delay = pending_pump_throttled_tasks_runtime_.value() - now; - TRACE_EVENT1("renderer.scheduler", - "TaskQueueThrottler::MaybeSchedulePumpThrottledTasks", - "delay_till_next_pump_ms", delay.InMilliseconds()); - control_task_runner_->PostDelayedTask( - from_here, pump_throttled_tasks_closure_.GetCallback(), delay); } -CPUTimeBudgetPool* TaskQueueThrottler::CreateCPUTimeBudgetPool( - const char* name) { - CPUTimeBudgetPool* time_budget_pool = new CPUTimeBudgetPool( - name, this, tracing_controller_, tick_clock_->NowTicks()); - budget_pools_.Set(time_budget_pool, base::WrapUnique(time_budget_pool)); - return time_budget_pool; -} +absl::optional<base::sequence_manager::DelayedWakeUp> +TaskQueueThrottler::GetNextAllowedWakeUp( + LazyNow* lazy_now, + absl::optional<base::sequence_manager::DelayedWakeUp> next_desired_wake_up, + bool has_ready_task) { + TRACE_EVENT0("renderer.scheduler", + "TaskQueueThrottler::OnNextDelayedWakeUpChanged"); -WakeUpBudgetPool* TaskQueueThrottler::CreateWakeUpBudgetPool(const char* name) { - WakeUpBudgetPool* wake_up_budget_pool = - new WakeUpBudgetPool(name, this, tick_clock_->NowTicks()); - budget_pools_.Set(wake_up_budget_pool, base::WrapUnique(wake_up_budget_pool)); - return wake_up_budget_pool; + return GetNextAllowedWakeUpImpl(lazy_now, next_desired_wake_up, + has_ready_task); } -void TaskQueueThrottler::OnTaskRunTimeReported(TaskQueue* task_queue, - base::TimeTicks start_time, +void TaskQueueThrottler::OnTaskRunTimeReported(base::TimeTicks start_time, base::TimeTicks end_time) { - if (!IsThrottled(task_queue)) + if (!IsThrottled()) return; - auto find_it = queue_details_.find(task_queue); - if (find_it == queue_details_.end()) - return; - - for (BudgetPool* budget_pool : find_it->value->budget_pools()) { - budget_pool->RecordTaskRunTime(task_queue, start_time, end_time); + for (BudgetPool* budget_pool : budget_pools_) { + budget_pool->RecordTaskRunTime(start_time, end_time); } } -void TaskQueueThrottler::UpdateQueueSchedulingLifecycleState( - base::TimeTicks now, - TaskQueue* queue) { - UpdateQueueSchedulingLifecycleStateInternal(now, queue, false); -} - -void TaskQueueThrottler::UpdateQueueSchedulingLifecycleStateInternal( - base::TimeTicks now, - TaskQueue* queue, - bool is_wake_up) { - // Clear the next granted run time, to ensure that the queue's BudgetPools - // aren't incorrectly informed of a wake up at the next PumpThrottledTasks(). - // If necessary, an up-to-date next granted run time will be set below. - auto find_it = queue_details_.find(queue); - if (find_it != queue_details_.end()) - find_it->value->set_next_granted_run_time(base::TimeTicks::Max()); - - if (!queue->IsQueueEnabled() || !IsThrottled(queue)) { +void TaskQueueThrottler::UpdateQueueState(base::TimeTicks now) { + if (!task_queue_->IsQueueEnabled() || !IsThrottled()) return; - } - LazyNow lazy_now(now); - - absl::optional<base::TimeTicks> next_desired_run_time = - NextTaskRunTime(&lazy_now, queue); - - if (CanRunTasksAt(queue, now, is_wake_up)) { - // Unblock queue if we can run tasks immediately. - base::TimeTicks unblock_until = - GetTimeTasksCanRunUntil(queue, now, is_wake_up); - if (unblock_until.is_max()) { - queue->RemoveFence(); - } else if (unblock_until > now) { - queue->InsertFenceAt(unblock_until); - } else { - DCHECK_EQ(unblock_until, now); - queue->InsertFence(TaskQueue::InsertFencePosition::kNow); + if (CanRunTasksAt(now)) { + UpdateFence(now); + } else { + // Insert a fence of an appropriate type. + absl::optional<QueueBlockType> block_type = GetBlockType(now); + DCHECK(block_type); + switch (block_type.value()) { + case QueueBlockType::kAllTasks: + task_queue_->InsertFence( + TaskQueue::InsertFencePosition::kBeginningOfTime); + break; + case QueueBlockType::kNewTasksOnly: + if (!task_queue_->HasActiveFence()) { + // Insert a new non-fully blocking fence only when there is no fence + // already in order avoid undesired unblocking of old tasks. + task_queue_->InsertFence(TaskQueue::InsertFencePosition::kNow); + } + break; } - - // Throttled time domain does not schedule wake-ups without explicitly being - // told so. Schedule a wake up if there is a next desired run time in the - // future, and tasks can run at that time. - if (next_desired_run_time.has_value() && - next_desired_run_time.value() != now && - next_desired_run_time.value() < unblock_until) { - time_domain_->SetNextTaskRunTime(next_desired_run_time.value()); - } - - absl::optional<base::TimeTicks> next_wake_up = - queue->GetNextScheduledWakeUp(); - // TODO(altimin, crbug.com/813218): Find a testcase to repro freezes - // mentioned in the bug. - if (next_wake_up) { - MaybeSchedulePumpThrottledTasks( - FROM_HERE, now, - UpdateNextAllowedRunTime(queue, next_wake_up.value())); - } - - return; + TRACE_EVENT_INSTANT("renderer.scheduler", + "TaskQueueThrottler::InsertFence"); } - - if (!next_desired_run_time) - return; - - const base::TimeTicks next_run_time = - UpdateNextAllowedRunTime(queue, next_desired_run_time.value()); - - // Insert a fence of an approriate type. - absl::optional<QueueBlockType> block_type = GetQueueBlockType(now, queue); - DCHECK(block_type); - - switch (block_type.value()) { - case QueueBlockType::kAllTasks: - queue->InsertFence(TaskQueue::InsertFencePosition::kBeginningOfTime); - - { - // Braces limit the scope for a declared variable. Does not compile - // otherwise. - TRACE_EVENT1( - "renderer.scheduler", - "TaskQueueThrottler::PumpThrottledTasks_ExpensiveTaskThrottled", - "throttle_time_in_seconds", - (next_run_time - next_desired_run_time.value()).InSecondsF()); - } - break; - case QueueBlockType::kNewTasksOnly: - if (!queue->HasActiveFence()) { - // Insert a new non-fully blocking fence only when there is no fence - // already in order avoid undesired unblocking of old tasks. - queue->InsertFence(TaskQueue::InsertFencePosition::kNow); - } - break; + task_queue_->UpdateDelayedWakeUp(&lazy_now); +} + +void TaskQueueThrottler::OnWakeUp(base::sequence_manager::LazyNow* lazy_now) { + DCHECK(IsThrottled()); + for (BudgetPool* budget_pool : budget_pools_) + budget_pool->OnWakeUp(lazy_now->Now()); + + base::TimeTicks now = lazy_now->Now(); + DCHECK(CanRunTasksAt(now)); + UpdateFence(now); +} + +void TaskQueueThrottler::UpdateFence(base::TimeTicks now) { + DCHECK(IsThrottled()); + // Unblock queue if we can run tasks immediately. + base::TimeTicks unblock_until = GetTimeTasksCanRunUntil(now); + if (unblock_until.is_max()) { + task_queue_->RemoveFence(); + } else if (unblock_until > now) { + task_queue_->InsertFenceAt(unblock_until); + } else { + DCHECK_EQ(unblock_until, now); + task_queue_->InsertFence(TaskQueue::InsertFencePosition::kNow); } - - // Schedule a pump. - MaybeSchedulePumpThrottledTasks(FROM_HERE, now, next_run_time); } -absl::optional<QueueBlockType> TaskQueueThrottler::GetQueueBlockType( - base::TimeTicks now, - TaskQueue* queue) { - auto find_it = queue_details_.find(queue); - if (find_it == queue_details_.end()) - return absl::nullopt; +void TaskQueueThrottler::DisableThrottling() { + task_queue_->RemoveFence(); + task_queue_->ResetThrottler(); +} +absl::optional<QueueBlockType> TaskQueueThrottler::GetBlockType( + base::TimeTicks now) const { bool has_new_tasks_only_block = false; - for (BudgetPool* budget_pool : find_it->value->budget_pools()) { - if (!budget_pool->CanRunTasksAt(now, false)) { + for (BudgetPool* budget_pool : budget_pools_) { + if (!budget_pool->CanRunTasksAt(now)) { if (budget_pool->GetBlockType() == QueueBlockType::kAllTasks) return QueueBlockType::kAllTasks; DCHECK_EQ(budget_pool->GetBlockType(), QueueBlockType::kNewTasksOnly); @@ -411,207 +211,54 @@ absl::optional<QueueBlockType> TaskQueueThrottler::GetQueueBlockType( return absl::nullopt; } -void TaskQueueThrottler::WriteIntoTrace(perfetto::TracedValue context, - base::TimeTicks now) const { - auto dict = std::move(context).WriteDictionary(); - if (pending_pump_throttled_tasks_runtime_) { - dict.Add( - "next_throttled_tasks_pump_in_seconds", - (pending_pump_throttled_tasks_runtime_.value() - now).InSecondsF()); - } - - dict.Add("allow_throttling", allow_throttling_); - - { - auto time_budget_pools = dict.AddArray("time_budget_pools"); - for (const auto& budget_pool : budget_pools_) { - budget_pool.key->WriteIntoTrace(time_budget_pools.AppendItem(), now); - } - } - - { - auto queue_details_array = dict.AddArray("queue_details"); - for (const auto& queue_details : queue_details_) { - auto details_dict = queue_details_array.AppendDictionary(); - details_dict.Add("queue_name", queue_details.key->GetName()); - details_dict.Add("metadata", queue_details.value); - } - } +void TaskQueueThrottler::AddBudgetPool(BudgetPool* budget_pool) { + budget_pools_.insert(budget_pool); } -void TaskQueueThrottler::AddQueueToBudgetPool(TaskQueue* queue, - BudgetPool* budget_pool) { - auto insert_result = - queue_details_.insert(queue, std::make_unique<Metadata>(queue, this)); - - Metadata* metadata = insert_result.stored_value->value.get(); - - DCHECK(metadata->budget_pools().find(budget_pool) == - metadata->budget_pools().end()); - - metadata->budget_pools().insert(budget_pool); -} - -void TaskQueueThrottler::RemoveQueueFromBudgetPool(TaskQueue* queue, - BudgetPool* budget_pool) { - auto find_it = queue_details_.find(queue); - DCHECK(find_it != queue_details_.end() && - find_it->value->budget_pools().find(budget_pool) != - find_it->value->budget_pools().end()); - - find_it->value->budget_pools().erase(budget_pool); - - MaybeDeleteQueueMetadata(find_it); -} - -void TaskQueueThrottler::UnregisterBudgetPool(BudgetPool* budget_pool) { +void TaskQueueThrottler::RemoveBudgetPool(BudgetPool* budget_pool) { budget_pools_.erase(budget_pool); } -base::TimeTicks TaskQueueThrottler::UpdateNextAllowedRunTime( - TaskQueue* queue, - base::TimeTicks desired_run_time) { - base::TimeTicks next_run_time = desired_run_time; - - auto find_it = queue_details_.find(queue); - if (find_it == queue_details_.end()) - return next_run_time; - - for (BudgetPool* budget_pool : find_it->value->budget_pools()) { - next_run_time = std::max( - next_run_time, budget_pool->GetNextAllowedRunTime(desired_run_time)); - } - - find_it->value->set_next_granted_run_time(next_run_time); - - return next_run_time; -} - -bool TaskQueueThrottler::CanRunTasksAt(TaskQueue* queue, - base::TimeTicks moment, - bool is_wake_up) { - auto find_it = queue_details_.find(queue); - if (find_it == queue_details_.end()) - return true; - - for (BudgetPool* budget_pool : find_it->value->budget_pools()) { - if (!budget_pool->CanRunTasksAt(moment, is_wake_up)) +bool TaskQueueThrottler::CanRunTasksAt(base::TimeTicks moment) { + for (BudgetPool* budget_pool : budget_pools_) { + if (!budget_pool->CanRunTasksAt(moment)) { return false; + } } return true; } -base::TimeTicks TaskQueueThrottler::GetTimeTasksCanRunUntil( - TaskQueue* queue, - base::TimeTicks now, - bool is_wake_up) const { - // Start with no known limit for the time tasks can run until. - base::TimeTicks result = base::TimeTicks::Max(); - - auto find_it = queue_details_.find(queue); - if (find_it == queue_details_.end()) - return result; +base::TimeTicks TaskQueueThrottler::GetNextAllowedRunTime( + base::TimeTicks desired_runtime) const { + // If |desired_runtime| isn't affected by any BudgetPool, TimeTicks() is + // returned. + base::TimeTicks result = base::TimeTicks(); - for (BudgetPool* budget_pool : find_it->value->budget_pools()) { + for (BudgetPool* budget_pool : budget_pools_) { + if (budget_pool->CanRunTasksAt(desired_runtime)) + continue; result = - std::min(result, budget_pool->GetTimeTasksCanRunUntil(now, is_wake_up)); + std::max(result, budget_pool->GetNextAllowedRunTime(desired_runtime)); } - return result; } -void TaskQueueThrottler::MaybeDeleteQueueMetadata(TaskQueueMap::iterator it) { - if (it->value->throttling_ref_count() == 0 && - it->value->budget_pools().IsEmpty()) { - queue_details_.erase(it); - } -} - -void TaskQueueThrottler::DisableThrottling() { - if (!allow_throttling_) - return; - - allow_throttling_ = false; - - for (const auto& map_entry : queue_details_) { - if (map_entry.value->throttling_ref_count() == 0) - continue; - - TaskQueue* queue = map_entry.key; - - queue->SetTimeDomain(thread_scheduler_->GetActiveTimeDomain()); - queue->RemoveFence(); - } - - pump_throttled_tasks_closure_.Cancel(); - pending_pump_throttled_tasks_runtime_ = absl::nullopt; - - TRACE_EVENT0("renderer.scheduler", "TaskQueueThrottler_DisableThrottling"); -} - -void TaskQueueThrottler::EnableThrottling() { - if (allow_throttling_) - return; - - allow_throttling_ = true; - - LazyNow lazy_now(tick_clock_); - - for (const auto& map_entry : queue_details_) { - if (map_entry.value->throttling_ref_count() == 0) - continue; - - TaskQueue* queue = map_entry.key; - - // Throttling is enabled and task queue should be blocked immediately - // to enforce task alignment. - queue->InsertFence(TaskQueue::InsertFencePosition::kBeginningOfTime); - queue->SetTimeDomain(time_domain_.get()); - UpdateQueueSchedulingLifecycleState(lazy_now.Now(), queue); - } - - TRACE_EVENT0("renderer.scheduler", "TaskQueueThrottler_EnableThrottling"); -} - -TaskQueueThrottler::Metadata::Metadata(base::sequence_manager::TaskQueue* queue, - TaskQueueThrottler* throttler) - : queue_(queue), throttler_(throttler) {} - -TaskQueueThrottler::Metadata::~Metadata() { - if (throttling_ref_count_ > 0) - queue_->SetObserver(nullptr); -} - -bool TaskQueueThrottler::Metadata::IncrementRefCount() { - if (throttling_ref_count_++ == 0) { - queue_->SetObserver(this); - return true; - } - return false; -} +base::TimeTicks TaskQueueThrottler::GetTimeTasksCanRunUntil( + base::TimeTicks now) const { + // Start with no known limit for the time tasks can run until. + base::TimeTicks result = base::TimeTicks::Max(); -// Returns true if |throttling_ref_count_| is now zero. -bool TaskQueueThrottler::Metadata::DecrementRefCount() { - if (throttling_ref_count_ == 0) - return false; - if (--throttling_ref_count_ == 0) { - queue_->SetObserver(nullptr); - return true; + for (BudgetPool* budget_pool : budget_pools_) { + result = std::min(result, budget_pool->GetTimeTasksCanRunUntil(now)); } - return false; -} -void TaskQueueThrottler::Metadata::OnQueueNextWakeUpChanged( - base::TimeTicks wake_up) { - throttler_->OnQueueNextWakeUpChanged(queue_, wake_up); + return result; } -void TaskQueueThrottler::Metadata::WriteIntoTrace( - perfetto::TracedValue context) const { +void TaskQueueThrottler::WriteIntoTrace(perfetto::TracedValue context) const { auto dict = std::move(context).WriteDictionary(); dict.Add("throttling_ref_count", throttling_ref_count_); - dict.Add("next_granted_run_time", next_granted_run_time_); } } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h index e2028aa577b..c56289aff1a 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h @@ -5,21 +5,12 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THROTTLING_TASK_QUEUE_THROTTLER_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THROTTLING_TASK_QUEUE_THROTTLER_H_ -#include "base/macros.h" -#include "base/memory/weak_ptr.h" #include "base/task/sequence_manager/task_queue.h" -#include "base/task/sequence_manager/time_domain.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/renderer/platform/platform_export.h" -#include "third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h" -#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h" -#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_controller.h" -#include "third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h" -#include "third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h" #include "third_party/blink/renderer/platform/scheduler/common/tracing_helper.h" -#include "third_party/blink/renderer/platform/wtf/hash_map.h" #include "third_party/blink/renderer/platform/wtf/hash_set.h" #include "third_party/perfetto/include/perfetto/tracing/traced_value_forward.h" @@ -33,10 +24,6 @@ namespace blink { namespace scheduler { class BudgetPool; -class ThreadSchedulerImpl; -class ThrottledTimeDomain; -class CPUTimeBudgetPool; -class WakeUpBudgetPool; // kNewTasksOnly prevents new tasks from running (old tasks can run normally), // kAllTasks block queue completely. @@ -46,201 +33,93 @@ class WakeUpBudgetPool; // unblock some tasks. enum class QueueBlockType { kAllTasks, kNewTasksOnly }; -// The job of the TaskQueueThrottler is to control when tasks posted on -// throttled queues get run. The TaskQueueThrottler: -// - runs throttled tasks once per second, -// - controls time budget for task queues grouped in CPUTimeBudgetPools. +// The job of the TaskQueueThrottler is to control when tasks posted on a +// throttled queue get to run. // -// This is done by disabling throttled queues and running -// a special "heart beat" function |PumpThrottledTasks| which when run -// temporarily enables throttled queues and inserts a fence to ensure tasks -// posted from a throttled task run next time the queue is pumped. +// This is done by inserting a fence in the queue when it cannot run and +// removing or updating the fence when the next allowed wake up time is reached. // -// Of course the TaskQueueThrottler isn't the only sub-system that wants to -// enable or disable queues. E.g. ThreadSchedulerImpl also does this for -// policy reasons. To prevent the systems from fighting, clients of -// TaskQueueThrottler must use SetQueueEnabled rather than calling the function -// directly on the queue. +// TaskQueueThrottler assumes that it's the only system inserting fences in +// its associated TaskQueue. // // There may be more than one system that wishes to throttle a queue (e.g. // renderer suspension vs tab level suspension) so the TaskQueueThrottler keeps -// a count of the number of systems that wish a queue to be throttled. -// See IncreaseThrottleRefCount & DecreaseThrottleRefCount. +// a count of the number of systems that wish the queue to be throttled. See +// IncreaseThrottleRefCount & DecreaseThrottleRefCount. // // This class is main-thread only. -class PLATFORM_EXPORT TaskQueueThrottler : public BudgetPoolController { +class PLATFORM_EXPORT TaskQueueThrottler final + : public base::sequence_manager::TaskQueue::Throttler { public: - // We use tracing controller from ThreadSchedulerImpl because an instance - // of this class is always its member, so has the same lifetime. - TaskQueueThrottler(ThreadSchedulerImpl* thread_scheduler, - TraceableVariableController* tracing_controller); - - ~TaskQueueThrottler() override; - - void OnQueueNextWakeUpChanged(base::sequence_manager::TaskQueue* queue, - base::TimeTicks wake_up); - - // BudgetPoolController implementation: - void AddQueueToBudgetPool(base::sequence_manager::TaskQueue* queue, - BudgetPool* budget_pool) override; - void RemoveQueueFromBudgetPool(base::sequence_manager::TaskQueue* queue, - BudgetPool* budget_pool) override; - void UnregisterBudgetPool(BudgetPool* budget_pool) override; - void UpdateQueueSchedulingLifecycleState( - base::TimeTicks now, - base::sequence_manager::TaskQueue* queue) override; - bool IsThrottled(base::sequence_manager::TaskQueue* queue) const override; + TaskQueueThrottler(base::sequence_manager::TaskQueue* task_queue, + const base::TickClock* tick_clock); + TaskQueueThrottler(const TaskQueueThrottler&) = delete; + TaskQueueThrottler& operator=(const TaskQueueThrottler&) = delete; + ~TaskQueueThrottler(); + + // Updates the queue's next wake up and fence based on policies enforced + // by this TaskQueueThrottler's budget pools. + void UpdateQueueState(base::TimeTicks now); + + // Returns true if the queue is throttled. + bool IsThrottled() const; // Increments the throttled refcount and causes |task_queue| to be throttled // if its not already throttled. - void IncreaseThrottleRefCount(base::sequence_manager::TaskQueue* task_queue); - + void IncreaseThrottleRefCount(); // If the refcouint is non-zero it's decremented. If the throttled refcount // becomes zero then |task_queue| is unthrottled. If the refcount was already // zero this function does nothing. - void DecreaseThrottleRefCount(base::sequence_manager::TaskQueue* task_queue); - - // Removes |task_queue| from |queue_details| and from appropriate budget pool. - void ShutdownTaskQueue(base::sequence_manager::TaskQueue* task_queue); - - // Disable throttling for all queues, this setting takes precedence over - // all other throttling settings. Designed to be used when a global event - // disabling throttling happens (e.g. audio is playing). - void DisableThrottling(); - - // Enable back global throttling. - void EnableThrottling(); - - const ThrottledTimeDomain* time_domain() const { return time_domain_.get(); } - - // TODO(altimin): Remove it. - static base::TimeTicks AlignedThrottledRunTime( - base::TimeTicks unthrottled_runtime); - - // Returned object is owned by |TaskQueueThrottler|. - CPUTimeBudgetPool* CreateCPUTimeBudgetPool(const char* name); - WakeUpBudgetPool* CreateWakeUpBudgetPool(const char* name); + void DecreaseThrottleRefCount(); // Accounts for given task for cpu-based throttling needs. - void OnTaskRunTimeReported(base::sequence_manager::TaskQueue* task_queue, - base::TimeTicks start_time, + void OnTaskRunTimeReported(base::TimeTicks start_time, base::TimeTicks end_time); - void WriteIntoTrace(perfetto::TracedValue context, base::TimeTicks now) const; - - base::WeakPtr<TaskQueueThrottler> AsWeakPtr() { - return weak_factory_.GetWeakPtr(); - } + void WriteIntoTrace(perfetto::TracedValue context) const; private: - class Metadata : public base::sequence_manager::TaskQueue::Observer { - public: - Metadata(base::sequence_manager::TaskQueue* queue, - TaskQueueThrottler* throttler); - - ~Metadata() override; - - // Returns true if |throttling_ref_count_| was zero. - bool IncrementRefCount(); - - // Returns true if |throttling_ref_count_| is now zero. - bool DecrementRefCount(); - - // TaskQueue::Observer implementation: - void OnQueueNextWakeUpChanged(base::TimeTicks wake_up) override; + friend class BudgetPool; - size_t throttling_ref_count() const { return throttling_ref_count_; } + absl::optional<QueueBlockType> GetBlockType(base::TimeTicks now) const; - const HashSet<BudgetPool*>& budget_pools() const { return budget_pools_; } + // To be used by BudgetPool only, use BudgetPool::{Add,Remove}Queue + // methods instead. + void AddBudgetPool(BudgetPool* budget_pool); + void RemoveBudgetPool(BudgetPool* budget_pool); - HashSet<BudgetPool*>& budget_pools() { return budget_pools_; } - - base::TimeTicks next_granted_run_time() const { - return next_granted_run_time_; - } - void set_next_granted_run_time(base::TimeTicks next_granted_run_time) { - next_granted_run_time_ = next_granted_run_time; - } - - void WriteIntoTrace(perfetto::TracedValue context) const; - - private: - base::sequence_manager::TaskQueue* const queue_; - TaskQueueThrottler* const throttler_; - size_t throttling_ref_count_ = 0; - HashSet<BudgetPool*> budget_pools_; - - // The next granted run time for |queue_|. Is TimeTicks::Max() when there is - // no next granted run time, for example when: - // - The queue didn't request a wake up. - // - The queue only has immediate tasks which are currently allowed to run. - // - A wake up just happened and the next granted run time is about to be - // re-evaluated. - base::TimeTicks next_granted_run_time_ = base::TimeTicks::Max(); - - DISALLOW_COPY_AND_ASSIGN(Metadata); - }; - - using TaskQueueMap = - HashMap<base::sequence_manager::TaskQueue*, std::unique_ptr<Metadata>>; - - void PumpThrottledTasks(); - - // Note |unthrottled_runtime| might be in the past. When this happens we - // compute the delay to the next runtime based on now rather than - // unthrottled_runtime. - void MaybeSchedulePumpThrottledTasks(const base::Location& from_here, - base::TimeTicks now, - base::TimeTicks runtime); - - // Evaluate the next possible time when |queue| is allowed to run in - // accordance with throttling policy. Returns it and stores it in |queue|'s - // metadata. - base::TimeTicks UpdateNextAllowedRunTime( - base::sequence_manager::TaskQueue* queue, - base::TimeTicks desired_run_time); - - bool CanRunTasksAt(base::sequence_manager::TaskQueue* queue, - base::TimeTicks moment, - bool is_wake_up); + bool CanRunTasksAt(base::TimeTicks moment); + // Returns the next allowed runtime, given |desired_runtime| if it was + // affected by any BudgetPool, of TimeTicks() otherwise. + base::TimeTicks GetNextAllowedRunTime(base::TimeTicks desired_runtime) const; // Returns the time until which tasks in |queue| can run. TimeTicks::Max() // means that there are no known limits. - base::TimeTicks GetTimeTasksCanRunUntil( - base::sequence_manager::TaskQueue* queue, - base::TimeTicks now, - bool is_wake_up) const; - - void MaybeDeleteQueueMetadata(TaskQueueMap::iterator it); + base::TimeTicks GetTimeTasksCanRunUntil(base::TimeTicks now) const; - void UpdateQueueSchedulingLifecycleStateInternal( - base::TimeTicks now, - base::sequence_manager::TaskQueue* queue, - bool is_wake_up); + // See GetNextAllowedWakeUp(). + absl::optional<base::sequence_manager::DelayedWakeUp> + GetNextAllowedWakeUpImpl( + base::sequence_manager::LazyNow* lazy_now, + absl::optional<base::sequence_manager::DelayedWakeUp> next_wake_up, + bool has_ready_task); - absl::optional<QueueBlockType> GetQueueBlockType( - base::TimeTicks now, - base::sequence_manager::TaskQueue* queue); + // TaskQueue::Throttler implementation: + absl::optional<base::sequence_manager::DelayedWakeUp> GetNextAllowedWakeUp( + base::sequence_manager::LazyNow* lazy_now, + absl::optional<base::sequence_manager::DelayedWakeUp> next_wake_up, + bool has_ready_task) override; + void OnWakeUp(base::sequence_manager::LazyNow* lazy_now) override; + void OnHasImmediateTask() override; - TaskQueueMap queue_details_; - base::RepeatingCallback<void(base::sequence_manager::TaskQueue*, - base::TimeTicks)> - forward_immediate_work_callback_; - scoped_refptr<base::SingleThreadTaskRunner> control_task_runner_; - ThreadSchedulerImpl* thread_scheduler_; // NOT OWNED - TraceableVariableController* tracing_controller_; // NOT OWNED - const base::TickClock* tick_clock_; // NOT OWNED - std::unique_ptr<ThrottledTimeDomain> time_domain_; + void UpdateFence(base::TimeTicks now); - CancelableClosureHolder pump_throttled_tasks_closure_; - absl::optional<base::TimeTicks> pending_pump_throttled_tasks_runtime_; - bool allow_throttling_; - - HashMap<BudgetPool*, std::unique_ptr<BudgetPool>> budget_pools_; - - base::WeakPtrFactory<TaskQueueThrottler> weak_factory_{this}; + void DisableThrottling(); - DISALLOW_COPY_AND_ASSIGN(TaskQueueThrottler); + base::sequence_manager::TaskQueue* const task_queue_; + size_t throttling_ref_count_ = 0; + HashSet<BudgetPool*> budget_pools_; + const base::TickClock* tick_clock_; }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc index ed9b0ab008d..0cad303e888 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc @@ -10,7 +10,6 @@ #include "base/bind.h" #include "base/callback.h" -#include "base/macros.h" #include "base/task/sequence_manager/sequence_manager.h" #include "base/task/sequence_manager/test/sequence_manager_for_test.h" #include "base/test/bind.h" @@ -18,9 +17,9 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h" +#include "third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h" +#include "third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h" #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/wtf/deque.h" namespace blink { @@ -35,16 +34,6 @@ using base::sequence_manager::LazyNow; using base::sequence_manager::TaskQueue; using testing::ElementsAre; -class MainThreadSchedulerImplForTest : public MainThreadSchedulerImpl { - public: - using MainThreadSchedulerImpl::ControlTaskQueue; - - MainThreadSchedulerImplForTest( - std::unique_ptr<base::sequence_manager::SequenceManager> manager, - absl::optional<base::Time> initial_virtual_time) - : MainThreadSchedulerImpl(std::move(manager), initial_virtual_time) {} -}; - void NopTask() {} void AddOneTask(size_t* count) { @@ -71,41 +60,65 @@ class TaskQueueThrottlerTest : public testing::Test { public: TaskQueueThrottlerTest() : test_task_runner_(base::MakeRefCounted<TestMockTimeTaskRunner>()) {} + TaskQueueThrottlerTest(const TaskQueueThrottlerTest&) = delete; + TaskQueueThrottlerTest& operator=(const TaskQueueThrottlerTest&) = delete; ~TaskQueueThrottlerTest() override = default; void SetUp() override { // A null clock triggers some assertions. test_task_runner_->AdvanceMockTickClock( base::TimeDelta::FromMilliseconds(5)); + start_time_ = test_task_runner_->NowTicks(); - scheduler_ = std::make_unique<MainThreadSchedulerImplForTest>( - base::sequence_manager::SequenceManagerForTest::Create( - nullptr, test_task_runner_, GetTickClock()), - absl::nullopt); - task_queue_throttler_ = scheduler_->task_queue_throttler(); + sequence_manager_ = base::sequence_manager::SequenceManagerForTest::Create( + nullptr, test_task_runner_, GetTickClock()); wake_up_budget_pool_ = - task_queue_throttler_->CreateWakeUpBudgetPool("Wake Up Budget Pool"); + std::make_unique<WakeUpBudgetPool>("Wake Up Budget Pool"); wake_up_budget_pool_->SetWakeUpDuration(base::TimeDelta()); - timer_queue_ = scheduler_->NewTaskQueue( - MainThreadTaskQueue::QueueCreationParams( - MainThreadTaskQueue::QueueType::kFrameThrottleable) - .SetCanBeThrottled(true)); - wake_up_budget_pool_->AddQueue(base::TimeTicks(), - timer_queue_->GetTaskQueueForTest()); - timer_task_runner_ = timer_queue_->GetTaskRunnerWithDefaultTaskType(); + wake_up_budget_pool_->SetWakeUpInterval(base::TimeTicks(), + base::TimeDelta::FromSeconds(1)); + + timer_queue_ = CreateTaskQueue("Timer queue"); + task_queue_throttler_ = CreateThrottlerForTaskQueue(timer_queue_.get()); + + wake_up_budget_pool_->AddThrottler(test_task_runner_->NowTicks(), + task_queue_throttler_.get()); + timer_task_runner_ = timer_queue_->task_runner(); } void TearDown() override { - wake_up_budget_pool_->RemoveQueue(test_task_runner_->NowTicks(), - timer_queue_->GetTaskQueueForTest()); - wake_up_budget_pool_->Close(); - scheduler_->Shutdown(); - scheduler_.reset(); + wake_up_budget_pool_->RemoveThrottler(test_task_runner_->NowTicks(), + task_queue_throttler_.get()); + timer_queue_->ShutdownTaskQueue(); + } + + scoped_refptr<base::sequence_manager::TaskQueue> CreateTaskQueue( + const char* name) { + return sequence_manager_->CreateTaskQueue( + base::sequence_manager::TaskQueue::Spec(name).SetDelayedFencesAllowed( + true)); + } + + std::unique_ptr<TaskQueueThrottler> CreateThrottlerForTaskQueue( + base::sequence_manager::TaskQueue* queue) { + auto throttler = std::make_unique<TaskQueueThrottler>( + queue, test_task_runner_->GetMockTickClock()); + queue->SetOnTaskCompletedHandler(base::BindRepeating( + [](TaskQueueThrottler* throttler, + const base::sequence_manager::Task& task, + TaskQueue::TaskTiming* task_timing, + base::sequence_manager::LazyNow* lazy_now) { + task_timing->RecordTaskEnd(lazy_now); + throttler->OnTaskRunTimeReported(task_timing->start_time(), + task_timing->end_time()); + }, + base::Unretained(throttler.get()))); + return throttler; } void ExpectThrottled(scoped_refptr<TaskQueue> timer_queue) { size_t count = 0; - timer_queue->task_runner()->PostDelayedTask( + timer_task_runner_->PostDelayedTask( FROM_HERE, base::BindOnce(&RunTenTimesTask, &count, timer_queue), base::TimeDelta::FromMilliseconds(1)); @@ -119,7 +132,7 @@ class TaskQueueThrottlerTest : public testing::Test { void ExpectUnthrottled(scoped_refptr<TaskQueue> timer_queue) { size_t count = 0; - timer_queue->task_runner()->PostDelayedTask( + timer_task_runner_->PostDelayedTask( FROM_HERE, base::BindOnce(&RunTenTimesTask, &count, timer_queue), base::TimeDelta::FromMilliseconds(1)); @@ -140,27 +153,24 @@ class TaskQueueThrottlerTest : public testing::Test { test_task_runner_->NowTicks()); } - TaskQueue* GetTaskQueue(MainThreadTaskQueue* queue) { - return queue->GetTaskQueueForTest(); - } - protected: virtual const base::TickClock* GetTickClock() const { return test_task_runner_->GetMockTickClock(); } + base::TimeTicks start_time_; + scoped_refptr<TestMockTimeTaskRunner> test_task_runner_; - std::unique_ptr<MainThreadSchedulerImplForTest> scheduler_; + std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager_; // A queue that is subject to |wake_up_budget_pool_|. - scoped_refptr<MainThreadTaskQueue> timer_queue_; + scoped_refptr<base::sequence_manager::TaskQueue> timer_queue_; + std::unique_ptr<TaskQueueThrottler> task_queue_throttler_; scoped_refptr<base::SingleThreadTaskRunner> timer_task_runner_; - TaskQueueThrottler* task_queue_throttler_ = nullptr; - WakeUpBudgetPool* wake_up_budget_pool_ = nullptr; + std::unique_ptr<WakeUpBudgetPool> wake_up_budget_pool_; - private: - DISALLOW_COPY_AND_ASSIGN(TaskQueueThrottlerTest); + TraceableVariableController tracing_controller_; }; // Advances mock clock every time we call NowTicks() from the scheduler. @@ -191,6 +201,10 @@ class TaskQueueThrottlerWithAutoAdvancingTimeTest public: TaskQueueThrottlerWithAutoAdvancingTimeTest() : proxy_clock_(test_task_runner_) {} + TaskQueueThrottlerWithAutoAdvancingTimeTest( + const TaskQueueThrottlerWithAutoAdvancingTimeTest&) = delete; + TaskQueueThrottlerWithAutoAdvancingTimeTest& operator=( + const TaskQueueThrottlerWithAutoAdvancingTimeTest&) = delete; ~TaskQueueThrottlerWithAutoAdvancingTimeTest() override = default; void SetUp() override { @@ -207,73 +221,12 @@ class TaskQueueThrottlerWithAutoAdvancingTimeTest private: AutoAdvancingProxyClock proxy_clock_; - - DISALLOW_COPY_AND_ASSIGN(TaskQueueThrottlerWithAutoAdvancingTimeTest); }; INSTANTIATE_TEST_SUITE_P(All, TaskQueueThrottlerWithAutoAdvancingTimeTest, testing::Bool()); -TEST_F(TaskQueueThrottlerTest, ThrottledTasksReportRealTime) { - EXPECT_EQ(GetTaskQueue(timer_queue_.get())->GetTimeDomain()->Now(), - test_task_runner_->NowTicks()); - - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - EXPECT_EQ(GetTaskQueue(timer_queue_.get())->GetTimeDomain()->Now(), - test_task_runner_->NowTicks()); - - test_task_runner_->AdvanceMockTickClock( - base::TimeDelta::FromMilliseconds(250)); - // Make sure the throttled time domain's Now() reports the same as the - // underlying clock. - EXPECT_EQ(GetTaskQueue(timer_queue_.get())->GetTimeDomain()->Now(), - test_task_runner_->NowTicks()); -} - -TEST_F(TaskQueueThrottlerTest, AlignedThrottledRunTime) { - EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0), - TaskQueueThrottler::AlignedThrottledRunTime( - base::TimeTicks() + base::TimeDelta::FromSecondsD(0.0))); - - EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0), - TaskQueueThrottler::AlignedThrottledRunTime( - base::TimeTicks() + base::TimeDelta::FromSecondsD(0.1))); - - EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0), - TaskQueueThrottler::AlignedThrottledRunTime( - base::TimeTicks() + base::TimeDelta::FromSecondsD(0.2))); - - EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0), - TaskQueueThrottler::AlignedThrottledRunTime( - base::TimeTicks() + base::TimeDelta::FromSecondsD(0.5))); - - EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0), - TaskQueueThrottler::AlignedThrottledRunTime( - base::TimeTicks() + base::TimeDelta::FromSecondsD(0.8))); - - EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0), - TaskQueueThrottler::AlignedThrottledRunTime( - base::TimeTicks() + base::TimeDelta::FromSecondsD(0.9))); - - EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(2.0), - TaskQueueThrottler::AlignedThrottledRunTime( - base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0))); - - EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(2.0), - TaskQueueThrottler::AlignedThrottledRunTime( - base::TimeTicks() + base::TimeDelta::FromSecondsD(1.1))); - - EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(9.0), - TaskQueueThrottler::AlignedThrottledRunTime( - base::TimeTicks() + base::TimeDelta::FromSecondsD(8.0))); - - EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(9.0), - TaskQueueThrottler::AlignedThrottledRunTime( - base::TimeTicks() + base::TimeDelta::FromSecondsD(8.1))); -} - namespace { // Round up time to milliseconds to deal with autoadvancing time. @@ -324,25 +277,21 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TimerAlignment) { FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_), base::TimeDelta::FromMilliseconds(8300.0)); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); test_task_runner_->FastForwardUntilNoTasksRemain(); // Times are aligned to a multiple of 1000 milliseconds. - EXPECT_THAT( - run_times, - ElementsAre( - base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000.0), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000.0), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(2000.0), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(9000.0))); + EXPECT_THAT(run_times, + ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1), + base::TimeTicks() + base::TimeDelta::FromSeconds(1), + base::TimeTicks() + base::TimeDelta::FromSeconds(2), + base::TimeTicks() + base::TimeDelta::FromSeconds(9))); } TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TimerAlignment_Unthrottled) { Vector<base::TimeTicks> run_times; - base::TimeTicks start_time = test_task_runner_->NowTicks(); timer_task_runner_->PostDelayedTask( FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_), base::TimeDelta::FromMilliseconds(200.0)); @@ -359,124 +308,49 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_), base::TimeDelta::FromMilliseconds(8300.0)); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - task_queue_throttler_->DecreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); + task_queue_throttler_->DecreaseThrottleRefCount(); test_task_runner_->FastForwardUntilNoTasksRemain(); // Times are not aligned. EXPECT_THAT( run_times, - ElementsAre(RoundTimeToMilliseconds( - start_time + base::TimeDelta::FromMilliseconds(200.0)), - RoundTimeToMilliseconds( - start_time + base::TimeDelta::FromMilliseconds(800.0)), - RoundTimeToMilliseconds( - start_time + base::TimeDelta::FromMilliseconds(1200.0)), - RoundTimeToMilliseconds( - start_time + base::TimeDelta::FromMilliseconds(8300.0)))); + ElementsAre( + RoundTimeToMilliseconds(start_time_ + + base::TimeDelta::FromMilliseconds(200.0)), + RoundTimeToMilliseconds(start_time_ + + base::TimeDelta::FromMilliseconds(800.0)), + RoundTimeToMilliseconds(start_time_ + + base::TimeDelta::FromMilliseconds(1200.0)), + RoundTimeToMilliseconds(start_time_ + + base::TimeDelta::FromMilliseconds(8300.0)))); } TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, Refcount) { - ExpectUnthrottled(GetTaskQueue(timer_queue_.get())); - - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - ExpectThrottled(GetTaskQueue(timer_queue_.get())); + ExpectUnthrottled(timer_queue_.get()); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - ExpectThrottled(GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); + ExpectThrottled(timer_queue_.get()); - task_queue_throttler_->DecreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - ExpectThrottled(GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); + ExpectThrottled(timer_queue_.get()); - task_queue_throttler_->DecreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - ExpectUnthrottled(GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->DecreaseThrottleRefCount(); + ExpectThrottled(timer_queue_.get()); - // Should be a NOP. - task_queue_throttler_->DecreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - ExpectUnthrottled(GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->DecreaseThrottleRefCount(); + ExpectUnthrottled(timer_queue_.get()); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - ExpectThrottled(GetTaskQueue(timer_queue_.get())); -} - -TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, - ThrotlingAnEmptyQueueDoesNotPostPumpThrottledTasksLocked) { - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - - EXPECT_TRUE(GetTaskQueue(scheduler_->ControlTaskQueue().get())->IsEmpty()); -} - -TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, - OnTimeDomainHasImmediateWork_EnabledQueue) { - task_queue_throttler_->OnQueueNextWakeUpChanged( - GetTaskQueue(timer_queue_.get()), base::TimeTicks()); - // Check PostPumpThrottledTasksLocked was called. - EXPECT_FALSE(GetTaskQueue(scheduler_->ControlTaskQueue().get())->IsEmpty()); -} - -TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, - OnTimeDomainHasImmediateWork_DisabledQueue) { - std::unique_ptr<TaskQueue::QueueEnabledVoter> voter = - GetTaskQueue(timer_queue_.get())->CreateQueueEnabledVoter(); - voter->SetVoteToEnable(false); - - task_queue_throttler_->OnQueueNextWakeUpChanged( - GetTaskQueue(timer_queue_.get()), base::TimeTicks()); - // Check PostPumpThrottledTasksLocked was not called. - EXPECT_TRUE(GetTaskQueue(scheduler_->ControlTaskQueue().get())->IsEmpty()); -} - -TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, - ThrottlingADisabledQueueDoesNotPostPumpThrottledTasks) { - timer_task_runner_->PostTask(FROM_HERE, base::BindOnce(&NopTask)); - - std::unique_ptr<TaskQueue::QueueEnabledVoter> voter = - GetTaskQueue(timer_queue_.get())->CreateQueueEnabledVoter(); - voter->SetVoteToEnable(false); - - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - EXPECT_TRUE(GetTaskQueue(scheduler_->ControlTaskQueue().get())->IsEmpty()); - - // Enabling it should trigger a call to PostPumpThrottledTasksLocked. - voter->SetVoteToEnable(true); - EXPECT_FALSE(GetTaskQueue(scheduler_->ControlTaskQueue().get())->IsEmpty()); -} - -TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, - ThrottlingADisabledQueueDoesNotPostPumpThrottledTasks_DelayedTask) { - timer_task_runner_->PostDelayedTask(FROM_HERE, base::BindOnce(&NopTask), - base::TimeDelta::FromMilliseconds(1)); - - std::unique_ptr<TaskQueue::QueueEnabledVoter> voter = - GetTaskQueue(timer_queue_.get())->CreateQueueEnabledVoter(); - voter->SetVoteToEnable(false); - - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - EXPECT_TRUE(GetTaskQueue(scheduler_->ControlTaskQueue().get())->IsEmpty()); - - // Enabling it should trigger a call to PostPumpThrottledTasksLocked. - voter->SetVoteToEnable(true); - EXPECT_FALSE(GetTaskQueue(scheduler_->ControlTaskQueue().get())->IsEmpty()); + task_queue_throttler_->IncreaseThrottleRefCount(); + ExpectThrottled(timer_queue_.get()); } TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, WakeUpForNonDelayedTask) { Vector<base::TimeTicks> run_times; // Nothing is posted on timer_queue_ so PumpThrottledTasks will not tick. - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); // Posting a task should trigger the pump. timer_task_runner_->PostTask( @@ -492,8 +366,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, WakeUpForDelayedTask) { Vector<base::TimeTicks> run_times; // Nothing is posted on timer_queue_ so PumpThrottledTasks will not tick. - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); // Posting a task should trigger the pump. timer_task_runner_->PostDelayedTask( @@ -508,8 +381,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, WakeUpForDelayedTask) { TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, SingleThrottledTaskPumpedAndRunWithNoExtraneousMessageLoopTasks) { - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); base::TimeDelta delay(base::TimeDelta::FromMilliseconds(10)); timer_task_runner_->PostDelayedTask(FROM_HERE, base::BindOnce(&NopTask), @@ -519,8 +391,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, SingleFutureThrottledTaskPumpedAndRunWithNoExtraneousMessageLoopTasks) { - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); base::TimeDelta delay(base::TimeDelta::FromSecondsD(15.5)); timer_task_runner_->PostDelayedTask(FROM_HERE, base::BindOnce(&NopTask), @@ -530,8 +401,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TwoFutureThrottledTaskPumpedAndRunWithNoExtraneousMessageLoopTasks) { - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); Vector<base::TimeTicks> run_times; base::TimeDelta delay(base::TimeDelta::FromSecondsD(15.5)); @@ -560,8 +430,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TaskDelayIsBasedOnRealTime) { Vector<base::TimeTicks> run_times; - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); // Post an initial task that should run at the first aligned time period. timer_task_runner_->PostDelayedTask( @@ -582,87 +451,32 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, test_task_runner_->FastForwardUntilNoTasksRemain(); - EXPECT_THAT( - run_times, - ElementsAre( - base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000.0), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000.0))); -} - -TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TaskQueueDisabledTillPump) { - size_t count = 0; - timer_task_runner_->PostTask(FROM_HERE, base::BindOnce(&AddOneTask, &count)); - - EXPECT_FALSE(IsQueueBlocked(GetTaskQueue(timer_queue_.get()))); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - EXPECT_TRUE(IsQueueBlocked(GetTaskQueue(timer_queue_.get()))); - - test_task_runner_->FastForwardUntilNoTasksRemain(); // Wait until the pump. - EXPECT_EQ(1u, count); // The task got run. + EXPECT_THAT(run_times, + ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1), + base::TimeTicks() + base::TimeDelta::FromSeconds(3))); } TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, DoubleIncrementDoubleDecrement) { - timer_task_runner_->PostTask(FROM_HERE, base::BindOnce(&NopTask)); - - EXPECT_FALSE(IsQueueBlocked(GetTaskQueue(timer_queue_.get()))); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - EXPECT_TRUE(IsQueueBlocked(GetTaskQueue(timer_queue_.get()))); - task_queue_throttler_->DecreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - task_queue_throttler_->DecreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - EXPECT_FALSE(IsQueueBlocked(GetTaskQueue(timer_queue_.get()))); + EXPECT_FALSE(IsQueueBlocked(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); + task_queue_throttler_->IncreaseThrottleRefCount(); + EXPECT_TRUE(IsQueueBlocked(timer_queue_.get())); + task_queue_throttler_->DecreaseThrottleRefCount(); + task_queue_throttler_->DecreaseThrottleRefCount(); + EXPECT_FALSE(IsQueueBlocked(timer_queue_.get())); } -TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, - EnableVirtualTimeThenIncrement) { - timer_task_runner_->PostTask(FROM_HERE, base::BindOnce(&NopTask)); - - scheduler_->EnableVirtualTime( - MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE); - EXPECT_EQ(GetTaskQueue(timer_queue_.get())->GetTimeDomain(), - scheduler_->GetVirtualTimeDomain()); - - EXPECT_FALSE(IsQueueBlocked(GetTaskQueue(timer_queue_.get()))); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - EXPECT_FALSE(IsQueueBlocked(GetTaskQueue(timer_queue_.get()))); - EXPECT_EQ(GetTaskQueue(timer_queue_.get())->GetTimeDomain(), - scheduler_->GetVirtualTimeDomain()); -} - -TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, - IncrementThenEnableVirtualTime) { - timer_task_runner_->PostTask(FROM_HERE, base::BindOnce(&NopTask)); - - EXPECT_FALSE(IsQueueBlocked(GetTaskQueue(timer_queue_.get()))); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - EXPECT_TRUE(IsQueueBlocked(GetTaskQueue(timer_queue_.get()))); - - scheduler_->EnableVirtualTime( - MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE); - EXPECT_FALSE(IsQueueBlocked(GetTaskQueue(timer_queue_.get()))); - EXPECT_EQ(GetTaskQueue(timer_queue_.get())->GetTimeDomain(), - scheduler_->GetVirtualTimeDomain()); -} - -TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TimeBasedThrottling) { +TEST_F(TaskQueueThrottlerTest, TimeBasedThrottling) { Vector<base::TimeTicks> run_times; - CPUTimeBudgetPool* pool = - task_queue_throttler_->CreateCPUTimeBudgetPool("test"); + std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>( + "test", &tracing_controller_, test_task_runner_->NowTicks()); pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1); - pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get())); + pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get()); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); // Submit two tasks. They should be aligned, and second one should be // throttled. @@ -677,12 +491,15 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TimeBasedThrottling) { test_task_runner_->FastForwardUntilNoTasksRemain(); - EXPECT_THAT(run_times, - ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1), - base::TimeTicks() + base::TimeDelta::FromSeconds(3))); + // The 1st task runs when allowed by the WakeUpBudgetPool. The 2nd task + // runs when the CPU budget used by the 2nd task has recovered. + EXPECT_THAT( + run_times, + ElementsAre(TimeTicks() + base::TimeDelta::FromSeconds(1), + start_time_ + base::TimeDelta::FromMilliseconds(2500))); - pool->RemoveQueue(test_task_runner_->NowTicks(), - GetTaskQueue(timer_queue_.get())); + pool->RemoveThrottler(test_task_runner_->NowTicks(), + task_queue_throttler_.get()); run_times.clear(); // Queue was removed from CPUTimeBudgetPool, only timer alignment should be @@ -700,27 +517,24 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TimeBasedThrottling) { EXPECT_THAT( run_times, - ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(4000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(4250))); + ElementsAre(TimeTicks() + base::TimeDelta::FromMilliseconds(3000), + TimeTicks() + base::TimeDelta::FromMilliseconds(3250))); - task_queue_throttler_->DecreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - pool->Close(); + task_queue_throttler_->DecreaseThrottleRefCount(); } TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, EnableAndDisableCPUTimeBudgetPool) { Vector<base::TimeTicks> run_times; - CPUTimeBudgetPool* pool = - task_queue_throttler_->CreateCPUTimeBudgetPool("test"); + std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>( + "test", &tracing_controller_, test_task_runner_->NowTicks()); EXPECT_TRUE(pool->IsThrottlingEnabled()); pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1); - pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get())); + pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get()); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); // Post an expensive task. Pool is now throttled. timer_task_runner_->PostDelayedTask( @@ -763,30 +577,26 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, test_task_runner_->FastForwardUntilNoTasksRemain(); - EXPECT_THAT(run_times, ElementsAre(base::TimeTicks() + - base::TimeDelta::FromMilliseconds(4000))); + EXPECT_THAT(run_times, ElementsAre(start_time_ + + base::TimeDelta::FromMilliseconds(3500))); run_times.clear(); - task_queue_throttler_->DecreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->DecreaseThrottleRefCount(); - pool->RemoveQueue(test_task_runner_->NowTicks(), - GetTaskQueue(timer_queue_.get())); - pool->Close(); + pool->RemoveThrottler(test_task_runner_->NowTicks(), + task_queue_throttler_.get()); } -TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, - ImmediateTasksTimeBudgetThrottling) { +TEST_F(TaskQueueThrottlerTest, ImmediateTasksTimeBudgetThrottling) { Vector<base::TimeTicks> run_times; - CPUTimeBudgetPool* pool = - task_queue_throttler_->CreateCPUTimeBudgetPool("test"); + std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>( + "test", &tracing_controller_, test_task_runner_->NowTicks()); pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1); - pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get())); + pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get()); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); // Submit two tasks. They should be aligned, and second one should be // throttled. @@ -799,12 +609,13 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, test_task_runner_->FastForwardUntilNoTasksRemain(); - EXPECT_THAT(run_times, - ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1), - base::TimeTicks() + base::TimeDelta::FromSeconds(3))); + EXPECT_THAT( + run_times, + ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000), + start_time_ + base::TimeDelta::FromMilliseconds(2500))); - pool->RemoveQueue(test_task_runner_->NowTicks(), - GetTaskQueue(timer_queue_.get())); + pool->RemoveThrottler(test_task_runner_->NowTicks(), + task_queue_throttler_.get()); run_times.clear(); // Queue was removed from CPUTimeBudgetPool, only timer alignment should be @@ -820,63 +631,57 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, EXPECT_THAT( run_times, - ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(4000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(4250))); + ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000), + base::TimeTicks() + base::TimeDelta::FromMilliseconds(3250))); - task_queue_throttler_->DecreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - pool->Close(); + task_queue_throttler_->DecreaseThrottleRefCount(); } TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TwoQueuesTimeBudgetThrottling) { Vector<base::TimeTicks> run_times; - scoped_refptr<MainThreadTaskQueue> second_queue = scheduler_->NewTaskQueue( - MainThreadTaskQueue::QueueCreationParams( - MainThreadTaskQueue::QueueType::kFrameThrottleable) - .SetCanBeThrottled(true)); + scoped_refptr<base::sequence_manager::TaskQueue> second_queue = + sequence_manager_->CreateTaskQueue( + base::sequence_manager::TaskQueue::Spec("Second queue") + .SetDelayedFencesAllowed(true)); + auto second_queue_throttler = CreateThrottlerForTaskQueue(second_queue.get()); - CPUTimeBudgetPool* pool = - task_queue_throttler_->CreateCPUTimeBudgetPool("test"); + std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>( + "test", &tracing_controller_, test_task_runner_->NowTicks()); pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1); - pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get())); - pool->AddQueue(base::TimeTicks(), GetTaskQueue(second_queue.get())); - wake_up_budget_pool_->AddQueue(base::TimeTicks(), - GetTaskQueue(second_queue.get())); + pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get()); + pool->AddThrottler(base::TimeTicks(), second_queue_throttler.get()); + wake_up_budget_pool_->AddThrottler(base::TimeTicks(), + second_queue_throttler.get()); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(second_queue.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); + second_queue_throttler->IncreaseThrottleRefCount(); timer_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_)); - second_queue->GetTaskRunnerWithDefaultTaskType()->PostTask( + second_queue->task_runner()->PostTask( FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_)); test_task_runner_->FastForwardUntilNoTasksRemain(); - EXPECT_THAT(run_times, - ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1), - base::TimeTicks() + base::TimeDelta::FromSeconds(3))); - - task_queue_throttler_->DecreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - task_queue_throttler_->DecreaseThrottleRefCount( - GetTaskQueue(second_queue.get())); + EXPECT_THAT( + run_times, + ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000), + start_time_ + base::TimeDelta::FromMilliseconds(2500))); - pool->RemoveQueue(test_task_runner_->NowTicks(), - GetTaskQueue(timer_queue_.get())); - pool->RemoveQueue(test_task_runner_->NowTicks(), - GetTaskQueue(second_queue.get())); - wake_up_budget_pool_->RemoveQueue(test_task_runner_->NowTicks(), - GetTaskQueue(second_queue.get())); + task_queue_throttler_->DecreaseThrottleRefCount(); + second_queue_throttler->DecreaseThrottleRefCount(); - pool->Close(); + pool->RemoveThrottler(test_task_runner_->NowTicks(), + task_queue_throttler_.get()); + pool->RemoveThrottler(test_task_runner_->NowTicks(), + second_queue_throttler.get()); + wake_up_budget_pool_->RemoveThrottler(test_task_runner_->NowTicks(), + second_queue_throttler.get()); } TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, @@ -884,15 +689,14 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, Vector<base::TimeTicks> run_times; LazyNow lazy_now(test_task_runner_->GetMockTickClock()); - CPUTimeBudgetPool* pool = - task_queue_throttler_->CreateCPUTimeBudgetPool("test"); + std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>( + "test", &tracing_controller_, test_task_runner_->NowTicks()); pool->SetTimeBudgetRecoveryRate(lazy_now.Now(), 0.1); pool->DisableThrottling(&lazy_now); - pool->AddQueue(lazy_now.Now(), GetTaskQueue(timer_queue_.get())); + pool->AddThrottler(lazy_now.Now(), task_queue_throttler_.get()); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); timer_task_runner_->PostDelayedTask( FROM_HERE, @@ -915,15 +719,15 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TimeBudgetThrottlingDoesNotAffectUnthrottledQueues) { Vector<base::TimeTicks> run_times; - CPUTimeBudgetPool* pool = - task_queue_throttler_->CreateCPUTimeBudgetPool("test"); + std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>( + "test", &tracing_controller_, test_task_runner_->NowTicks()); pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1); LazyNow lazy_now(test_task_runner_->GetMockTickClock()); pool->DisableThrottling(&lazy_now); - pool->AddQueue(test_task_runner_->NowTicks(), - GetTaskQueue(timer_queue_.get())); + pool->AddThrottler(test_task_runner_->NowTicks(), + task_queue_throttler_.get()); timer_task_runner_->PostDelayedTask( FROM_HERE, @@ -938,24 +742,23 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, EXPECT_THAT( run_times, - ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(105), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(355))); + ElementsAre(start_time_ + base::TimeDelta::FromMilliseconds(100), + start_time_ + base::TimeDelta::FromMilliseconds(350))); } TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, MaxThrottlingDelay) { Vector<base::TimeTicks> run_times; - CPUTimeBudgetPool* pool = - task_queue_throttler_->CreateCPUTimeBudgetPool("test"); + std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>( + "test", &tracing_controller_, test_task_runner_->NowTicks()); pool->SetMaxThrottlingDelay(base::TimeTicks(), base::TimeDelta::FromMinutes(1)); pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.001); - pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get())); + pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get()); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); for (int i = 0; i < 5; ++i) { timer_task_runner_->PostDelayedTask( @@ -968,32 +771,33 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, MaxThrottlingDelay) { EXPECT_THAT( run_times, - ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1), - base::TimeTicks() + base::TimeDelta::FromSeconds(62), - base::TimeTicks() + base::TimeDelta::FromSeconds(123), - base::TimeTicks() + base::TimeDelta::FromSeconds(184), - base::TimeTicks() + base::TimeDelta::FromSeconds(245))); + ElementsAre( + base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000), + base::TimeTicks() + base::TimeDelta::FromMilliseconds(61250), + base::TimeTicks() + base::TimeDelta::FromMilliseconds(121500), + base::TimeTicks() + base::TimeDelta::FromMilliseconds(181750), + base::TimeTicks() + base::TimeDelta::FromMilliseconds(242000))); } TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, EnableAndDisableThrottling) { Vector<base::TimeTicks> run_times; - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); timer_task_runner_->PostDelayedTask( FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_), base::TimeDelta::FromMilliseconds(200)); - test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(295)); + test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(300)); // Disable throttling - task should run immediately. - task_queue_throttler_->DisableThrottling(); + LazyNow lazy_now_1(test_task_runner_->GetMockTickClock()); + wake_up_budget_pool_->DisableThrottling(&lazy_now_1); test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(200)); - EXPECT_THAT(run_times, ElementsAre(base::TimeTicks() + + EXPECT_THAT(run_times, ElementsAre(start_time_ + base::TimeDelta::FromMilliseconds(300))); run_times.clear(); @@ -1014,8 +818,8 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, EXPECT_THAT( run_times, - ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(900), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(1200))); + ElementsAre(start_time_ + base::TimeDelta::FromMilliseconds(900), + start_time_ + base::TimeDelta::FromMilliseconds(1200))); run_times.clear(); // Schedule a task at 1500ms. It should be throttled because of enabled @@ -1027,7 +831,8 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(100)); // Throttling is enabled and new task should be aligned. - task_queue_throttler_->EnableThrottling(); + LazyNow lazy_now_2(test_task_runner_->GetMockTickClock()); + wake_up_budget_pool_->EnableThrottling(&lazy_now_2); test_task_runner_->FastForwardUntilNoTasksRemain(); @@ -1035,21 +840,20 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, base::TimeDelta::FromMilliseconds(2000))); } -TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, ReportThrottling) { +TEST_F(TaskQueueThrottlerTest, ReportThrottling) { Vector<base::TimeTicks> run_times; Vector<base::TimeDelta> reported_throttling_times; - CPUTimeBudgetPool* pool = - task_queue_throttler_->CreateCPUTimeBudgetPool("test"); + std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>( + "test", &tracing_controller_, test_task_runner_->NowTicks()); pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1); - pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get())); + pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get()); pool->SetReportingCallback( base::BindRepeating(&RecordThrottling, &reported_throttling_times)); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); timer_task_runner_->PostDelayedTask( FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_), @@ -1065,35 +869,34 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, ReportThrottling) { test_task_runner_->FastForwardUntilNoTasksRemain(); - EXPECT_THAT(run_times, - ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1), - base::TimeTicks() + base::TimeDelta::FromSeconds(1), - base::TimeTicks() + base::TimeDelta::FromSeconds(3))); + EXPECT_THAT( + run_times, + ElementsAre(TimeTicks() + base::TimeDelta::FromSeconds(1), + TimeTicks() + base::TimeDelta::FromSeconds(1), + start_time_ + base::TimeDelta::FromMilliseconds(2500))); EXPECT_THAT(reported_throttling_times, - ElementsAre(base::TimeDelta::FromMilliseconds(1255), - base::TimeDelta::FromMilliseconds(1755))); + ElementsAre((start_time_ - TimeTicks()) + + base::TimeDelta::FromMilliseconds(1250), + base::TimeDelta::FromMilliseconds(2250))); - pool->RemoveQueue(test_task_runner_->NowTicks(), - GetTaskQueue(timer_queue_.get())); - task_queue_throttler_->DecreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - pool->Close(); + pool->RemoveThrottler(test_task_runner_->NowTicks(), + task_queue_throttler_.get()); + task_queue_throttler_->DecreaseThrottleRefCount(); } -TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, GrantAdditionalBudget) { +TEST_F(TaskQueueThrottlerTest, GrantAdditionalBudget) { Vector<base::TimeTicks> run_times; - CPUTimeBudgetPool* pool = - task_queue_throttler_->CreateCPUTimeBudgetPool("test"); + std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>( + "test", &tracing_controller_, test_task_runner_->NowTicks()); pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1); - pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get())); + pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get()); pool->GrantAdditionalBudget(base::TimeTicks(), base::TimeDelta::FromMilliseconds(500)); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); // Submit five tasks. First three will not be throttled because they have // budget to run. @@ -1108,76 +911,43 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, GrantAdditionalBudget) { EXPECT_THAT( run_times, - ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(1250), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(1500), - base::TimeTicks() + base::TimeDelta::FromSeconds(3), - base::TimeTicks() + base::TimeDelta::FromSeconds(6))); - - pool->RemoveQueue(test_task_runner_->NowTicks(), - GetTaskQueue(timer_queue_.get())); - task_queue_throttler_->DecreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + ElementsAre(TimeTicks() + base::TimeDelta::FromMilliseconds(1000), + TimeTicks() + base::TimeDelta::FromMilliseconds(1250), + TimeTicks() + base::TimeDelta::FromMilliseconds(1500), + start_time_ + base::TimeDelta::FromMilliseconds(2500), + start_time_ + base::TimeDelta::FromMilliseconds(5000))); + + pool->RemoveThrottler(test_task_runner_->NowTicks(), + task_queue_throttler_.get()); + task_queue_throttler_->DecreaseThrottleRefCount(); pool->Close(); } TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, - EnableAndDisableThrottlingAndTimeBudgets) { - // This test checks that if time budget pool is enabled when throttling - // is disabled, it does not throttle the queue. - Vector<base::TimeTicks> run_times; - - task_queue_throttler_->DisableThrottling(); - - CPUTimeBudgetPool* pool = - task_queue_throttler_->CreateCPUTimeBudgetPool("test"); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - - LazyNow lazy_now_1(test_task_runner_->GetMockTickClock()); - pool->DisableThrottling(&lazy_now_1); - - pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get())); - - test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(95)); - - LazyNow lazy_now_2(test_task_runner_->GetMockTickClock()); - pool->EnableThrottling(&lazy_now_2); - - timer_task_runner_->PostDelayedTask( - FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_), - base::TimeDelta::FromMilliseconds(200)); - - test_task_runner_->FastForwardUntilNoTasksRemain(); - - EXPECT_THAT(run_times, ElementsAre(base::TimeTicks() + - base::TimeDelta::FromMilliseconds(300))); -} - -TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, - AddQueueToBudgetPoolWhenThrottlingDisabled) { + AddQueueThrottlerToBudgetPoolWhenThrottlingDisabled) { // This test checks that a task queue is added to time budget pool // when throttling is disabled, is does not throttle queue. Vector<base::TimeTicks> run_times; - task_queue_throttler_->DisableThrottling(); + std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>( + "test", &tracing_controller_, test_task_runner_->NowTicks()); - CPUTimeBudgetPool* pool = - task_queue_throttler_->CreateCPUTimeBudgetPool("test"); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + LazyNow lazy_now_1(test_task_runner_->GetMockTickClock()); + wake_up_budget_pool_->DisableThrottling(&lazy_now_1); + pool->DisableThrottling(&lazy_now_1); + task_queue_throttler_->IncreaseThrottleRefCount(); - test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(95)); + test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(100)); timer_task_runner_->PostDelayedTask( FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_), base::TimeDelta::FromMilliseconds(200)); - pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get())); + pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get()); test_task_runner_->FastForwardUntilNoTasksRemain(); - EXPECT_THAT(run_times, ElementsAre(base::TimeTicks() + + EXPECT_THAT(run_times, ElementsAre(start_time_ + base::TimeDelta::FromMilliseconds(300))); } @@ -1185,25 +955,26 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, DisabledQueueThenEnabledQueue) { Vector<base::TimeTicks> run_times; - scoped_refptr<MainThreadTaskQueue> second_queue = scheduler_->NewTaskQueue( - MainThreadTaskQueue::QueueCreationParams( - MainThreadTaskQueue::QueueType::kFrameThrottleable) - .SetCanBeThrottled(true)); + scoped_refptr<base::sequence_manager::TaskQueue> second_queue = + sequence_manager_->CreateTaskQueue( + base::sequence_manager::TaskQueue::Spec("Second queue") + .SetDelayedFencesAllowed(true)); + auto second_queue_throttler = CreateThrottlerForTaskQueue(second_queue.get()); + wake_up_budget_pool_->AddThrottler(base::TimeTicks(), + second_queue_throttler.get()); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(second_queue.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); + second_queue_throttler->IncreaseThrottleRefCount(); timer_task_runner_->PostDelayedTask( FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_), base::TimeDelta::FromMilliseconds(100)); - second_queue->GetTaskRunnerWithDefaultTaskType()->PostDelayedTask( + second_queue->task_runner()->PostDelayedTask( FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_), base::TimeDelta::FromMilliseconds(200)); std::unique_ptr<TaskQueue::QueueEnabledVoter> voter = - GetTaskQueue(timer_queue_.get())->CreateQueueEnabledVoter(); + timer_queue_->CreateQueueEnabledVoter(); voter->SetVoteToEnable(false); test_task_runner_->AdvanceMockTickClock( @@ -1226,45 +997,50 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, run_times, ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000), base::TimeTicks() + base::TimeDelta::FromMilliseconds(2000))); + + wake_up_budget_pool_->RemoveThrottler(base::TimeTicks(), + second_queue_throttler.get()); } -TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TwoBudgetPools) { +TEST_F(TaskQueueThrottlerTest, TwoBudgetPools) { Vector<base::TimeTicks> run_times; - scoped_refptr<MainThreadTaskQueue> second_queue = scheduler_->NewTaskQueue( - MainThreadTaskQueue::QueueCreationParams( - MainThreadTaskQueue::QueueType::kFrameThrottleable) - .SetCanBeThrottled(true)); + std::unique_ptr<CPUTimeBudgetPool> pool1 = + std::make_unique<CPUTimeBudgetPool>("test", &tracing_controller_, + test_task_runner_->NowTicks()); + std::unique_ptr<CPUTimeBudgetPool> pool2 = + std::make_unique<CPUTimeBudgetPool>("test", &tracing_controller_, + test_task_runner_->NowTicks()); - wake_up_budget_pool_->AddQueue(base::TimeTicks(), - GetTaskQueue(second_queue.get())); + scoped_refptr<base::sequence_manager::TaskQueue> second_queue = + sequence_manager_->CreateTaskQueue( + base::sequence_manager::TaskQueue::Spec("Second queue") + .SetDelayedFencesAllowed(true)); + auto second_queue_throttler = CreateThrottlerForTaskQueue(second_queue.get()); + + wake_up_budget_pool_->AddThrottler(base::TimeTicks(), + second_queue_throttler.get()); - CPUTimeBudgetPool* pool1 = - task_queue_throttler_->CreateCPUTimeBudgetPool("test"); pool1->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1); - pool1->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get())); - pool1->AddQueue(base::TimeTicks(), GetTaskQueue(second_queue.get())); + pool1->AddThrottler(base::TimeTicks(), task_queue_throttler_.get()); + pool1->AddThrottler(base::TimeTicks(), second_queue_throttler.get()); - CPUTimeBudgetPool* pool2 = - task_queue_throttler_->CreateCPUTimeBudgetPool("test"); pool2->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.01); - pool2->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get())); + pool2->AddThrottler(base::TimeTicks(), task_queue_throttler_.get()); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(second_queue.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); + second_queue_throttler->IncreaseThrottleRefCount(); timer_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_)); - second_queue->GetTaskRunnerWithDefaultTaskType()->PostTask( + second_queue->task_runner()->PostTask( FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_)); timer_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_)); - second_queue->GetTaskRunnerWithDefaultTaskType()->PostTask( + second_queue->task_runner()->PostTask( FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_)); @@ -1272,20 +1048,19 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TwoBudgetPools) { EXPECT_THAT( run_times, - ElementsAre( - base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(6000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(26000))); + ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000), + start_time_ + base::TimeDelta::FromMilliseconds(2500), + start_time_ + base::TimeDelta::FromMilliseconds(5000), + start_time_ + base::TimeDelta::FromMilliseconds(25000))); - wake_up_budget_pool_->RemoveQueue(test_task_runner_->NowTicks(), - GetTaskQueue(second_queue.get())); + wake_up_budget_pool_->RemoveThrottler(test_task_runner_->NowTicks(), + second_queue_throttler.get()); } namespace { void RunChainedTask(Deque<base::TimeDelta> task_durations, - scoped_refptr<MainThreadTaskQueue> queue, + scoped_refptr<TaskQueue> queue, scoped_refptr<TestMockTimeTaskRunner> task_runner, Vector<base::TimeTicks>* run_times, base::TimeDelta delay) { @@ -1298,7 +1073,7 @@ void RunChainedTask(Deque<base::TimeDelta> task_durations, task_runner->AdvanceMockTickClock(task_durations.front()); task_durations.pop_front(); - queue->GetTaskRunnerWithDefaultTaskType()->PostDelayedTask( + queue->task_runner()->PostDelayedTask( FROM_HERE, base::BindOnce(&RunChainedTask, std::move(task_durations), queue, task_runner, run_times, delay), @@ -1312,8 +1087,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, base::TimeDelta::FromMilliseconds(10)); Vector<base::TimeTicks> run_times; - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); timer_task_runner_->PostDelayedTask( FROM_HERE, @@ -1343,8 +1117,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, base::TimeDelta::FromMilliseconds(10)); Vector<base::TimeTicks> run_times; - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); timer_task_runner_->PostDelayedTask( FROM_HERE, @@ -1377,8 +1150,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, base::TimeDelta::FromMilliseconds(10)); Vector<base::TimeTicks> run_times; - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); timer_task_runner_->PostDelayedTask( FROM_HERE, @@ -1409,31 +1181,29 @@ TEST_F(TaskQueueThrottlerTest, // of one-minute. wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(), base::TimeDelta::FromMinutes(1)); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - WakeUpBudgetPool* one_minute_pool = wake_up_budget_pool_; + task_queue_throttler_->IncreaseThrottleRefCount(); + WakeUpBudgetPool* one_minute_pool = wake_up_budget_pool_.get(); scoped_refptr<base::SingleThreadTaskRunner> one_minute_task_runner = timer_task_runner_; // Create another TaskQueue, throttled by another WakeUpBudgetPool with // a wake-up interval of two minutes. - WakeUpBudgetPool* two_minutes_pool = - task_queue_throttler_->CreateWakeUpBudgetPool( - "Two Minutes Interval Pool"); + std::unique_ptr<WakeUpBudgetPool> two_minutes_pool = + std::make_unique<WakeUpBudgetPool>("Two Minutes Interval Pool"); two_minutes_pool->SetWakeUpDuration(base::TimeDelta()); two_minutes_pool->SetWakeUpInterval(test_task_runner_->NowTicks(), base::TimeDelta::FromMinutes(2)); - scoped_refptr<MainThreadTaskQueue> two_minutes_queue = - scheduler_->NewTaskQueue( - MainThreadTaskQueue::QueueCreationParams( - MainThreadTaskQueue::QueueType::kFrameThrottleable) - .SetCanBeThrottled(true)); - two_minutes_pool->AddQueue(base::TimeTicks(), - GetTaskQueue(two_minutes_queue.get())); + scoped_refptr<base::sequence_manager::TaskQueue> two_minutes_queue = + sequence_manager_->CreateTaskQueue( + base::sequence_manager::TaskQueue::Spec("Second queue") + .SetDelayedFencesAllowed(true)); + auto two_minutes_queue_throttler = + CreateThrottlerForTaskQueue(two_minutes_queue.get()); + two_minutes_pool->AddThrottler(base::TimeTicks(), + two_minutes_queue_throttler.get()); scoped_refptr<base::SingleThreadTaskRunner> two_minutes_task_runner = - two_minutes_queue->GetTaskRunnerWithDefaultTaskType(); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(two_minutes_queue.get())); + two_minutes_queue->task_runner(); + two_minutes_queue_throttler->IncreaseThrottleRefCount(); // Post a task with a short delay to the first queue. constexpr base::TimeDelta kShortDelay = base::TimeDelta::FromSeconds(1); @@ -1475,39 +1245,36 @@ TEST_F(TaskQueueThrottlerTest, EXPECT_EQ(two_minutes_pool->last_wake_up_for_testing(), absl::nullopt); // Clean up. - two_minutes_pool->RemoveQueue(test_task_runner_->NowTicks(), - GetTaskQueue(two_minutes_queue.get())); - two_minutes_pool->Close(); + two_minutes_pool->RemoveThrottler(test_task_runner_->NowTicks(), + two_minutes_queue_throttler.get()); } TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottling_MultiplePoolsWithDifferentIntervals) { wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(), base::TimeDelta::FromMinutes(1)); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - WakeUpBudgetPool* one_minute_pool = wake_up_budget_pool_; + task_queue_throttler_->IncreaseThrottleRefCount(); + WakeUpBudgetPool* one_minute_pool = wake_up_budget_pool_.get(); scoped_refptr<base::SingleThreadTaskRunner> one_minute_task_runner = timer_task_runner_; // Create another TaskQueue, throttled by another WakeUpBudgetPool. - WakeUpBudgetPool* two_minutes_pool = - task_queue_throttler_->CreateWakeUpBudgetPool( - "Two Minutes Interval Pool"); + std::unique_ptr<WakeUpBudgetPool> two_minutes_pool = + std::make_unique<WakeUpBudgetPool>("Two Minutes Interval Pool"); two_minutes_pool->SetWakeUpDuration(base::TimeDelta()); two_minutes_pool->SetWakeUpInterval(test_task_runner_->NowTicks(), base::TimeDelta::FromMinutes(2)); - scoped_refptr<MainThreadTaskQueue> two_minutes_queue = - scheduler_->NewTaskQueue( - MainThreadTaskQueue::QueueCreationParams( - MainThreadTaskQueue::QueueType::kFrameThrottleable) - .SetCanBeThrottled(true)); - two_minutes_pool->AddQueue(base::TimeTicks(), - GetTaskQueue(two_minutes_queue.get())); + scoped_refptr<base::sequence_manager::TaskQueue> two_minutes_queue = + sequence_manager_->CreateTaskQueue( + base::sequence_manager::TaskQueue::Spec("Second queue") + .SetDelayedFencesAllowed(true)); + auto two_minutes_queue_throttler = + CreateThrottlerForTaskQueue(two_minutes_queue.get()); + two_minutes_pool->AddThrottler(base::TimeTicks(), + two_minutes_queue_throttler.get()); scoped_refptr<base::SingleThreadTaskRunner> two_minutes_task_runner = - two_minutes_queue->GetTaskRunnerWithDefaultTaskType(); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(two_minutes_queue.get())); + two_minutes_queue->task_runner(); + two_minutes_queue_throttler->IncreaseThrottleRefCount(); // Post tasks with a short delay to both queues. constexpr base::TimeDelta kShortDelay = base::TimeDelta::FromSeconds(1); @@ -1550,9 +1317,8 @@ TEST_F(TaskQueueThrottlerTest, base::TimeTicks() + base::TimeDelta::FromMinutes(2)); // Clean up. - two_minutes_pool->RemoveQueue(test_task_runner_->NowTicks(), - GetTaskQueue(two_minutes_queue.get())); - two_minutes_pool->Close(); + two_minutes_pool->RemoveThrottler(test_task_runner_->NowTicks(), + two_minutes_queue_throttler.get()); } TEST_F(TaskQueueThrottlerTest, @@ -1563,32 +1329,33 @@ TEST_F(TaskQueueThrottlerTest, wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(), base::TimeDelta::FromMinutes(1)); - wake_up_budget_pool_->AllowUnalignedWakeUpIfNoRecentWakeUp(); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - WakeUpBudgetPool* one_minute_pool = wake_up_budget_pool_; + wake_up_budget_pool_->AllowLowerAlignmentIfNoRecentWakeUp( + base::TimeDelta::FromSeconds(1)); + task_queue_throttler_->IncreaseThrottleRefCount(); + WakeUpBudgetPool* one_minute_pool = wake_up_budget_pool_.get(); scoped_refptr<base::SingleThreadTaskRunner> one_minute_task_runner = timer_task_runner_; // Create another TaskQueue, throttled by another WakeUpBudgetPool. - WakeUpBudgetPool* two_minutes_pool = - task_queue_throttler_->CreateWakeUpBudgetPool( - "Two Minutes Interval Pool"); + std::unique_ptr<WakeUpBudgetPool> two_minutes_pool = + std::make_unique<WakeUpBudgetPool>("Two Minutes Interval Pool"); two_minutes_pool->SetWakeUpDuration(base::TimeDelta()); two_minutes_pool->SetWakeUpInterval(test_task_runner_->NowTicks(), base::TimeDelta::FromMinutes(1)); - two_minutes_pool->AllowUnalignedWakeUpIfNoRecentWakeUp(); - scoped_refptr<MainThreadTaskQueue> two_minutes_queue = - scheduler_->NewTaskQueue( - MainThreadTaskQueue::QueueCreationParams( - MainThreadTaskQueue::QueueType::kFrameThrottleable) - .SetCanBeThrottled(true)); - two_minutes_pool->AddQueue(base::TimeTicks(), - GetTaskQueue(two_minutes_queue.get())); + two_minutes_pool->AllowLowerAlignmentIfNoRecentWakeUp( + base::TimeDelta::FromSeconds(1)); + scoped_refptr<base::sequence_manager::TaskQueue> two_minutes_queue = + sequence_manager_->CreateTaskQueue( + base::sequence_manager::TaskQueue::Spec("Second queue") + .SetDelayedFencesAllowed(true)); + auto two_minutes_queue_throttler = + CreateThrottlerForTaskQueue(two_minutes_queue.get()); + + two_minutes_pool->AddThrottler(base::TimeTicks(), + two_minutes_queue_throttler.get()); scoped_refptr<base::SingleThreadTaskRunner> two_minutes_task_runner = - two_minutes_queue->GetTaskRunnerWithDefaultTaskType(); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(two_minutes_queue.get())); + two_minutes_queue->task_runner(); + two_minutes_queue_throttler->IncreaseThrottleRefCount(); // Post tasks with short delays to both queues. They should run unaligned. The // wake up in |one_minute_pool| should not be taken into account when @@ -1660,9 +1427,8 @@ TEST_F(TaskQueueThrottlerTest, start_time + base::TimeDelta::FromSeconds(606)); // Clean up. - two_minutes_pool->RemoveQueue(test_task_runner_->NowTicks(), - GetTaskQueue(two_minutes_queue.get())); - two_minutes_pool->Close(); + two_minutes_pool->RemoveThrottler(test_task_runner_->NowTicks(), + two_minutes_queue_throttler.get()); } TEST_F(TaskQueueThrottlerTest, @@ -1674,31 +1440,32 @@ TEST_F(TaskQueueThrottlerTest, // The 1st WakeUpBudgetPool doesn't allow unaligned wake ups. wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(), base::TimeDelta::FromMinutes(1)); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); - WakeUpBudgetPool* aligned_pool = wake_up_budget_pool_; + task_queue_throttler_->IncreaseThrottleRefCount(); + WakeUpBudgetPool* aligned_pool = wake_up_budget_pool_.get(); scoped_refptr<base::SingleThreadTaskRunner> aligned_task_runner = timer_task_runner_; // Create another TaskQueue, throttled by another WakeUpBudgetPool. This 2nd // WakeUpBudgetPool allows unaligned wake ups. - WakeUpBudgetPool* unaligned_pool = - task_queue_throttler_->CreateWakeUpBudgetPool( - "Other Wake Up Budget Pool"); + std::unique_ptr<WakeUpBudgetPool> unaligned_pool = + std::make_unique<WakeUpBudgetPool>("Other Wake Up Budget Pool"); unaligned_pool->SetWakeUpDuration(base::TimeDelta()); unaligned_pool->SetWakeUpInterval(test_task_runner_->NowTicks(), base::TimeDelta::FromMinutes(1)); - unaligned_pool->AllowUnalignedWakeUpIfNoRecentWakeUp(); - scoped_refptr<MainThreadTaskQueue> unaligned_queue = scheduler_->NewTaskQueue( - MainThreadTaskQueue::QueueCreationParams( - MainThreadTaskQueue::QueueType::kFrameThrottleable) - .SetCanBeThrottled(true)); - unaligned_pool->AddQueue(base::TimeTicks(), - GetTaskQueue(unaligned_queue.get())); + unaligned_pool->AllowLowerAlignmentIfNoRecentWakeUp( + base::TimeDelta::FromSeconds(1)); + scoped_refptr<base::sequence_manager::TaskQueue> unaligned_queue = + sequence_manager_->CreateTaskQueue( + base::sequence_manager::TaskQueue::Spec("Second queue") + .SetDelayedFencesAllowed(true)); + auto unaligned_queue_throttler = + CreateThrottlerForTaskQueue(unaligned_queue.get()); + + unaligned_pool->AddThrottler(base::TimeTicks(), + unaligned_queue_throttler.get()); scoped_refptr<base::SingleThreadTaskRunner> unaligned_task_runner = - unaligned_queue->GetTaskRunnerWithDefaultTaskType(); - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(unaligned_queue.get())); + unaligned_queue->task_runner(); + unaligned_queue_throttler->IncreaseThrottleRefCount(); // Post tasks with short delays to both queues. The 1st task should run // aligned, while the 2nd task should run unaligned. @@ -1772,9 +1539,8 @@ TEST_F(TaskQueueThrottlerTest, start_time + base::TimeDelta::FromSeconds(663)); // Clean up. - unaligned_pool->RemoveQueue(test_task_runner_->NowTicks(), - GetTaskQueue(unaligned_queue.get())); - unaligned_pool->Close(); + unaligned_pool->RemoveThrottler(test_task_runner_->NowTicks(), + unaligned_queue_throttler.get()); } TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottling_EnableDisableThrottling) { @@ -1786,8 +1552,7 @@ TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottling_EnableDisableThrottling) { wake_up_budget_pool_->SetWakeUpDuration(base::TimeDelta::FromMilliseconds(1)); Vector<base::TimeTicks> run_times; - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); timer_task_runner_->PostDelayedTask( FROM_HERE, @@ -1829,7 +1594,7 @@ TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottling_EnableDisableThrottling) { base::TimeTicks() + base::TimeDelta::FromSeconds(300))); } -TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottling_UnalignedWakeUps) { +TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottling_LowAlignedWakeUps) { // All throttled wake ups are aligned on 1-second intervals by // TaskQueueThrottler, irrespective of BudgetPools. Start the test at a time // aligned on a 1-minute interval, to simplify expectations. @@ -1837,16 +1602,16 @@ TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottling_UnalignedWakeUps) { const base::TimeTicks start_time = test_task_runner_->NowTicks(); Vector<base::TimeTicks> run_times; - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(), base::TimeDelta::FromMinutes(1)); - wake_up_budget_pool_->AllowUnalignedWakeUpIfNoRecentWakeUp(); + wake_up_budget_pool_->AllowLowerAlignmentIfNoRecentWakeUp( + base::TimeDelta::FromSeconds(10)); timer_task_runner_->PostDelayedTask( FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_), - base::TimeDelta::FromSeconds(90)); + base::TimeDelta::FromSeconds(88)); test_task_runner_->FastForwardUntilNoTasksRemain(); @@ -1861,10 +1626,10 @@ TEST_F(TaskQueueThrottlerTest, const base::TimeTicks initial_time = test_task_runner_->NowTicks(); wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(), base::TimeDelta::FromMinutes(1)); - wake_up_budget_pool_->AllowUnalignedWakeUpIfNoRecentWakeUp(); + wake_up_budget_pool_->AllowLowerAlignmentIfNoRecentWakeUp( + base::TimeDelta::FromSeconds(1)); Vector<base::TimeTicks> run_times; - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); // Task delay: Expected run time: Reason: // 30 seconds 30 seconds >= 60 seconds after last wake up // 80 seconds 90 seconds >= 60 seconds after last wake up @@ -1903,8 +1668,7 @@ TEST_F(TaskQueueThrottlerTest, TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottling_IncreaseWakeUpIntervalBeforeWakeUp) { Vector<base::TimeTicks> run_times; - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); // Post 2 delayed tasks when the wake up interval is 1 minute. The delay of // the 2nd task is such that it won't be ready when the 1st task completes. @@ -1931,8 +1695,7 @@ TEST_F(TaskQueueThrottlerTest, TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottling_DecreaseWakeUpIntervalBeforeWakeUp) { Vector<base::TimeTicks> run_times; - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); // Post a delayed task when the wake up interval is 1 hour. wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(), @@ -1958,8 +1721,7 @@ TEST_F(TaskQueueThrottlerTest, base::TimeDelta::FromMilliseconds(10)); Vector<base::TimeTicks> run_times; - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); // Post a 1st delayed task when the wake up interval is 1 minute. wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(), @@ -1998,8 +1760,7 @@ TEST_F(TaskQueueThrottlerTest, base::TimeDelta::FromMilliseconds(10)); Vector<base::TimeTicks> run_times; - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); // Post a 1st delayed task when the wake up interval is 1 hour. wake_up_budget_pool_->SetWakeUpInterval(test_task_runner_->NowTicks(), @@ -2038,16 +1799,15 @@ TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottlingWithCPUBudgetThrottling) { wake_up_budget_pool_->SetWakeUpDuration( base::TimeDelta::FromMilliseconds(10)); - CPUTimeBudgetPool* pool = - task_queue_throttler_->CreateCPUTimeBudgetPool("test"); + std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>( + "test", &tracing_controller_, test_task_runner_->NowTicks()); pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1); - pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get())); + pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get()); Vector<base::TimeTicks> run_times; - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); Deque<base::TimeDelta> task_durations = MakeTaskDurations(9, base::TimeDelta()); @@ -2065,15 +1825,15 @@ TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottlingWithCPUBudgetThrottling) { EXPECT_THAT( run_times, - ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(6000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(6000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(6000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(8000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(8000))); + ElementsAre(TimeTicks() + base::TimeDelta::FromMilliseconds(1000), + start_time_ + base::TimeDelta::FromMilliseconds(2500), + start_time_ + base::TimeDelta::FromMilliseconds(2500), + start_time_ + base::TimeDelta::FromMilliseconds(2500), + start_time_ + base::TimeDelta::FromMilliseconds(5000), + start_time_ + base::TimeDelta::FromMilliseconds(5000), + start_time_ + base::TimeDelta::FromMilliseconds(5000), + start_time_ + base::TimeDelta::FromMilliseconds(7500), + start_time_ + base::TimeDelta::FromMilliseconds(7500))); } TEST_F(TaskQueueThrottlerTest, @@ -2081,11 +1841,11 @@ TEST_F(TaskQueueThrottlerTest, wake_up_budget_pool_->SetWakeUpDuration( base::TimeDelta::FromMilliseconds(10)); - CPUTimeBudgetPool* pool = - task_queue_throttler_->CreateCPUTimeBudgetPool("test"); + std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>( + "test", &tracing_controller_, test_task_runner_->NowTicks()); pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1); - pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get())); + pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get()); Vector<base::TimeTicks> run_times; @@ -2101,12 +1861,10 @@ TEST_F(TaskQueueThrottlerTest, base::TimeDelta::FromMilliseconds(300)); if (is_throttled) { - task_queue_throttler_->DecreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->DecreaseThrottleRefCount(); is_throttled = false; } else { - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); is_throttled = true; } @@ -2115,21 +1873,21 @@ TEST_F(TaskQueueThrottlerTest, EXPECT_THAT(run_times, ElementsAre( - // Throttled due to cpu budget. - base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000), + // Throttled due to wake-up budget, then cpu budget. + TimeTicks() + base::TimeDelta::FromMilliseconds(1000), + start_time_ + base::TimeDelta::FromMilliseconds(2500), // Unthrottled. - base::TimeTicks() + base::TimeDelta::FromMilliseconds(3200), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(3450), - // Throttled due to wake-up budget. Old tasks still run. - base::TimeTicks() + base::TimeDelta::FromMilliseconds(5000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(5250), + start_time_ + base::TimeDelta::FromMilliseconds(2700), + start_time_ + base::TimeDelta::FromMilliseconds(2950), + // Throttled due to wake-up budget. + TimeTicks() + base::TimeDelta::FromMilliseconds(4000), + start_time_ + base::TimeDelta::FromMilliseconds(5000), // Unthrottled. - base::TimeTicks() + base::TimeDelta::FromMilliseconds(6200), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(6450), - // Throttled due to wake-up budget. Old tasks still run. - base::TimeTicks() + base::TimeDelta::FromMilliseconds(8000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(8250))); + start_time_ + base::TimeDelta::FromMilliseconds(5200), + start_time_ + base::TimeDelta::FromMilliseconds(5450), + // Throttled due to wake-up budget, then cpu budget. + TimeTicks() + base::TimeDelta::FromMilliseconds(6000), + start_time_ + base::TimeDelta::FromMilliseconds(7500))); } TEST_F(TaskQueueThrottlerTest, @@ -2140,16 +1898,15 @@ TEST_F(TaskQueueThrottlerTest, wake_up_budget_pool_->SetWakeUpDuration( base::TimeDelta::FromMilliseconds(10)); - CPUTimeBudgetPool* pool = - task_queue_throttler_->CreateCPUTimeBudgetPool("test"); + std::unique_ptr<CPUTimeBudgetPool> pool = std::make_unique<CPUTimeBudgetPool>( + "test", &tracing_controller_, test_task_runner_->NowTicks()); pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.01); - pool->AddQueue(base::TimeTicks(), GetTaskQueue(timer_queue_.get())); + pool->AddThrottler(base::TimeTicks(), task_queue_throttler_.get()); Vector<base::TimeTicks> run_times; - task_queue_throttler_->IncreaseThrottleRefCount( - GetTaskQueue(timer_queue_.get())); + task_queue_throttler_->IncreaseThrottleRefCount(); timer_task_runner_->PostDelayedTask( FROM_HERE, @@ -2164,21 +1921,19 @@ TEST_F(TaskQueueThrottlerTest, EXPECT_THAT(run_times, ElementsAre( // Time budget is ~10ms and we can run two 7ms tasks. - base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(1007), + TimeTicks() + base::TimeDelta::FromMilliseconds(1000), + TimeTicks() + base::TimeDelta::FromMilliseconds(1007), // Time budget is ~6ms and we can run one 7ms task. - base::TimeTicks() + base::TimeDelta::FromMilliseconds(2000), - // Time budget is ~8ms and we can run two 7ms tasks. - base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(3007), - // Time budget is ~5ms and we can run one 7ms task. - base::TimeTicks() + base::TimeDelta::FromMilliseconds(4000), - // Time budget is ~8ms and we can run two 7ms tasks. - base::TimeTicks() + base::TimeDelta::FromMilliseconds(5000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(5007), - // Time budget is ~4ms and we can run one 7ms task. - base::TimeTicks() + base::TimeDelta::FromMilliseconds(6000), - base::TimeTicks() + base::TimeDelta::FromMilliseconds(7000))); + TimeTicks() + base::TimeDelta::FromMilliseconds(2000), + // Time budget is ~0ms and we can run one 7ms tasks every + // 700ms. + start_time_ + base::TimeDelta::FromMilliseconds(2100), + start_time_ + base::TimeDelta::FromMilliseconds(2800), + start_time_ + base::TimeDelta::FromMilliseconds(3500), + start_time_ + base::TimeDelta::FromMilliseconds(4200), + start_time_ + base::TimeDelta::FromMilliseconds(4900), + start_time_ + base::TimeDelta::FromMilliseconds(5600), + start_time_ + base::TimeDelta::FromMilliseconds(6300))); } } // namespace task_queue_throttler_unittest diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.cc deleted file mode 100644 index 69ac536ff0a..00000000000 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.cc +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2016 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 "third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.h" - -#include "base/task/sequence_manager/sequence_manager.h" - -namespace blink { -namespace scheduler { - -ThrottledTimeDomain::ThrottledTimeDomain() {} - -ThrottledTimeDomain::~ThrottledTimeDomain() = default; - -base::sequence_manager::LazyNow ThrottledTimeDomain::CreateLazyNow() const { - return base::sequence_manager::LazyNow(sequence_manager()->GetTickClock()); -} - -base::TimeTicks ThrottledTimeDomain::Now() const { - return sequence_manager()->NowTicks(); -} - -const char* ThrottledTimeDomain::GetName() const { - return "ThrottledTimeDomain"; -} - -void ThrottledTimeDomain::SetNextDelayedDoWork( - base::sequence_manager::LazyNow* lazy_now, - base::TimeTicks run_time) { - // We assume the owner (i.e. TaskQueueThrottler) will manage wake-ups on our - // behalf. -} - -void ThrottledTimeDomain::SetNextTaskRunTime(base::TimeTicks run_time) { - next_task_run_time_ = run_time; -} - -absl::optional<base::TimeDelta> ThrottledTimeDomain::DelayTillNextTask( - base::sequence_manager::LazyNow* lazy_now) { - base::TimeTicks now = lazy_now->Now(); - if (next_task_run_time_ && next_task_run_time_ > now) - return next_task_run_time_.value() - now; - - absl::optional<base::TimeTicks> next_run_time = NextScheduledRunTime(); - if (!next_run_time) - return absl::nullopt; - - if (now >= next_run_time) - return base::TimeDelta(); // Makes DoWork post an immediate continuation. - - // We assume the owner (i.e. TaskQueueThrottler) will manage wake-ups on our - // behalf. - return absl::nullopt; -} - -bool ThrottledTimeDomain::MaybeFastForwardToNextTask( - bool quit_when_idle_requested) { - return false; -} - -} // namespace scheduler -} // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.h b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.h deleted file mode 100644 index c8726b2c54a..00000000000 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2016 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THROTTLING_THROTTLED_TIME_DOMAIN_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THROTTLING_THROTTLED_TIME_DOMAIN_H_ - -#include "base/macros.h" -#include "base/task/sequence_manager/time_domain.h" -#include "third_party/blink/renderer/platform/platform_export.h" - -namespace blink { -namespace scheduler { - -// A time domain for throttled tasks. Behaves like an RealTimeDomain except it -// relies on the owner (TaskQueueThrottler) to schedule wake-ups. -class PLATFORM_EXPORT ThrottledTimeDomain - : public base::sequence_manager::TimeDomain { - public: - ThrottledTimeDomain(); - ~ThrottledTimeDomain() override; - - void SetNextTaskRunTime(base::TimeTicks run_time); - - // TimeDomain implementation: - base::sequence_manager::LazyNow CreateLazyNow() const override; - base::TimeTicks Now() const override; - absl::optional<base::TimeDelta> DelayTillNextTask( - base::sequence_manager::LazyNow* lazy_now) override; - bool MaybeFastForwardToNextTask(bool quit_when_idle_requested) override; - - protected: - const char* GetName() const override; - void SetNextDelayedDoWork(base::sequence_manager::LazyNow* lazy_now, - base::TimeTicks run_time) override; - - private: - // Next task run time provided by task queue throttler. Note that it does not - // get reset, so it is valid only when in the future. - absl::optional<base::TimeTicks> next_task_run_time_; - - DISALLOW_COPY_AND_ASSIGN(ThrottledTimeDomain); -}; - -} // namespace scheduler -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THROTTLING_THROTTLED_TIME_DOMAIN_H_ diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.cc index f72ed30bd1b..1ffe3935bad 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.cc @@ -15,11 +15,8 @@ namespace scheduler { using base::sequence_manager::TaskQueue; -WakeUpBudgetPool::WakeUpBudgetPool(const char* name, - BudgetPoolController* budget_pool_controller, - base::TimeTicks now) - : BudgetPool(name, budget_pool_controller), - wake_up_interval_(base::TimeDelta::FromSeconds(1)) {} +WakeUpBudgetPool::WakeUpBudgetPool(const char* name) + : BudgetPool(name), wake_up_interval_(base::TimeDelta::FromSeconds(1)) {} WakeUpBudgetPool::~WakeUpBudgetPool() = default; @@ -30,46 +27,36 @@ QueueBlockType WakeUpBudgetPool::GetBlockType() const { void WakeUpBudgetPool::SetWakeUpInterval(base::TimeTicks now, base::TimeDelta interval) { wake_up_interval_ = interval; - UpdateThrottlingStateForAllQueues(now); + UpdateStateForAllThrottlers(now); } void WakeUpBudgetPool::SetWakeUpDuration(base::TimeDelta duration) { wake_up_duration_ = duration; } -void WakeUpBudgetPool::AllowUnalignedWakeUpIfNoRecentWakeUp() { - allow_unaligned_wake_up_is_no_recent_wake_up_ = true; +void WakeUpBudgetPool::AllowLowerAlignmentIfNoRecentWakeUp( + base::TimeDelta alignment) { + DCHECK_LE(alignment, wake_up_interval_); + wake_up_alignment_if_no_recent_wake_up_ = alignment; } -void WakeUpBudgetPool::RecordTaskRunTime(TaskQueue* queue, - base::TimeTicks start_time, - base::TimeTicks end_time) { - budget_pool_controller_->UpdateQueueSchedulingLifecycleState(end_time, queue); -} - -bool WakeUpBudgetPool::CanRunTasksAt(base::TimeTicks moment, - bool is_wake_up) const { +bool WakeUpBudgetPool::CanRunTasksAt(base::TimeTicks moment) const { if (!is_enabled_) return true; if (!last_wake_up_) return false; - // |is_wake_up| flag means that we're in the beginning of the wake-up and - // |OnWakeUp| has just been called. This is needed to support - // backwards compatibility with old throttling mechanism (when - // |wake_up_duration| is zero) and allow only one task to run. - if (last_wake_up_ == moment && is_wake_up) + if (last_wake_up_ == moment) return true; + return moment < last_wake_up_.value() + wake_up_duration_; } base::TimeTicks WakeUpBudgetPool::GetTimeTasksCanRunUntil( - base::TimeTicks now, - bool is_wake_up) const { + base::TimeTicks now) const { if (!is_enabled_) return base::TimeTicks::Max(); - if (!last_wake_up_) - return base::TimeTicks(); - if (!CanRunTasksAt(now, is_wake_up)) + DCHECK(last_wake_up_); + if (!CanRunTasksAt(now)) return base::TimeTicks(); return last_wake_up_.value() + wake_up_duration_; } @@ -86,39 +73,42 @@ base::TimeTicks WakeUpBudgetPool::GetNextAllowedRunTime( return desired_run_time; } - // Do not throttle if there hasn't been a wake up in the last wake up - // interval. - if (allow_unaligned_wake_up_is_no_recent_wake_up_) { - // If unaligned wake ups are allowed, the first wake up can happen at any - // point. - if (!last_wake_up_.has_value()) - return desired_run_time; - - // Unaligned wake ups can happen at most every |wake_up_interval_| after the - // last wake up. - auto next_unaligned_wake_up = - std::max(desired_run_time, last_wake_up_.value() + wake_up_interval_); - - // Aligned wake ups happen every |wake_up_interval_|, snapped to the minute. - auto next_aligned_wake_up = desired_run_time.SnappedToNextTick( + // If there hasn't been a wake up in the last wake up interval, the next wake + // up is simply aligned on |wake_up_alignment_if_no_recent_wake_up_|. + if (!wake_up_alignment_if_no_recent_wake_up_.is_zero()) { + // The first wake up is simply aligned on + // |wake_up_alignment_if_no_recent_wake_up_|. + if (!last_wake_up_.has_value()) { + return desired_run_time.SnappedToNextTick( + base::TimeTicks(), wake_up_alignment_if_no_recent_wake_up_); + } + + // The next wake up is allowed at least |wake_up_interval_| after the last + // wake up. + auto next_aligned_wake_up = + std::max(desired_run_time, last_wake_up_.value() + wake_up_interval_) + .SnappedToNextTick(base::TimeTicks(), + wake_up_alignment_if_no_recent_wake_up_); + + // A wake up is also allowed every |wake_up_interval_|. + auto next_wake_up_at_interval = desired_run_time.SnappedToNextTick( base::TimeTicks(), wake_up_interval_); // Pick the earliest of the two allowed run times. - return std::min(next_unaligned_wake_up, next_aligned_wake_up); + return std::min(next_aligned_wake_up, next_wake_up_at_interval); } return desired_run_time.SnappedToNextTick(base::TimeTicks(), wake_up_interval_); } -void WakeUpBudgetPool::OnQueueNextWakeUpChanged( - TaskQueue* queue, - base::TimeTicks now, - base::TimeTicks desired_run_time) { - budget_pool_controller_->UpdateQueueSchedulingLifecycleState(now, queue); -} - void WakeUpBudgetPool::OnWakeUp(base::TimeTicks now) { + // To ensure that we correctly enforce wakeup limits for rapid successive + // wakeups, if |now| is within the last wakeup duration (e.g. |now| is 2ms + // after the last wakeup and |wake_up_duration_| is 3ms), this isn't counted + // as a new wakeup. + if (last_wake_up_ && now < last_wake_up_.value() + wake_up_duration_) + return; last_wake_up_ = now; } @@ -129,12 +119,14 @@ void WakeUpBudgetPool::WriteIntoTrace(perfetto::TracedValue context, dict.Add("name", name_); dict.Add("wake_up_interval_in_seconds", wake_up_interval_.InSecondsF()); dict.Add("wake_up_duration_in_seconds", wake_up_duration_.InSecondsF()); + dict.Add("wake_up_alignment_if_no_recent_wake_up_in_seconds", + wake_up_alignment_if_no_recent_wake_up_.InSecondsF()); if (last_wake_up_) { dict.Add("last_wake_up_seconds_ago", (now - last_wake_up_.value()).InSecondsF()); } dict.Add("is_enabled", is_enabled_); - dict.Add("task_queues", associated_task_queues_); + dict.Add("throttlers", associated_throttlers_); } } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h index 96d0952837f..fd02605fce4 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h @@ -7,7 +7,6 @@ #include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h" -#include "base/macros.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace blink { @@ -17,9 +16,9 @@ namespace scheduler { // limited time at regular intervals. class PLATFORM_EXPORT WakeUpBudgetPool : public BudgetPool { public: - WakeUpBudgetPool(const char* name, - BudgetPoolController* budget_pool_controller, - base::TimeTicks now); + explicit WakeUpBudgetPool(const char* name); + WakeUpBudgetPool(const WakeUpBudgetPool&) = delete; + WakeUpBudgetPool& operator=(const WakeUpBudgetPool&) = delete; ~WakeUpBudgetPool() override; // Sets the interval between wake ups. This can be invoked at any time. If a @@ -31,25 +30,21 @@ class PLATFORM_EXPORT WakeUpBudgetPool : public BudgetPool { // should be called only during initialization of a WakeUpBudgetPool. void SetWakeUpDuration(base::TimeDelta duration); - // If called, the budget pool allows an unaligned wake up when there hasn't - // been a wake up in the last |wake_up_interval_|. + // Sets a lower wake up alignment. If non-zero, the budget pool will ignore + // the |wake_up_interval_| and allow a wake up aligned on |alignment| if there + // hasn't been a wake up in the last |wake_up_interval_|. // // This does not have an immediate effect and should be called only during // initialization of a WakeUpBudgetPool. - void AllowUnalignedWakeUpIfNoRecentWakeUp(); + void AllowLowerAlignmentIfNoRecentWakeUp(base::TimeDelta alignment); // BudgetPool implementation: - void RecordTaskRunTime(base::sequence_manager::TaskQueue* queue, - base::TimeTicks start_time, - base::TimeTicks end_time) final; - bool CanRunTasksAt(base::TimeTicks moment, bool is_wake_up) const final; - base::TimeTicks GetTimeTasksCanRunUntil(base::TimeTicks now, - bool is_wake_up) const final; + void RecordTaskRunTime(base::TimeTicks start_time, + base::TimeTicks end_time) final {} + bool CanRunTasksAt(base::TimeTicks moment) const final; + base::TimeTicks GetTimeTasksCanRunUntil(base::TimeTicks now) const final; base::TimeTicks GetNextAllowedRunTime( base::TimeTicks desired_run_time) const final; - void OnQueueNextWakeUpChanged(base::sequence_manager::TaskQueue* queue, - base::TimeTicks now, - base::TimeTicks desired_run_time) final; void OnWakeUp(base::TimeTicks now) final; void WriteIntoTrace(perfetto::TracedValue context, base::TimeTicks now) const final; @@ -64,12 +59,9 @@ class PLATFORM_EXPORT WakeUpBudgetPool : public BudgetPool { private: base::TimeDelta wake_up_interval_; base::TimeDelta wake_up_duration_; - - bool allow_unaligned_wake_up_is_no_recent_wake_up_ = false; + base::TimeDelta wake_up_alignment_if_no_recent_wake_up_; absl::optional<base::TimeTicks> last_wake_up_; - - DISALLOW_COPY_AND_ASSIGN(WakeUpBudgetPool); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h index 95945d7ee8a..9d1afac1aad 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/tracing_helper.h @@ -9,7 +9,6 @@ #include <unordered_set> #include "base/compiler_specific.h" -#include "base/macros.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/typed_macros.h" @@ -99,6 +98,8 @@ class StateTracer { explicit StateTracer(const char* name) : name_(name), slice_is_open_(false) { internal::ValidateTracingCategory(category); } + StateTracer(const StateTracer&) = delete; + StateTracer& operator=(const StateTracer&) = delete; ~StateTracer() { if (slice_is_open_) @@ -145,8 +146,6 @@ class StateTracer { // We have to track whether slice is open to avoid confusion since assignment, // "absent" state and OnTraceLogEnabled can happen anytime. bool slice_is_open_; - - DISALLOW_COPY_AND_ASSIGN(StateTracer); }; // TODO(kraynov): Rename to something less generic and reflecting @@ -169,6 +168,8 @@ class TraceableState : public TraceableVariable, private StateTracer<category> { Trace(); } + TraceableState(const TraceableState&) = delete; + ~TraceableState() override = default; TraceableState& operator=(const T& value) { @@ -222,8 +223,6 @@ class TraceableState : public TraceableVariable, private StateTracer<category> { const ConverterFuncPtr converter_; T state_; - - DISALLOW_COPY(TraceableState); }; template <const char* category, typename TypedValue> @@ -370,6 +369,8 @@ class TraceableCounter : public TraceableVariable { return static_cast<double>(value); }) {} + TraceableCounter(const TraceableCounter&) = delete; + TraceableCounter& operator=(const T& value) { value_ = value; Trace(); @@ -407,7 +408,6 @@ class TraceableCounter : public TraceableVariable { const ConverterFuncPtr converter_; T value_; - DISALLOW_COPY(TraceableCounter); }; // Add operators when it's needed. diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/ukm_task_sampler.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/ukm_task_sampler.cc index 7e3fc68ee3b..fc298f38687 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/ukm_task_sampler.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/ukm_task_sampler.cc @@ -12,7 +12,9 @@ namespace scheduler { UkmTaskSampler::UkmTaskSampler(double thread_time_sampling_rate, double ukm_task_sampling_rate) : thread_time_sampling_rate_(clampTo(thread_time_sampling_rate, 0.0, 1.0)), - ukm_task_sampling_rate_(clampTo(ukm_task_sampling_rate, 0.0, 1.0)) {} + ukm_task_sampling_rate_(clampTo(ukm_task_sampling_rate, 0.0, 1.0)) { + random_generator_.Seed(); +} double UkmTaskSampler::GetConditionalSamplingProbability(bool has_thread_time) { if (thread_time_sampling_rate_ == 0.0 || ukm_task_sampling_rate_ == 0.0 || @@ -42,8 +44,7 @@ double UkmTaskSampler::GetConditionalSamplingProbability(bool has_thread_time) { bool UkmTaskSampler::ShouldRecordTaskUkm(bool has_thread_time) { double probability = GetConditionalSamplingProbability(has_thread_time); - std::bernoulli_distribution dist(probability); - return dist(random_generator_); + return random_generator_.RandDouble() < probability; } void UkmTaskSampler::SetUkmTaskSamplingRate(double rate) { diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/ukm_task_sampler.h b/chromium/third_party/blink/renderer/platform/scheduler/common/ukm_task_sampler.h index 40c95b3e7ba..4bc9276ccde 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/ukm_task_sampler.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/ukm_task_sampler.h @@ -5,9 +5,8 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_UKM_TASK_SAMPLER_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_UKM_TASK_SAMPLER_H_ -#include <random> - #include "base/gtest_prod_util.h" +#include "base/rand_util.h" #include "third_party/blink/renderer/platform/platform_export.h" namespace blink { @@ -47,7 +46,7 @@ class PLATFORM_EXPORT UkmTaskSampler { double thread_time_sampling_rate_; double ukm_task_sampling_rate_; - std::mt19937_64 random_generator_; + base::InsecureRandomGenerator random_generator_; }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/unprioritized_resource_loading_task_runner_handle.h b/chromium/third_party/blink/renderer/platform/scheduler/common/unprioritized_resource_loading_task_runner_handle.h index 9d4199b73e9..c61e4e2ad23 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/unprioritized_resource_loading_task_runner_handle.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/unprioritized_resource_loading_task_runner_handle.h @@ -23,6 +23,11 @@ class PLATFORM_EXPORT UnprioritizedResourceLoadingTaskRunnerHandle static std::unique_ptr<UnprioritizedResourceLoadingTaskRunnerHandle> WrapTaskRunner(scoped_refptr<base::SingleThreadTaskRunner> task_runner); + UnprioritizedResourceLoadingTaskRunnerHandle( + const UnprioritizedResourceLoadingTaskRunnerHandle&) = delete; + UnprioritizedResourceLoadingTaskRunnerHandle& operator=( + const UnprioritizedResourceLoadingTaskRunnerHandle&) = delete; + scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() const override; void DidChangeRequestPriority(net::RequestPriority priority) override; @@ -35,8 +40,6 @@ class PLATFORM_EXPORT UnprioritizedResourceLoadingTaskRunnerHandle private: scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - - DISALLOW_COPY_AND_ASSIGN(UnprioritizedResourceLoadingTaskRunnerHandle); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_priority.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/web_scheduling_priority.cc index 6b714382b70..9328da74395 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_priority.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/web_scheduling_priority.cc @@ -10,33 +10,20 @@ namespace blink { namespace { -const AtomicString& UserBlockingPriorityKeyword() { - DEFINE_STATIC_LOCAL(const AtomicString, user_blocking_priority, - ("user-blocking")); - return user_blocking_priority; -} - -const AtomicString& UserVisiblePriorityKeyword() { - DEFINE_STATIC_LOCAL(const AtomicString, user_visible_priority, - ("user-visible")); - return user_visible_priority; -} - -const AtomicString& BackgroundPriorityKeyword() { - DEFINE_STATIC_LOCAL(const AtomicString, background_priority, ("background")); - return background_priority; -} +const char kUserBlockingPriorityKeyword[] = "user-blocking"; +const char kUserVisiblePriorityKeyword[] = "user-visible"; +const char kBackgroundPriorityKeyword[] = "background"; } // namespace AtomicString WebSchedulingPriorityToString(WebSchedulingPriority priority) { switch (priority) { case WebSchedulingPriority::kUserBlockingPriority: - return UserBlockingPriorityKeyword(); + return AtomicString(kUserBlockingPriorityKeyword); case WebSchedulingPriority::kUserVisiblePriority: - return UserVisiblePriorityKeyword(); + return AtomicString(kUserVisiblePriorityKeyword); case WebSchedulingPriority::kBackgroundPriority: - return BackgroundPriorityKeyword(); + return AtomicString(kBackgroundPriorityKeyword); } NOTREACHED(); @@ -45,11 +32,11 @@ AtomicString WebSchedulingPriorityToString(WebSchedulingPriority priority) { WebSchedulingPriority WebSchedulingPriorityFromString( const AtomicString& priority) { - if (priority == UserBlockingPriorityKeyword()) + if (priority == kUserBlockingPriorityKeyword) return WebSchedulingPriority::kUserBlockingPriority; - if (priority == UserVisiblePriorityKeyword()) + if (priority == kUserVisiblePriorityKeyword) return WebSchedulingPriority::kUserVisiblePriority; - if (priority == BackgroundPriorityKeyword()) + if (priority == kBackgroundPriorityKeyword) return WebSchedulingPriority::kBackgroundPriority; NOTREACHED(); return WebSchedulingPriority::kUserVisiblePriority; diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/web_thread_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/web_thread_scheduler.cc index c5098f0fe65..d544075e707 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/common/web_thread_scheduler.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/common/web_thread_scheduler.cc @@ -64,6 +64,12 @@ WebThreadScheduler::DefaultTaskRunner() { } scoped_refptr<base::SingleThreadTaskRunner> +WebThreadScheduler::InputTaskRunner() { + NOTREACHED(); + return nullptr; +} + +scoped_refptr<base::SingleThreadTaskRunner> WebThreadScheduler::CompositorTaskRunner() { NOTREACHED(); return nullptr; diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.cc deleted file mode 100644 index 6f9a1844b1b..00000000000 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.cc +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright 2020 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 "third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.h" - -#include <algorithm> -#include <memory> - -#include "base/check.h" -#include "base/feature_list.h" -#include "base/sequence_checker.h" -#include "base/synchronization/lock.h" -#include "third_party/abseil-cpp/absl/types/optional.h" -#include "third_party/blink/renderer/platform/scheduler/common/features.h" -#include "third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h" -#include "third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h" -#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h" - -namespace blink { -namespace scheduler { -namespace { - -using ::base::sequence_manager::TaskQueue; - -using PrioritisationType = - ::blink::scheduler::MainThreadTaskQueue::QueueTraits::PrioritisationType; - -// Scheduling strategy that does nothing. This emulates the "current" shipped -// behavior, and is the default unless overridden. Corresponds to the -// |kNoOpStrategy| feature. -class NoOpStrategy final : public AgentSchedulingStrategy { - public: - NoOpStrategy() = default; - - ShouldUpdatePolicy OnFrameAdded(const FrameSchedulerImpl&) override { - VerifyValidSequence(); - return ShouldUpdatePolicy::kNo; - } - ShouldUpdatePolicy OnFrameRemoved(const FrameSchedulerImpl&) override { - VerifyValidSequence(); - return ShouldUpdatePolicy::kNo; - } - ShouldUpdatePolicy OnMainFrameFirstMeaningfulPaint( - const FrameSchedulerImpl&) override { - VerifyValidSequence(); - return ShouldUpdatePolicy::kNo; - } - ShouldUpdatePolicy OnInputEvent() override { - VerifyValidSequence(); - return ShouldUpdatePolicy::kNo; - } - ShouldUpdatePolicy OnDocumentChangedInMainFrame( - const FrameSchedulerImpl&) override { - VerifyValidSequence(); - return ShouldUpdatePolicy::kNo; - } - ShouldUpdatePolicy OnMainFrameLoad(const FrameSchedulerImpl&) override { - VerifyValidSequence(); - return ShouldUpdatePolicy::kNo; - } - ShouldUpdatePolicy OnDelayPassed(const FrameSchedulerImpl&) override { - VerifyValidSequence(); - return ShouldUpdatePolicy::kNo; - } - - absl::optional<bool> QueueEnabledState( - const MainThreadTaskQueue& task_queue) const override { - VerifyValidSequence(); - return absl::nullopt; - } - absl::optional<TaskQueue::QueuePriority> QueuePriority( - const MainThreadTaskQueue& task_queue) const override { - VerifyValidSequence(); - return absl::nullopt; - } - - bool ShouldNotifyOnInputEvent() const override { return false; } -}; - -// Strategy that keeps track of main frames reaching a certain signal to make -// scheduling decisions. The exact behavior will be determined by parameter -// values. -class TrackMainFrameSignal final : public AgentSchedulingStrategy { - public: - TrackMainFrameSignal(Delegate& delegate, - PerAgentAffectedQueues affected_queue_types, - PerAgentSlowDownMethod method, - PerAgentSignal signal, - base::TimeDelta delay) - : delegate_(delegate), - affected_queue_types_(affected_queue_types), - method_(method), - signal_(signal), - delay_(delay), - waiting_for_input_(&waiting_for_input_lock_) { - DCHECK(signal != PerAgentSignal::kDelayOnly || !delay.is_zero()) - << "Delay duration can not be zero when using |kDelayOnly|."; - } - - ShouldUpdatePolicy OnFrameAdded( - const FrameSchedulerImpl& frame_scheduler) override { - VerifyValidSequence(); - return OnNewDocument(frame_scheduler); - } - - ShouldUpdatePolicy OnFrameRemoved( - const FrameSchedulerImpl& frame_scheduler) override { - VerifyValidSequence(); - if (frame_scheduler.GetFrameType() != - FrameScheduler::FrameType::kMainFrame) { - return ShouldUpdatePolicy::kNo; - } - - main_frames_.erase(&frame_scheduler); - main_frames_waiting_for_signal_.erase(&frame_scheduler); - if (main_frames_waiting_for_signal_.IsEmpty()) - SetWaitingForInput(false); - - // TODO(talp): If the frame wasn't in the set to begin with (e.g.: because - // it already hit FMP), or if there are still other frames in the set, - // then we may not have to trigger a policy update. (But what about cases - // where the current agent just changed from main to non-main?) - return ShouldUpdatePolicy::kYes; - } - - ShouldUpdatePolicy OnMainFrameFirstMeaningfulPaint( - const FrameSchedulerImpl& frame_scheduler) override { - VerifyValidSequence(); - DCHECK(frame_scheduler.GetFrameType() == - FrameScheduler::FrameType::kMainFrame); - - return OnSignal(frame_scheduler, PerAgentSignal::kFirstMeaningfulPaint); - } - - ShouldUpdatePolicy OnInputEvent() override { - VerifyValidSequence(); - - // We only use input as a fail-safe for FMP, other signals are more - // reliable. - DCHECK_EQ(signal_, PerAgentSignal::kFirstMeaningfulPaint) - << "OnInputEvent should only be called for FMP-based strategies."; - - if (main_frames_waiting_for_signal_.IsEmpty()) - return ShouldUpdatePolicy::kNo; - - // Ideally we would like to only remove the frame the input event is related - // to, but we don't currently have that information. One suggestion (by - // altimin@) is to attribute it to a widget, and apply it to all frames on - // the page the widget is on. - main_frames_waiting_for_signal_.clear(); - SetWaitingForInput(false); - return ShouldUpdatePolicy::kYes; - } - - ShouldUpdatePolicy OnDocumentChangedInMainFrame( - const FrameSchedulerImpl& frame_scheduler) override { - VerifyValidSequence(); - return OnNewDocument(frame_scheduler); - } - - ShouldUpdatePolicy OnMainFrameLoad( - const FrameSchedulerImpl& frame_scheduler) override { - VerifyValidSequence(); - DCHECK(frame_scheduler.GetFrameType() == - FrameScheduler::FrameType::kMainFrame); - - return OnSignal(frame_scheduler, PerAgentSignal::kOnLoad); - } - - ShouldUpdatePolicy OnDelayPassed( - const FrameSchedulerImpl& frame_scheduler) override { - VerifyValidSequence(); - return SignalReached(frame_scheduler); - } - - absl::optional<bool> QueueEnabledState( - const MainThreadTaskQueue& task_queue) const override { - VerifyValidSequence(); - - if (method_ == PerAgentSlowDownMethod::kDisable && - ShouldAffectQueue(task_queue)) { - return false; - } - - return absl::nullopt; - } - - absl::optional<TaskQueue::QueuePriority> QueuePriority( - const MainThreadTaskQueue& task_queue) const override { - VerifyValidSequence(); - - if (method_ == PerAgentSlowDownMethod::kBestEffort && - ShouldAffectQueue(task_queue)) { - return TaskQueue::QueuePriority::kBestEffortPriority; - } - - return absl::nullopt; - } - - bool ShouldNotifyOnInputEvent() const override { - if (signal_ != PerAgentSignal::kFirstMeaningfulPaint) - return false; - - return waiting_for_input_.IsSet(); - } - - private: - ShouldUpdatePolicy OnNewDocument(const FrameSchedulerImpl& frame_scheduler) { - // For now we *always* return kYes here. It might be possible to optimize - // this, but there are a number of tricky cases that need to be taken into - // account here: (i) a non-main frame could have navigated between a main - // and a non-main agent, possibly requiring policy update for that frame, or - // (ii) main frame navigated to a different agent, potentially changing the - // main/non-main classification for both the "previous" and "current" agents - // and requiring their policies be updated. - - if (frame_scheduler.GetFrameType() != - FrameScheduler::FrameType::kMainFrame) { - return ShouldUpdatePolicy::kYes; - } - - if (signal_ == PerAgentSignal::kDelayOnly) - delegate_.OnSetTimer(frame_scheduler, delay_); - else if (signal_ == PerAgentSignal::kFirstMeaningfulPaint) - SetWaitingForInput(true); - - main_frames_.insert(&frame_scheduler); - - // Only add ordinary page frames to the set of waiting frames, as - // non-ordinary ones don't report any signals. - if (frame_scheduler.IsOrdinary()) - main_frames_waiting_for_signal_.insert(&frame_scheduler); - - return ShouldUpdatePolicy::kYes; - } - - bool ShouldAffectQueue(const MainThreadTaskQueue& task_queue) const { - // Queues that don't have a frame scheduler are, by definition, not - // associated with a frame (or agent). - if (!task_queue.GetFrameScheduler()) - return false; - - if (affected_queue_types_ == PerAgentAffectedQueues::kTimerQueues && - task_queue.GetPrioritisationType() != - PrioritisationType::kJavaScriptTimer) { - return false; - } - - // Don't do anything if all main frames have reached the signal. - if (main_frames_waiting_for_signal_.IsEmpty()) - return false; - - // Otherwise, affect the queue only if it doesn't belong to any main agent. - base::UnguessableToken agent_cluster_id = - task_queue.GetFrameScheduler()->GetAgentClusterId(); - return std::all_of(main_frames_.begin(), main_frames_.end(), - [agent_cluster_id](const FrameSchedulerImpl* frame) { - return frame->GetAgentClusterId() != agent_cluster_id; - }); - } - - ShouldUpdatePolicy OnSignal(const FrameSchedulerImpl& frame_scheduler, - PerAgentSignal signal) { - if (signal != signal_) - return ShouldUpdatePolicy::kNo; - - // If there is no delay, then we have reached the awaited signal. - if (delay_.is_zero()) { - return SignalReached(frame_scheduler); - } - - // No need to update policy if we have to wait for a delay. - delegate_.OnSetTimer(frame_scheduler, delay_); - return ShouldUpdatePolicy::kNo; - } - - ShouldUpdatePolicy SignalReached(const FrameSchedulerImpl& frame_scheduler) { - main_frames_waiting_for_signal_.erase(&frame_scheduler); - if (main_frames_waiting_for_signal_.IsEmpty()) - SetWaitingForInput(false); - - // TODO(talp): If the frame wasn't in the set to begin with (e.g.: because - // an input event cleared it), or if there are still other frames in the - // set, then we may not have to trigger a policy update. - return ShouldUpdatePolicy::kYes; - } - - Delegate& delegate_; - const PerAgentAffectedQueues affected_queue_types_; - const PerAgentSlowDownMethod method_; - const PerAgentSignal signal_; - const base::TimeDelta delay_; - - WTF::HashSet<const FrameSchedulerImpl*> main_frames_; - WTF::HashSet<const FrameSchedulerImpl*> main_frames_waiting_for_signal_; - - base::Lock waiting_for_input_lock_; - PollableThreadSafeFlag waiting_for_input_; - void SetWaitingForInput(bool waiting_for_input) { - if (waiting_for_input_.IsSet() != waiting_for_input) { - base::AutoLock lock(waiting_for_input_lock_); - waiting_for_input_.SetWhileLocked(waiting_for_input); - } - } -}; -} // namespace - -AgentSchedulingStrategy::~AgentSchedulingStrategy() { - VerifyValidSequence(); -} - -std::unique_ptr<AgentSchedulingStrategy> AgentSchedulingStrategy::Create( - Delegate& delegate) { - if (!base::FeatureList::IsEnabled(kPerAgentSchedulingExperiments)) - return std::make_unique<NoOpStrategy>(); - - return std::make_unique<TrackMainFrameSignal>( - delegate, kPerAgentQueues.Get(), kPerAgentMethod.Get(), - kPerAgentSignal.Get(), - base::TimeDelta::FromMilliseconds(kPerAgentDelayMs.Get())); -} - -void AgentSchedulingStrategy::VerifyValidSequence() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(main_thread_sequence_checker_); -} - -} // namespace scheduler -} // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.h deleted file mode 100644 index c37021f6052..00000000000 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.h +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2020 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_AGENT_SCHEDULING_STRATEGY_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_AGENT_SCHEDULING_STRATEGY_H_ - -#include "base/sequence_checker.h" -#include "base/task/sequence_manager/task_queue.h" -#include "base/time/time.h" -#include "base/unguessable_token.h" -#include "third_party/abseil-cpp/absl/types/optional.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_task_queue.h" -#include "third_party/blink/renderer/platform/wtf/casting.h" - -namespace blink { -namespace scheduler { - -// Abstract class that can be consulted to determine task queue priorities and -// scheduling policies, that are based on the queue's Agent. -// Strategies should only be accessed from the main thread. -class PLATFORM_EXPORT AgentSchedulingStrategy { - public: - enum class ShouldUpdatePolicy { - kNo, - kYes, - }; - - class Delegate { - public: - Delegate() = default; - virtual ~Delegate() = default; - - // Delegate should call OnDelayPassed after |delay| has passed, and pass - // |frame_scheduler| as a parameter. - virtual void OnSetTimer(const FrameSchedulerImpl& frame_scheduler, - base::TimeDelta delay) = 0; - }; - - AgentSchedulingStrategy(const AgentSchedulingStrategy&) = delete; - AgentSchedulingStrategy(AgentSchedulingStrategy&&) = delete; - - virtual ~AgentSchedulingStrategy(); - - static std::unique_ptr<AgentSchedulingStrategy> Create(Delegate& delegate); - - // The following functions need to be called as appropriate to manage the - // strategy's internal state. Will return |kYes| when a policy update should - // be triggered. - virtual ShouldUpdatePolicy OnFrameAdded( - const FrameSchedulerImpl& frame_scheduler) WARN_UNUSED_RESULT = 0; - virtual ShouldUpdatePolicy OnFrameRemoved( - const FrameSchedulerImpl& frame_scheduler) WARN_UNUSED_RESULT = 0; - virtual ShouldUpdatePolicy OnMainFrameFirstMeaningfulPaint( - const FrameSchedulerImpl& frame_scheduler) WARN_UNUSED_RESULT = 0; - // FMP is not reported consistently, so input events are used as a failsafe - // to make sure frames aren't considered waiting for FMP indefinitely. Should - // not be called for mouse move events. - virtual ShouldUpdatePolicy OnInputEvent() WARN_UNUSED_RESULT = 0; - virtual ShouldUpdatePolicy OnDocumentChangedInMainFrame( - const FrameSchedulerImpl& frame_scheduler) WARN_UNUSED_RESULT = 0; - virtual ShouldUpdatePolicy OnMainFrameLoad( - const FrameSchedulerImpl& frame_scheduler) WARN_UNUSED_RESULT = 0; - // OnDelayPassed should be called by Delegate after the appropriate delay. - virtual ShouldUpdatePolicy OnDelayPassed( - const FrameSchedulerImpl& frame_scheduler) WARN_UNUSED_RESULT = 0; - - // The following functions should be consulted when making scheduling - // decisions. Will return |absl::optional| containing the desired value, or - // |nullopt| to signify that the original scheduler's decision should not be - // changed. - virtual absl::optional<bool> QueueEnabledState( - const MainThreadTaskQueue& task_queue) const = 0; - virtual absl::optional<base::sequence_manager::TaskQueue::QueuePriority> - QueuePriority(const MainThreadTaskQueue& task_queue) const = 0; - - // Returns true if the strategy is interested in getting input event - // notifications. This is *the only* method that may be called from different - // threads. - virtual bool ShouldNotifyOnInputEvent() const = 0; - - protected: - AgentSchedulingStrategy() = default; - - // Check that the strategy is used from the right (= main) thread. Should be - // called from all public methods except ShouldNotifyOnInput(). - void VerifyValidSequence() const; - - private: - SEQUENCE_CHECKER(main_thread_sequence_checker_); -}; - -} // namespace scheduler -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_AGENT_SCHEDULING_STRATEGY_H_ diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy_unittest.cc deleted file mode 100644 index 9f1e710bb04..00000000000 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy_unittest.cc +++ /dev/null @@ -1,527 +0,0 @@ -#include "third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.h" - -#include <memory> -#include "base/memory/scoped_refptr.h" -#include "base/metrics/field_trial_params.h" -#include "base/test/scoped_feature_list.h" -#include "base/time/time.h" -#include "base/unguessable_token.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" -#include "third_party/blink/renderer/platform/scheduler/common/features.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_task_queue.h" -#include "third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h" -#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h" -#include "third_party/blink/renderer/platform/scheduler/test/fake_frame_scheduler.h" - -namespace blink { -namespace scheduler { - -using FeatureAndParams = ::base::test::ScopedFeatureList::FeatureAndParams; -using ShouldUpdatePolicy = - ::blink::scheduler::AgentSchedulingStrategy::ShouldUpdatePolicy; -using PrioritisationType = - ::blink::scheduler::MainThreadTaskQueue::QueueTraits::PrioritisationType; - -using ::base::FieldTrialParams; -using ::base::sequence_manager::TaskQueue; -using ::base::test::ScopedFeatureList; -using ::testing::_; -using ::testing::NiceMock; -using ::testing::Return; -using ::testing::ReturnRef; -using ::testing::Test; - -namespace { - -class MockDelegate : public AgentSchedulingStrategy::Delegate { - public: - MOCK_METHOD(void, - OnSetTimer, - (const FrameSchedulerImpl& frame_scheduler, - base::TimeDelta delay)); -}; - -class MockFrameSchedulerDelegate : public FrameScheduler::Delegate { - public: - MockFrameSchedulerDelegate() { - ON_CALL(*this, GetAgentClusterId) - .WillByDefault(ReturnRef(agent_cluster_id_)); - } - - MOCK_METHOD(const base::UnguessableToken&, - GetAgentClusterId, - (), - (const, override)); - MOCK_METHOD(ukm::UkmRecorder*, GetUkmRecorder, ()); - MOCK_METHOD(ukm::SourceId, GetUkmSourceId, ()); - MOCK_METHOD(void, UpdateTaskTime, (base::TimeDelta)); - MOCK_METHOD(void, UpdateActiveSchedulerTrackedFeatures, (uint64_t)); - - private: - base::UnguessableToken agent_cluster_id_ = base::UnguessableToken::Create(); -}; - -class MockFrameScheduler : public FrameSchedulerImpl { - public: - explicit MockFrameScheduler(FrameScheduler::FrameType frame_type) - : FrameSchedulerImpl(/*main_thread_scheduler=*/nullptr, - /*parent_page_scheduler=*/nullptr, - /*delegate=*/&delegate_, - /*blame_context=*/nullptr, - /*frame_type=*/frame_type) { - ON_CALL(*this, IsOrdinary).WillByDefault(Return(true)); - } - - MOCK_METHOD(bool, IsOrdinary, (), (const)); - - private: - NiceMock<MockFrameSchedulerDelegate> delegate_; -}; - -} // namespace - -class PerAgentSchedulingBaseTest : public Test { - public: - explicit PerAgentSchedulingBaseTest( - const FieldTrialParams experiment_params) { - feature_list_.InitWithFeaturesAndParameters( - {{kPerAgentSchedulingExperiments, experiment_params}}, {}); - strategy_ = AgentSchedulingStrategy::Create(delegate_); - timer_queue_->SetFrameSchedulerForTest(&subframe_); - non_timer_queue_->SetFrameSchedulerForTest(&subframe_); - } - - protected: - ScopedFeatureList feature_list_; - NiceMock<MockDelegate> delegate_{}; - std::unique_ptr<AgentSchedulingStrategy> strategy_; - NiceMock<MockFrameScheduler> main_frame_{ - FrameScheduler::FrameType::kMainFrame}; - NiceMock<MockFrameScheduler> subframe_{FrameScheduler::FrameType::kSubframe}; - scoped_refptr<MainThreadTaskQueueForTest> timer_queue_{ - new MainThreadTaskQueueForTest(PrioritisationType::kJavaScriptTimer)}; - scoped_refptr<MainThreadTaskQueueForTest> non_timer_queue_{ - new MainThreadTaskQueueForTest(PrioritisationType::kRegular)}; -}; - -class PerAgentDisableTimersUntilTimeoutStrategyTest - : public PerAgentSchedulingBaseTest { - public: - PerAgentDisableTimersUntilTimeoutStrategyTest() - : PerAgentSchedulingBaseTest({{"queues", "timer-queues"}, - {"method", "disable"}, - {"signal", "delay"}, - {"delay_ms", "50"}}) {} -}; - -TEST_F(PerAgentDisableTimersUntilTimeoutStrategyTest, RequestsPolicyUpdate) { - EXPECT_EQ(strategy_->OnFrameAdded(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_), - ShouldUpdatePolicy::kNo); - EXPECT_EQ(strategy_->OnMainFrameLoad(main_frame_), ShouldUpdatePolicy::kNo); - EXPECT_EQ(strategy_->OnDelayPassed(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnFrameRemoved(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnDocumentChangedInMainFrame(main_frame_), - ShouldUpdatePolicy::kYes); -} - -TEST_F(PerAgentDisableTimersUntilTimeoutStrategyTest, InitiatesTimer) { - EXPECT_CALL(delegate_, OnSetTimer(_, base::TimeDelta::FromMilliseconds(50))) - .Times(1); - - ignore_result(strategy_->OnFrameAdded(main_frame_)); -} - -TEST_F(PerAgentDisableTimersUntilTimeoutStrategyTest, - DisablesTimerQueueUntilTimeout) { - ignore_result(strategy_->OnFrameAdded(main_frame_)); - ignore_result(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_)); - - EXPECT_THAT(strategy_->QueueEnabledState(*timer_queue_), - testing::Optional(false)); - EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value()); - - ignore_result(strategy_->OnDelayPassed(main_frame_)); - - EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value()); -} - -class PerAgentDisableTimersUntilFMPStrategyTest - : public PerAgentSchedulingBaseTest { - public: - PerAgentDisableTimersUntilFMPStrategyTest() - : PerAgentSchedulingBaseTest({{"queues", "timer-queues"}, - {"method", "disable"}, - {"signal", "fmp"}}) {} -}; - -TEST_F(PerAgentDisableTimersUntilFMPStrategyTest, RequestsPolicyUpdate) { - EXPECT_EQ(strategy_->OnFrameAdded(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_), - ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnMainFrameLoad(main_frame_), ShouldUpdatePolicy::kNo); - EXPECT_EQ(strategy_->OnFrameRemoved(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnDocumentChangedInMainFrame(main_frame_), - ShouldUpdatePolicy::kYes); - // Only the first input event (since a main frame document was added) should - // cause a policy update. This is necessary as we may get several input event - // notifications, but we don't want them to re-calculate priorities as nothing - // will change. - EXPECT_EQ(strategy_->OnInputEvent(), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnInputEvent(), ShouldUpdatePolicy::kNo); -} - -TEST_F(PerAgentDisableTimersUntilFMPStrategyTest, DisablesTimerQueueUntilFMP) { - ignore_result(strategy_->OnFrameAdded(main_frame_)); - - EXPECT_THAT(strategy_->QueueEnabledState(*timer_queue_), - testing::Optional(false)); - EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value()); - - ignore_result(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_)); - - EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value()); -} - -class PerAgentBestEffortPriorityTimersUntilFMPStrategyTest - : public PerAgentSchedulingBaseTest { - public: - PerAgentBestEffortPriorityTimersUntilFMPStrategyTest() - : PerAgentSchedulingBaseTest({{"queues", "timer-queues"}, - {"method", "best-effort"}, - {"signal", "fmp"}}) {} -}; - -TEST_F(PerAgentBestEffortPriorityTimersUntilFMPStrategyTest, - RequestsPolicyUpdate) { - EXPECT_EQ(strategy_->OnFrameAdded(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_), - ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnMainFrameLoad(main_frame_), ShouldUpdatePolicy::kNo); - EXPECT_EQ(strategy_->OnFrameRemoved(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnDocumentChangedInMainFrame(main_frame_), - ShouldUpdatePolicy::kYes); - // Only the first input event (since a main frame document was added) should - // cause a policy update. This is necessary as we may get several input event - // notifications, but we don't want them to re-calculate priorities as nothing - // will change. - EXPECT_EQ(strategy_->OnInputEvent(), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnInputEvent(), ShouldUpdatePolicy::kNo); -} - -TEST_F(PerAgentBestEffortPriorityTimersUntilFMPStrategyTest, - LowersTimerQueuePriorityUntilFMP) { - ignore_result(strategy_->OnFrameAdded(main_frame_)); - - EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value()); - EXPECT_THAT(strategy_->QueuePriority(*timer_queue_), - testing::Optional(TaskQueue::QueuePriority::kBestEffortPriority)); - EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value()); - - ignore_result(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_)); - - EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value()); -} - -class PerAgentDisableTimersUntilLoadStrategyTest - : public PerAgentSchedulingBaseTest { - public: - PerAgentDisableTimersUntilLoadStrategyTest() - : PerAgentSchedulingBaseTest({{"queues", "timer-queues"}, - {"method", "disable"}, - {"signal", "onload"}}) {} -}; - -TEST_F(PerAgentDisableTimersUntilLoadStrategyTest, RequestsPolicyUpdate) { - EXPECT_EQ(strategy_->OnFrameAdded(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_), - ShouldUpdatePolicy::kNo); - EXPECT_EQ(strategy_->OnMainFrameLoad(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnFrameRemoved(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnDocumentChangedInMainFrame(main_frame_), - ShouldUpdatePolicy::kYes); -} - -TEST_F(PerAgentDisableTimersUntilLoadStrategyTest, DisablesTimerQueue) { - ignore_result(strategy_->OnFrameAdded(main_frame_)); - - EXPECT_THAT(strategy_->QueueEnabledState(*timer_queue_), - testing::Optional(false)); - EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value()); - - ignore_result(strategy_->OnMainFrameLoad(main_frame_)); - - EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value()); -} - -class PerAgentBestEffortPriorityTimersUntilLoadStrategyTest - : public PerAgentSchedulingBaseTest { - public: - PerAgentBestEffortPriorityTimersUntilLoadStrategyTest() - : PerAgentSchedulingBaseTest({{"queues", "timer-queues"}, - {"method", "best-effort"}, - {"signal", "onload"}}) {} -}; - -TEST_F(PerAgentBestEffortPriorityTimersUntilLoadStrategyTest, - RequestsPolicyUpdate) { - EXPECT_EQ(strategy_->OnFrameAdded(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_), - ShouldUpdatePolicy::kNo); - EXPECT_EQ(strategy_->OnMainFrameLoad(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnFrameRemoved(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnDocumentChangedInMainFrame(main_frame_), - ShouldUpdatePolicy::kYes); -} - -TEST_F(PerAgentBestEffortPriorityTimersUntilLoadStrategyTest, - LowersTimerQueuePriority) { - ignore_result(strategy_->OnFrameAdded(main_frame_)); - - EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value()); - EXPECT_THAT(strategy_->QueuePriority(*timer_queue_), - testing::Optional(TaskQueue::QueuePriority::kBestEffortPriority)); - EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value()); - - ignore_result(strategy_->OnMainFrameLoad(main_frame_)); - - EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value()); -} - -class PerAgentDisableAllUntilFMPStrategyTest - : public PerAgentSchedulingBaseTest { - public: - PerAgentDisableAllUntilFMPStrategyTest() - : PerAgentSchedulingBaseTest({{"queues", "all-queues"}, - {"method", "disable"}, - {"signal", "fmp"}}) {} -}; - -TEST_F(PerAgentDisableAllUntilFMPStrategyTest, RequestsPolicyUpdate) { - EXPECT_EQ(strategy_->OnFrameAdded(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_), - ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnMainFrameLoad(main_frame_), ShouldUpdatePolicy::kNo); - EXPECT_EQ(strategy_->OnFrameRemoved(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnDocumentChangedInMainFrame(main_frame_), - ShouldUpdatePolicy::kYes); - // Only the first input event (since a main frame document was added) should - // cause a policy update. This is necessary as we may get several input event - // notifications, but we don't want them to re-calculate priorities as nothing - // will change. - EXPECT_EQ(strategy_->OnInputEvent(), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnInputEvent(), ShouldUpdatePolicy::kNo); -} - -TEST_F(PerAgentDisableAllUntilFMPStrategyTest, DisablesTimerQueueUntilFMP) { - ignore_result(strategy_->OnFrameAdded(main_frame_)); - - EXPECT_THAT(strategy_->QueueEnabledState(*timer_queue_), - testing::Optional(false)); - EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value()); - EXPECT_THAT(strategy_->QueueEnabledState(*non_timer_queue_), - testing::Optional(false)); - EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value()); - - ignore_result(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_)); - - EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value()); -} - -class PerAgentBestEffortPriorityAllUntilFMPStrategyTest - : public PerAgentSchedulingBaseTest { - public: - PerAgentBestEffortPriorityAllUntilFMPStrategyTest() - : PerAgentSchedulingBaseTest({{"queues", "all-queues"}, - {"method", "best-effort"}, - {"signal", "fmp"}}) {} -}; - -TEST_F(PerAgentBestEffortPriorityAllUntilFMPStrategyTest, - RequestsPolicyUpdate) { - EXPECT_EQ(strategy_->OnFrameAdded(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_), - ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnMainFrameLoad(main_frame_), ShouldUpdatePolicy::kNo); - EXPECT_EQ(strategy_->OnFrameRemoved(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnDocumentChangedInMainFrame(main_frame_), - ShouldUpdatePolicy::kYes); - // Only the first input event (since a main frame document was added) should - // cause a policy update. This is necessary as we may get several input event - // notifications, but we don't want them to re-calculate priorities as nothing - // will change. - EXPECT_EQ(strategy_->OnInputEvent(), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnInputEvent(), ShouldUpdatePolicy::kNo); -} - -TEST_F(PerAgentBestEffortPriorityAllUntilFMPStrategyTest, - LowersTimerQueuePriorityUntilFMP) { - ignore_result(strategy_->OnFrameAdded(main_frame_)); - - EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value()); - EXPECT_THAT(strategy_->QueuePriority(*timer_queue_), - testing::Optional(TaskQueue::QueuePriority::kBestEffortPriority)); - EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value()); - EXPECT_THAT(strategy_->QueuePriority(*non_timer_queue_), - testing::Optional(TaskQueue::QueuePriority::kBestEffortPriority)); - - ignore_result(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_)); - - EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value()); -} - -class PerAgentDisableAllUntilLoadStrategyTest - : public PerAgentSchedulingBaseTest { - public: - PerAgentDisableAllUntilLoadStrategyTest() - : PerAgentSchedulingBaseTest({{"queues", "all-queues"}, - {"method", "disable"}, - {"signal", "onload"}}) {} -}; - -TEST_F(PerAgentDisableAllUntilLoadStrategyTest, RequestsPolicyUpdate) { - EXPECT_EQ(strategy_->OnFrameAdded(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_), - ShouldUpdatePolicy::kNo); - EXPECT_EQ(strategy_->OnMainFrameLoad(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnFrameRemoved(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnDocumentChangedInMainFrame(main_frame_), - ShouldUpdatePolicy::kYes); -} - -TEST_F(PerAgentDisableAllUntilLoadStrategyTest, DisablesTimerQueue) { - ignore_result(strategy_->OnFrameAdded(main_frame_)); - - EXPECT_THAT(strategy_->QueueEnabledState(*timer_queue_), - testing::Optional(false)); - EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value()); - EXPECT_THAT(strategy_->QueueEnabledState(*non_timer_queue_), - testing::Optional(false)); - EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value()); - - ignore_result(strategy_->OnMainFrameLoad(main_frame_)); - - EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value()); -} - -class PerAgentBestEffortPriorityAllUntilLoadStrategyTest - : public PerAgentSchedulingBaseTest { - public: - PerAgentBestEffortPriorityAllUntilLoadStrategyTest() - : PerAgentSchedulingBaseTest({{"queues", "all-queues"}, - {"method", "best-effort"}, - {"signal", "onload"}}) {} -}; - -TEST_F(PerAgentBestEffortPriorityAllUntilLoadStrategyTest, - RequestsPolicyUpdate) { - EXPECT_EQ(strategy_->OnFrameAdded(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_), - ShouldUpdatePolicy::kNo); - EXPECT_EQ(strategy_->OnMainFrameLoad(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnFrameRemoved(main_frame_), ShouldUpdatePolicy::kYes); - EXPECT_EQ(strategy_->OnDocumentChangedInMainFrame(main_frame_), - ShouldUpdatePolicy::kYes); -} - -TEST_F(PerAgentBestEffortPriorityAllUntilLoadStrategyTest, - LowersTimerQueuePriority) { - ignore_result(strategy_->OnFrameAdded(main_frame_)); - - EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value()); - EXPECT_THAT(strategy_->QueuePriority(*timer_queue_), - testing::Optional(TaskQueue::QueuePriority::kBestEffortPriority)); - EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value()); - EXPECT_THAT(strategy_->QueuePriority(*non_timer_queue_), - testing::Optional(TaskQueue::QueuePriority::kBestEffortPriority)); - - ignore_result(strategy_->OnMainFrameLoad(main_frame_)); - - EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value()); -} - -class PerAgentDefaultIsNoOpStrategyTest : public Test { - public: - PerAgentDefaultIsNoOpStrategyTest() { - timer_queue_->SetFrameSchedulerForTest(&subframe_); - } - - protected: - NiceMock<MockDelegate> delegate_{}; - std::unique_ptr<AgentSchedulingStrategy> strategy_ = - AgentSchedulingStrategy::Create(delegate_); - MockFrameScheduler main_frame_{FrameScheduler::FrameType::kMainFrame}; - NiceMock<MockFrameScheduler> subframe_{FrameScheduler::FrameType::kSubframe}; - scoped_refptr<MainThreadTaskQueueForTest> timer_queue_{ - new MainThreadTaskQueueForTest(PrioritisationType::kJavaScriptTimer)}; -}; - -TEST_F(PerAgentDefaultIsNoOpStrategyTest, DoesntRequestPolicyUpdate) { - EXPECT_EQ(strategy_->OnFrameAdded(main_frame_), ShouldUpdatePolicy::kNo); - EXPECT_EQ(strategy_->OnMainFrameFirstMeaningfulPaint(main_frame_), - ShouldUpdatePolicy::kNo); - EXPECT_EQ(strategy_->OnFrameRemoved(main_frame_), ShouldUpdatePolicy::kNo); - EXPECT_EQ(strategy_->OnDocumentChangedInMainFrame(main_frame_), - ShouldUpdatePolicy::kNo); - EXPECT_EQ(strategy_->OnInputEvent(), ShouldUpdatePolicy::kNo); -} - -TEST_F(PerAgentDefaultIsNoOpStrategyTest, DoesntModifyPolicyDecisions) { - EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value()); -} - -class PerAgentNonOrdinaryPageTest : public PerAgentSchedulingBaseTest { - public: - PerAgentNonOrdinaryPageTest() - : PerAgentSchedulingBaseTest({{"queues", "timer-queues"}, - {"method", "disable"}, - {"signal", "onload"}}) { - ON_CALL(non_ordinary_frame_scheduler_, IsOrdinary) - .WillByDefault(Return(false)); - } - - protected: - NiceMock<MockFrameScheduler> non_ordinary_frame_scheduler_{ - FrameScheduler::FrameType::kMainFrame}; -}; - -TEST_F(PerAgentNonOrdinaryPageTest, DoesntWaitForNonOrdinaryFrames) { - EXPECT_EQ(strategy_->OnFrameAdded(non_ordinary_frame_scheduler_), - ShouldUpdatePolicy::kYes); - EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value()); - EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value()); -} - -} // namespace scheduler -} // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/attribution_group.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/attribution_group.h index 4d5b3b0bf4b..dffe694b09d 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/attribution_group.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/attribution_group.h @@ -38,7 +38,7 @@ struct AttributionGroupHash { STATIC_ONLY(AttributionGroupHash); static unsigned GetHash(const AttributionGroup& group) { - return group.attribution.GetHash(); + return static_cast<unsigned>(group.attribution.GetHash()); } static bool Equal(const AttributionGroup& a, const AttributionGroup& b) { diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.cc index a638dcbb7dd..4790db3430d 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.cc @@ -17,8 +17,7 @@ namespace scheduler { AutoAdvancingVirtualTimeDomain::AutoAdvancingVirtualTimeDomain( base::Time initial_time, base::TimeTicks initial_time_ticks, - SchedulerHelper* helper, - BaseTimeOverridePolicy policy) + SchedulerHelper* helper) : task_starvation_count_(0), max_task_starvation_count_(0), can_advance_virtual_time_(true), @@ -30,14 +29,15 @@ AutoAdvancingVirtualTimeDomain::AutoAdvancingVirtualTimeDomain( DCHECK_EQ(AutoAdvancingVirtualTimeDomain::g_time_domain_, nullptr); AutoAdvancingVirtualTimeDomain::g_time_domain_ = this; - // GetVirtualTime / GetVirtualTimeTicks access g_time_domain_. - std::atomic_thread_fence(std::memory_order_seq_cst); + // GetVirtualTime / GetVirtualTimeTicks access |g_time_domain_|. Ensure that + // the write of |g_time_domain_| above propagates before the overrides to + // GetVirtualTime / GetVirtualTimeTicks are put in place below, by + // preventing reordering via a release fence. + std::atomic_thread_fence(std::memory_order_release); - if (policy == BaseTimeOverridePolicy::OVERRIDE) { - time_overrides_ = std::make_unique<base::subtle::ScopedTimeClockOverrides>( - &AutoAdvancingVirtualTimeDomain::GetVirtualTime, - &AutoAdvancingVirtualTimeDomain::GetVirtualTimeTicks, nullptr); - } + time_overrides_ = std::make_unique<base::subtle::ScopedTimeClockOverrides>( + &AutoAdvancingVirtualTimeDomain::GetVirtualTime, + &AutoAdvancingVirtualTimeDomain::GetVirtualTimeTicks, nullptr); helper_->AddTaskObserver(this); } @@ -47,10 +47,6 @@ AutoAdvancingVirtualTimeDomain::~AutoAdvancingVirtualTimeDomain() { time_overrides_.reset(); - // GetVirtualTime / GetVirtualTimeTicks (the functions we may have - // temporariliy installed in the constructor) access g_time_domain_. - std::atomic_thread_fence(std::memory_order_seq_cst); - DCHECK_EQ(AutoAdvancingVirtualTimeDomain::g_time_domain_, this); AutoAdvancingVirtualTimeDomain::g_time_domain_ = nullptr; } @@ -188,12 +184,22 @@ AutoAdvancingVirtualTimeDomain* AutoAdvancingVirtualTimeDomain::g_time_domain_ = // static base::TimeTicks AutoAdvancingVirtualTimeDomain::GetVirtualTimeTicks() { + // ScopedTimeClockOverrides sets the override to GetVirtualTimeTicks() as a + // relaxed atomic operation. To ensure that the read of |g_time_domain_| is + // not reordered with the read of the override, place an acquire fence before + // loading |g_time_domain_|. + std::atomic_thread_fence(std::memory_order_acquire); DCHECK(AutoAdvancingVirtualTimeDomain::g_time_domain_); return AutoAdvancingVirtualTimeDomain::g_time_domain_->Now(); } // static base::Time AutoAdvancingVirtualTimeDomain::GetVirtualTime() { + // ScopedTimeClockOverrides sets the override to GetVirtualTimeTicks() as a + // relaxed atomic operation. To ensure that the read of |g_time_domain_| is + // not reordered with the read of the override, place an acquire fence before + // loading |g_time_domain_|. + std::atomic_thread_fence(std::memory_order_acquire); DCHECK(AutoAdvancingVirtualTimeDomain::g_time_domain_); return AutoAdvancingVirtualTimeDomain::g_time_domain_->Date(); } diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h index f62e52db83a..30cfb0ac60d 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h @@ -5,7 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_AUTO_ADVANCING_VIRTUAL_TIME_DOMAIN_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_AUTO_ADVANCING_VIRTUAL_TIME_DOMAIN_H_ -#include "base/macros.h" #include "base/task/sequence_manager/time_domain.h" #include "base/task/task_observer.h" #include "base/time/time_override.h" @@ -16,7 +15,12 @@ namespace scheduler { class SchedulerHelper; // A time domain that runs tasks sequentially in time order but doesn't sleep -// between delayed tasks. +// between delayed tasks. Because AutoAdvancingVirtualTimeDomain may override +// Time/TimeTicks in a multi-threaded context, it must outlive any thread that +// may call Time::Now() or TimeTicks::Now(). In practice, this means +// AutoAdvancingVirtualTimeDomain can never be destroyed in production and acts +// as a one-way switch. In tests, it should only be destroyed after all threads +// have been joined. // // KEY: A-E are delayed tasks // | A B C D E (Execution with RealTimeDomain) @@ -28,12 +32,13 @@ class PLATFORM_EXPORT AutoAdvancingVirtualTimeDomain : public base::sequence_manager::TimeDomain, public base::TaskObserver { public: - enum class BaseTimeOverridePolicy { OVERRIDE, DO_NOT_OVERRIDE }; - AutoAdvancingVirtualTimeDomain(base::Time initial_time, base::TimeTicks initial_time_ticks, - SchedulerHelper* helper, - BaseTimeOverridePolicy policy); + SchedulerHelper* helper); + AutoAdvancingVirtualTimeDomain(const AutoAdvancingVirtualTimeDomain&) = + delete; + AutoAdvancingVirtualTimeDomain& operator=( + const AutoAdvancingVirtualTimeDomain&) = delete; ~AutoAdvancingVirtualTimeDomain() override; // Controls whether or not virtual time is allowed to advance, when the @@ -43,10 +48,10 @@ class PLATFORM_EXPORT AutoAdvancingVirtualTimeDomain // If non-null, virtual time may not advance past |virtual_time_fence|. void SetVirtualTimeFence(base::TimeTicks virtual_time_fence); - // The maximum number amount of delayed task starvation we will allow. - // NB a value of 0 allows infinite starvation. A reasonable value for this in - // practice is around 1000 tasks, which should only affect rendering of the - // heaviest pages. + // The maximum number of tasks we will run before advancing virtual time in + // order to avoid starving delayed tasks. NB a value of 0 allows infinite + // starvation. A reasonable value for this in practice is around 1000 tasks, + // which should only affect rendering of the heaviest pages. void SetMaxVirtualTimeTaskStarvationCount(int max_task_starvation_count); // Updates to min(NextDelayedTaskTime, |new_virtual_time|) if thats ahead of @@ -108,8 +113,6 @@ class PLATFORM_EXPORT AutoAdvancingVirtualTimeDomain base::Time previous_time_; std::unique_ptr<base::subtle::ScopedTimeClockOverrides> time_overrides_; - - DISALLOW_COPY_AND_ASSIGN(AutoAdvancingVirtualTimeDomain); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain_unittest.cc index 6afa2f817de..ef8155a2ef4 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain_unittest.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain_unittest.cc @@ -44,8 +44,7 @@ class AutoAdvancingVirtualTimeDomainTest : public testing::Test { initial_time_ticks_ = test_task_runner_->NowTicks(); auto_advancing_time_domain_ = std::make_unique<AutoAdvancingVirtualTimeDomain>( - initial_time_, initial_time_ticks_, scheduler_helper_.get(), - AutoAdvancingVirtualTimeDomain::BaseTimeOverridePolicy::OVERRIDE); + initial_time_, initial_time_ticks_, scheduler_helper_.get()); scheduler_helper_->RegisterTimeDomain(auto_advancing_time_domain_.get()); task_queue_->SetTimeDomain(auto_advancing_time_domain_.get()); } diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.cc index 0827874b665..b4c37e0f7da 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.cc @@ -37,9 +37,6 @@ CompositorPriorityExperiments::GetExperimentFromFeatureList() { kVeryHighPriorityForCompositingAlternating)) { return Experiment::kVeryHighPriorityForCompositingAlternating; } else if (base::FeatureList::IsEnabled( - kVeryHighPriorityForCompositingBudget)) { - return Experiment::kVeryHighPriorityForCompositingBudget; - } else if (base::FeatureList::IsEnabled( kVeryHighPriorityForCompositingAfterDelay)) { return Experiment::kVeryHighPriorityForCompositingAfterDelay; } else { @@ -66,29 +63,12 @@ QueuePriority CompositorPriorityExperiments::GetCompositorPriority() const { return alternating_compositor_priority_; case Experiment::kVeryHighPriorityForCompositingAfterDelay: return delay_compositor_priority_; - case Experiment::kVeryHighPriorityForCompositingBudget: - return budget_compositor_priority_; case Experiment::kNone: NOTREACHED(); return QueuePriority::kNormalPriority; } } -void CompositorPriorityExperiments::OnMainThreadSchedulerInitialized() { - if (experiment_ == Experiment::kVeryHighPriorityForCompositingBudget) { - budget_pool_controller_ = std::make_unique<CompositorBudgetPoolController>( - this, scheduler_, scheduler_->CompositorTaskQueue().get(), - &scheduler_->tracing_controller_, - base::TimeDelta::FromMilliseconds( - kInitialCompositorBudgetInMilliseconds.Get()), - kCompositorBudgetRecoveryRate.Get()); - } -} - -void CompositorPriorityExperiments::OnMainThreadSchedulerShutdown() { - budget_pool_controller_.reset(); -} - void CompositorPriorityExperiments::OnWillBeginMainFrame() { will_begin_main_frame_ = true; } @@ -144,82 +124,10 @@ void CompositorPriorityExperiments::OnTaskCompleted( if (current_compositor_priority != delay_compositor_priority_) scheduler_->OnCompositorPriorityExperimentUpdateCompositorPriority(); return; - case Experiment::kVeryHighPriorityForCompositingBudget: - budget_pool_controller_->OnTaskCompleted(queue, task_timing, - have_seen_stop_signal); - return; case Experiment::kNone: return; } } -void CompositorPriorityExperiments::OnBudgetExhausted() { - // Compositor will still be allowed to run tasks if the budget is exhausted - // if there is no other higher priority work to be done. If a compositor task - // is run while the budget is exhausted it will still deplete the budget which - // will keep it at a normal priority for longer. - budget_compositor_priority_ = QueuePriority::kNormalPriority; - scheduler_->OnCompositorPriorityExperimentUpdateCompositorPriority(); -} - -void CompositorPriorityExperiments::OnBudgetReplenished() { - budget_compositor_priority_ = QueuePriority::kVeryHighPriority; - scheduler_->OnCompositorPriorityExperimentUpdateCompositorPriority(); -} - -CompositorPriorityExperiments::CompositorBudgetPoolController:: - CompositorBudgetPoolController( - CompositorPriorityExperiments* experiment, - MainThreadSchedulerImpl* scheduler, - MainThreadTaskQueue* compositor_queue, - TraceableVariableController* tracing_controller, - base::TimeDelta min_budget, - double budget_recovery_rate) - : experiment_(experiment) { - DCHECK_EQ(compositor_queue->queue_type(), - MainThreadTaskQueue::QueueType::kCompositor); - base::TimeTicks now = scheduler->GetTickClock()->NowTicks(); - - compositor_budget_pool_ = std::make_unique<CPUTimeBudgetPool>( - "CompositorBudgetPool", this, tracing_controller, now); - compositor_budget_pool_->SetMinBudgetLevelToRun(now, min_budget); - compositor_budget_pool_->SetTimeBudgetRecoveryRate(now, budget_recovery_rate); - compositor_queue->AddToBudgetPool(now, compositor_budget_pool_.get()); -} - -CompositorPriorityExperiments::CompositorBudgetPoolController:: - ~CompositorBudgetPoolController() = default; - -void CompositorPriorityExperiments::CompositorBudgetPoolController:: - UpdateQueueSchedulingLifecycleState(base::TimeTicks now, TaskQueue* queue) { - UpdateCompositorBudgetState(now); -} - -void CompositorPriorityExperiments::CompositorBudgetPoolController:: - UpdateCompositorBudgetState(base::TimeTicks now) { - bool is_exhausted = - !compositor_budget_pool_->CanRunTasksAt(now, false /* is_wake_up */); - if (is_exhausted_ == is_exhausted) - return; - - is_exhausted_ = is_exhausted; - if (is_exhausted_) { - experiment_->OnBudgetExhausted(); - return; - } - experiment_->OnBudgetReplenished(); -} - -void CompositorPriorityExperiments::CompositorBudgetPoolController:: - OnTaskCompleted(MainThreadTaskQueue* queue, - TaskQueue::TaskTiming* task_timing, - bool have_seen_stop_signal) { - if (have_seen_stop_signal) { - compositor_budget_pool_->RecordTaskRunTime( - nullptr, task_timing->start_time(), task_timing->end_time()); - } - UpdateCompositorBudgetState(task_timing->end_time()); -} - } // namespace scheduler } // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.h index 96280a3980d..4d0f8597e94 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.h @@ -8,9 +8,6 @@ #include "base/task/sequence_manager/task_queue.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h" -#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h" -#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_controller.h" -#include "third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" @@ -20,7 +17,6 @@ namespace scheduler { using TaskQueue = base::sequence_manager::TaskQueue; using QueuePriority = base::sequence_manager::TaskQueue::QueuePriority; -class CPUTimeBudgetPool; class MainThreadSchedulerImpl; class MainThreadTaskQueue; @@ -37,7 +33,6 @@ class PLATFORM_EXPORT CompositorPriorityExperiments { kVeryHighPriorityForCompositingWhenFast, kVeryHighPriorityForCompositingAlternating, kVeryHighPriorityForCompositingAfterDelay, - kVeryHighPriorityForCompositingBudget }; bool IsExperimentActive() const; @@ -54,47 +49,7 @@ class PLATFORM_EXPORT CompositorPriorityExperiments { void OnWillBeginMainFrame(); - void OnMainThreadSchedulerInitialized(); - void OnMainThreadSchedulerShutdown(); - - void OnBudgetExhausted(); - void OnBudgetReplenished(); - private: - class CompositorBudgetPoolController : public BudgetPoolController { - public: - explicit CompositorBudgetPoolController( - CompositorPriorityExperiments* experiment, - MainThreadSchedulerImpl* scheduler, - MainThreadTaskQueue* compositor_queue, - TraceableVariableController* tracing_controller, - base::TimeDelta min_budget, - double budget_recovery_rate); - ~CompositorBudgetPoolController() override; - - void UpdateQueueSchedulingLifecycleState(base::TimeTicks now, - TaskQueue* queue) override; - - void UpdateCompositorBudgetState(base::TimeTicks now); - - void OnTaskCompleted(MainThreadTaskQueue* queue, - TaskQueue::TaskTiming* task_timing, - bool have_seen_stop_signal); - - // Unimplemented methods. - void AddQueueToBudgetPool(TaskQueue* queue, - BudgetPool* budget_pool) override {} - void RemoveQueueFromBudgetPool(TaskQueue* queue, - BudgetPool* budget_pool) override {} - void UnregisterBudgetPool(BudgetPool* budget_pool) override {} - bool IsThrottled(TaskQueue* queue) const override { return false; } - - private: - CompositorPriorityExperiments* experiment_; - std::unique_ptr<CPUTimeBudgetPool> compositor_budget_pool_; - bool is_exhausted_ = false; - }; - static Experiment GetExperimentFromFeatureList(); enum class StopSignalType { kAnyCompositorTask, kBeginMainFrameTask }; @@ -110,9 +65,6 @@ class PLATFORM_EXPORT CompositorPriorityExperiments { base::TimeTicks last_compositor_task_time_; base::TimeDelta prioritize_compositing_after_delay_length_; - QueuePriority budget_compositor_priority_ = QueuePriority::kVeryHighPriority; - std::unique_ptr<CompositorBudgetPoolController> budget_pool_controller_; - const StopSignalType stop_signal_; bool will_begin_main_frame_ = false; }; diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner.h index 04f33623a6b..97e5305c97a 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner.h @@ -6,7 +6,6 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_DEADLINE_TASK_RUNNER_H_ #include "base/callback.h" -#include "base/macros.h" #include "base/single_thread_task_runner.h" #include "base/time/time.h" #include "third_party/blink/renderer/platform/platform_export.h" @@ -23,6 +22,8 @@ class PLATFORM_EXPORT DeadlineTaskRunner { public: DeadlineTaskRunner(const base::RepeatingClosure& callback, scoped_refptr<base::SingleThreadTaskRunner> task_runner); + DeadlineTaskRunner(const DeadlineTaskRunner&) = delete; + DeadlineTaskRunner& operator=(const DeadlineTaskRunner&) = delete; ~DeadlineTaskRunner(); @@ -44,8 +45,6 @@ class PLATFORM_EXPORT DeadlineTaskRunner { base::RepeatingClosure callback_; base::TimeTicks deadline_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - - DISALLOW_COPY_AND_ASSIGN(DeadlineTaskRunner); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.cc index ca1fdabd15a..72d2472bbbc 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.cc @@ -41,10 +41,7 @@ FindInPageBudgetPoolController::FindInPageBudgetPoolController( base::TimeTicks now = scheduler_->GetTickClock()->NowTicks(); find_in_page_budget_pool_ = std::make_unique<CPUTimeBudgetPool>( - "FindInPageBudgetPool", this, &scheduler_->tracing_controller_, now); - // Set no minimum budget for find-in-page, so that we won't delay running - // find-in-page tasks when budget is available. - find_in_page_budget_pool_->SetMinBudgetLevelToRun(now, base::TimeDelta()); + "FindInPageBudgetPool", &scheduler_->tracing_controller_, now); find_in_page_budget_pool_->SetMaxBudgetLevel(now, kFindInPageMaxBudget); find_in_page_budget_pool_->SetTimeBudgetRecoveryRate( now, kFindInPageBudgetRecoveryRate); @@ -60,12 +57,12 @@ void FindInPageBudgetPoolController::OnTaskCompleted( DCHECK(find_in_page_budget_pool_); if (queue->GetPrioritisationType() == MainThreadTaskQueue::QueueTraits::PrioritisationType::kFindInPage) { - find_in_page_budget_pool_->RecordTaskRunTime( - nullptr, task_timing->start_time(), task_timing->end_time()); + find_in_page_budget_pool_->RecordTaskRunTime(task_timing->start_time(), + task_timing->end_time()); } - bool is_exhausted = !find_in_page_budget_pool_->CanRunTasksAt( - task_timing->end_time(), false /* is_wake_up */); + bool is_exhausted = + !find_in_page_budget_pool_->CanRunTasksAt(task_timing->end_time()); QueuePriority task_priority = is_exhausted ? kFindInPageBudgetExhaustedPriority : kFindInPageBudgetNotExhaustedPriority; diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.h index 5042b6a0e39..37a04f8ccb2 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.h @@ -7,7 +7,6 @@ #include "base/task/sequence_manager/task_queue.h" #include "third_party/blink/renderer/platform/platform_export.h" -#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_controller.h" #include "third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h" @@ -20,8 +19,7 @@ using QueuePriority = base::sequence_manager::TaskQueue::QueuePriority; class CPUTimeBudgetPool; class MainThreadSchedulerImpl; -class PLATFORM_EXPORT FindInPageBudgetPoolController - : public BudgetPoolController { +class PLATFORM_EXPORT FindInPageBudgetPoolController { public: static constexpr auto kFindInPageBudgetNotExhaustedPriority = QueuePriority::kVeryHighPriority; @@ -29,25 +27,13 @@ class PLATFORM_EXPORT FindInPageBudgetPoolController QueuePriority::kNormalPriority; explicit FindInPageBudgetPoolController(MainThreadSchedulerImpl* scheduler); - ~FindInPageBudgetPoolController() override; + ~FindInPageBudgetPoolController(); void OnTaskCompleted(MainThreadTaskQueue* queue, TaskQueue::TaskTiming* task_timing); QueuePriority CurrentTaskPriority() { return task_priority_; } - // Unimplemented methods. - // TODO(crbug.com/1056512): Remove these functions once we factor out the - // budget calculating logic from BudgetPoolController. - void UpdateQueueSchedulingLifecycleState(base::TimeTicks now, - TaskQueue* queue) override {} - void AddQueueToBudgetPool(TaskQueue* queue, - BudgetPool* budget_pool) override {} - void RemoveQueueFromBudgetPool(TaskQueue* queue, - BudgetPool* budget_pool) override {} - void UnregisterBudgetPool(BudgetPool* budget_pool) override {} - bool IsThrottled(TaskQueue* queue) const override { return false; } - private: MainThreadSchedulerImpl* scheduler_; // Not owned. std::unique_ptr<CPUTimeBudgetPool> find_in_page_budget_pool_; diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.cc index 631724eda29..ca7405afacd 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.cc @@ -4,7 +4,6 @@ #include "third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h" -#include "base/macros.h" #include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h" namespace blink { @@ -31,8 +30,6 @@ const char* FrameOriginTypeToString(FrameOriginType origin) { return "same-origin-to-main-frame"; case FrameOriginType::kCrossOriginToMainFrame: return "cross-origin-to-main-frame"; - case FrameOriginType::kCount: - NOTREACHED(); } NOTREACHED(); return nullptr; diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h index 573ba2f4afd..a6ccf25c2db 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h @@ -16,8 +16,7 @@ enum class FrameOriginType { kMainFrame = 0, kSameOriginToMainFrame = 1, kCrossOriginToMainFrame = 2, - // TODO(dcheng): Get rid of this and use the kMaxValue idiom. - kCount = 3, + kMaxValue = kCrossOriginToMainFrame, }; FrameOriginType GetFrameOriginType(FrameScheduler* frame_scheduler); diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc index 99e62ba04e6..7ba83284ffb 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc @@ -30,11 +30,11 @@ #include "third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/find_in_page_budget_pool_controller.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_web_scheduling_task_queue_impl.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/page_visibility_state.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/resource_loading_task_runner_handle_impl.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.h" -#include "third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_task_queue_impl.h" #include "third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h" #include "third_party/perfetto/include/perfetto/tracing/traced_value.h" @@ -193,6 +193,11 @@ FrameSchedulerImpl::FrameSchedulerImpl( "FrameScheduler.KeepActive", &tracing_controller_, KeepActiveStateToString), + waiting_for_dom_content_loaded_( + true, + "FrameScheduler.WaitingForDOMContentLoaded", + &tracing_controller_, + YesNoStateToString), waiting_for_contentful_paint_(true, "FrameScheduler.WaitingForContentfulPaint", &tracing_controller_, @@ -201,6 +206,10 @@ FrameSchedulerImpl::FrameSchedulerImpl( "FrameScheduler.WaitingForMeaningfulPaint", &tracing_controller_, YesNoStateToString), + waiting_for_load_(true, + "FrameScheduler.WaitingForLoad", + &tracing_controller_, + YesNoStateToString), loading_power_mode_voter_( power_scheduler::PowerModeArbiter::GetInstance()->NewVoter( "PowerModeVoter.Loading")) { @@ -277,12 +286,39 @@ void FrameSchedulerImpl::RemoveThrottleableQueueFromBudgetPools( : base::sequence_manager::LazyNow(base::TimeTicks::Now()); if (cpu_time_budget_pool) { - cpu_time_budget_pool->RemoveQueue(lazy_now.Now(), - task_queue->GetTaskQueue()); + task_queue->RemoveFromBudgetPool(lazy_now.Now(), cpu_time_budget_pool); } - parent_page_scheduler_->RemoveQueueFromWakeUpBudgetPool( - task_queue, frame_origin_type_, &lazy_now); + parent_page_scheduler_->RemoveQueueFromWakeUpBudgetPool(task_queue, + &lazy_now); +} + +void FrameSchedulerImpl::MoveTaskQueuesToCorrectWakeUpBudgetPool() { + base::sequence_manager::LazyNow lazy_now( + main_thread_scheduler_->tick_clock()); + + // The WakeUpBudgetPool is selected based on origin state, frame visibility + // and page background state. + // + // For each throttled queue, check if it should be in a different + // WakeUpBudgetPool and make the necessary adjustments. + for (const auto& task_queue_and_voter : + frame_task_queue_controller_->GetAllTaskQueuesAndVoters()) { + auto* task_queue = task_queue_and_voter.first; + if (!task_queue->CanBeThrottled()) + continue; + + auto* new_wake_up_budget_pool = parent_page_scheduler_->GetWakeUpBudgetPool( + task_queue, frame_origin_type_, frame_visible_); + if (task_queue->GetWakeUpBudgetPool() == new_wake_up_budget_pool) { + continue; + } + + parent_page_scheduler_->RemoveQueueFromWakeUpBudgetPool(task_queue, + &lazy_now); + parent_page_scheduler_->AddQueueToWakeUpBudgetPool( + task_queue, frame_origin_type_, frame_visible_, &lazy_now); + } } void FrameSchedulerImpl::SetFrameVisible(bool frame_visible) { @@ -291,6 +327,8 @@ void FrameSchedulerImpl::SetFrameVisible(bool frame_visible) { return; UMA_HISTOGRAM_BOOLEAN("RendererScheduler.IPC.FrameVisibility", frame_visible); frame_visible_ = frame_visible; + + MoveTaskQueuesToCorrectWakeUpBudgetPool(); UpdatePolicy(); } @@ -305,39 +343,13 @@ void FrameSchedulerImpl::SetCrossOriginToMainFrame(bool 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); - } - } - + MoveTaskQueuesToCorrectWakeUpBudgetPool(); UpdatePolicy(); } @@ -386,12 +398,8 @@ QueueTraits FrameSchedulerImpl::CreateQueueTraitsForTaskType(TaskType type) { return ThrottleableTaskQueueTraits().SetPrioritisationType( QueueTraits::PrioritisationType::kBestEffort); case TaskType::kJavascriptTimerDelayedLowNesting: - return ThrottleableTaskQueueTraits() - .SetPrioritisationType( - QueueTraits::PrioritisationType::kJavaScriptTimer) - .SetCanBeIntensivelyThrottled( - IsIntensiveWakeUpThrottlingEnabled() && - CanIntensivelyThrottleLowNestingLevel()); + return ThrottleableTaskQueueTraits().SetPrioritisationType( + QueueTraits::PrioritisationType::kJavaScriptTimer); case TaskType::kJavascriptTimerDelayedHighNesting: return ThrottleableTaskQueueTraits() .SetPrioritisationType( @@ -493,6 +501,27 @@ QueueTraits FrameSchedulerImpl::CreateQueueTraitsForTaskType(TaskType type) { // Navigation IPCs do not run using virtual time to avoid hanging. case TaskType::kInternalNavigationAssociatedUnfreezable: return DoesNotUseVirtualTimeTaskQueueTraits(); + case TaskType::kInternalPostMessageForwarding: + // postMessages to remote frames hop through the scheduler so that any + // IPCs generated in the same task arrive first. These tasks must be + // pausable in order to maintain this invariant, otherwise they might run + // in a nested event loop before the task completes, e.g. debugger + // breakpoints or javascript dialogs. + if (base::FeatureList::IsEnabled( + kDisablePrioritizedPostMessageForwarding)) { + // This matches the pre-kInternalPostMessageForwarding behavior. + return PausableTaskQueueTraits(); + } else { + // Freezing this task type would prevent transmission of postMessages to + // remote frames that occurred in unfreezable tasks or from tasks that + // ran prior to being frozen (e.g. freeze event handler), which is not + // desirable. The messages are still queued on the receiving side, which + // is where frozenness should be assessed. + return PausableTaskQueueTraits() + .SetCanBeFrozen(false) + .SetPrioritisationType( + QueueTraits::PrioritisationType::kPostMessageForwarding); + } case TaskType::kDeprecatedNone: case TaskType::kMainThreadTaskQueueV8: case TaskType::kMainThreadTaskQueueCompositor: @@ -512,7 +541,6 @@ QueueTraits FrameSchedulerImpl::CreateQueueTraitsForTaskType(TaskType type) { // The associated TaskRunner should be obtained by creating a // WebSchedulingTaskQueue with CreateWebSchedulingTaskQueue(). case TaskType::kExperimentalWebScheduling: - case TaskType::kCount: // Not a valid frame-level TaskType. NOTREACHED(); return QueueTraits(); @@ -632,16 +660,24 @@ void FrameSchedulerImpl::DidCommitProvisionalLoad( loading_power_mode_voter_->ResetVoteAfterTimeout( power_scheduler::PowerModeVoter::kStuckLoadingTimeout); + waiting_for_dom_content_loaded_ = true; waiting_for_contentful_paint_ = true; waiting_for_meaningful_paint_ = true; + waiting_for_load_ = true; + + // If DeprioritizeDOMTimersDuringPageLoading is enabled, UpdatePolicy() + // needs to be called to change JavaScript timer task queues to low priority + // during reload and other navigations. + // + // TODO(shaseley): Think about merging this with MainThreadSchedulerImpl's + // policy update. + if (base::FeatureList::IsEnabled(kDeprioritizeDOMTimersDuringPageLoading)) { + UpdatePolicy(); + } } if (is_main_frame && !is_same_document) { task_time_ = base::TimeDelta(); - // Ignore result here, based on the assumption that - // MTSI::DidCommitProvisionalLoad will trigger an update policy. - ignore_result(main_thread_scheduler_->agent_scheduling_strategy() - .OnDocumentChangedInMainFrame(*this)); } main_thread_scheduler_->DidCommitProvisionalLoad( @@ -941,9 +977,20 @@ SchedulingLifecycleState FrameSchedulerImpl::CalculateLifecycleState( void FrameSchedulerImpl::OnFirstContentfulPaintInMainFrame() { waiting_for_contentful_paint_ = false; DCHECK_EQ(GetFrameType(), FrameScheduler::FrameType::kMainFrame); + parent_page_scheduler_->OnFirstContentfulPaintInMainFrame(); main_thread_scheduler_->OnMainFramePaint(); } +void FrameSchedulerImpl::OnDomContentLoaded() { + waiting_for_dom_content_loaded_ = false; + + if (base::FeatureList::IsEnabled(kDeprioritizeDOMTimersDuringPageLoading) && + kDeprioritizeDOMTimersPhase.Get() == + DeprioritizeDOMTimersPhase::kOnDOMContentLoaded) { + UpdatePolicy(); + } +} + void FrameSchedulerImpl::OnFirstMeaningfulPaint() { waiting_for_meaningful_paint_ = false; @@ -951,20 +998,20 @@ void FrameSchedulerImpl::OnFirstMeaningfulPaint() { return; main_thread_scheduler_->OnMainFramePaint(); - - if (main_thread_scheduler_->agent_scheduling_strategy() - .OnMainFrameFirstMeaningfulPaint(*this) == - AgentSchedulingStrategy::ShouldUpdatePolicy::kYes) { - main_thread_scheduler_->OnAgentStrategyUpdated(); - } } void FrameSchedulerImpl::OnLoad() { - if (GetFrameType() == FrameScheduler::FrameType::kMainFrame) { - // TODO(talp): Once MTSI::UpdatePolicyLocked is refactored, this can notify - // the agent strategy directly and, if necessary, trigger the queue priority - // update. - main_thread_scheduler_->OnMainFrameLoad(*this); + waiting_for_load_ = false; + + // FrameSchedulerImpl::OnFirstContentfulPaint() is NOT guaranteed to be called + // during the loading process, so we also try to do the recomputation in case + // of the DeprioritizeDOMTimersPhase::kFirstContentfulPaint option. + if (base::FeatureList::IsEnabled(kDeprioritizeDOMTimersDuringPageLoading) && + (kDeprioritizeDOMTimersPhase.Get() == + DeprioritizeDOMTimersPhase::kOnLoad || + kDeprioritizeDOMTimersPhase.Get() == + DeprioritizeDOMTimersPhase::kFirstContentfulPaint)) { + UpdatePolicy(); } loading_power_mode_voter_->ResetVoteAfterTimeout( @@ -988,18 +1035,15 @@ bool FrameSchedulerImpl::IsOrdinary() const { bool FrameSchedulerImpl::ShouldThrottleTaskQueues() const { DCHECK(parent_page_scheduler_); + if (parent_page_scheduler_->ThrottleForegroundTimers()) + return true; if (!RuntimeEnabledFeatures::TimerThrottlingForBackgroundTabsEnabled()) return false; if (parent_page_scheduler_->IsAudioPlaying()) return false; if (!parent_page_scheduler_->IsPageVisible()) return true; - if (base::FeatureList::IsEnabled(kThrottleVisibleNotFocusedTimers) && - !parent_page_scheduler_->IsPageFocused()) { - return true; - } - return RuntimeEnabledFeatures::TimerThrottlingForHiddenFramesEnabled() && - !frame_visible_ && IsCrossOriginToMainFrame(); + return !frame_visible_ && IsCrossOriginToMainFrame(); } bool FrameSchedulerImpl::IsExemptFromBudgetBasedThrottling() const { @@ -1029,6 +1073,9 @@ TaskQueue::QueuePriority FrameSchedulerImpl::ComputePriority( return TaskQueue::QueuePriority::kVeryHighPriority; case MainThreadTaskQueue::QueueTraits::PrioritisationType::kBestEffort: return TaskQueue::QueuePriority::kBestEffortPriority; + case MainThreadTaskQueue::QueueTraits::PrioritisationType:: + kPostMessageForwarding: + return TaskQueue::QueuePriority::kVeryHighPriority; default: break; } @@ -1128,14 +1175,6 @@ TaskQueue::QueuePriority FrameSchedulerImpl::ComputePriority( } } - // Consult per-agent scheduling strategy to see if it wants to affect queue - // priority. Done here to avoid interfering with other policy decisions. - absl::optional<TaskQueue::QueuePriority> per_agent_priority = - main_thread_scheduler_->agent_scheduling_strategy().QueuePriority( - *task_queue); - if (per_agent_priority.has_value()) - return per_agent_priority.value(); - if (task_queue->GetPrioritisationType() == MainThreadTaskQueue::QueueTraits::PrioritisationType::kLoadingControl) { return main_thread_scheduler_->should_prioritize_loading_with_compositing() @@ -1160,6 +1199,23 @@ TaskQueue::QueuePriority FrameSchedulerImpl::ComputePriority( return TaskQueue::QueuePriority::kHighestPriority; } + // Deprioritize JS timer tasks to speed up the page loading process. + if (base::FeatureList::IsEnabled(kDeprioritizeDOMTimersDuringPageLoading) && + task_queue->GetPrioritisationType() == + MainThreadTaskQueue::QueueTraits::PrioritisationType:: + kJavaScriptTimer && + waiting_for_load_ && + (kDeprioritizeDOMTimersPhase.Get() == + DeprioritizeDOMTimersPhase::kOnLoad || + (kDeprioritizeDOMTimersPhase.Get() == + DeprioritizeDOMTimersPhase::kOnDOMContentLoaded && + waiting_for_dom_content_loaded_) || + (kDeprioritizeDOMTimersPhase.Get() == + DeprioritizeDOMTimersPhase::kFirstContentfulPaint && + parent_page_scheduler_->IsWaitingForMainFrameContentfulPaint()))) { + return TaskQueue::QueuePriority::kLowPriority; + } + if (task_queue->GetPrioritisationType() == MainThreadTaskQueue::QueueTraits::PrioritisationType::kInput && base::FeatureList::IsEnabled( @@ -1235,12 +1291,11 @@ void FrameSchedulerImpl::OnTaskQueueCreated( CPUTimeBudgetPool* cpu_time_budget_pool = parent_page_scheduler_->background_cpu_time_budget_pool(); if (cpu_time_budget_pool) { - cpu_time_budget_pool->AddQueue(lazy_now.Now(), - task_queue->GetTaskQueue()); + task_queue->AddToBudgetPool(lazy_now.Now(), cpu_time_budget_pool); } parent_page_scheduler_->AddQueueToWakeUpBudgetPool( - task_queue, frame_origin_type_, &lazy_now); + task_queue, frame_origin_type_, frame_visible_, &lazy_now); if (task_queues_throttled_) { MainThreadTaskQueue::ThrottleHandle handle = task_queue->Throttle(); @@ -1342,12 +1397,24 @@ FrameSchedulerImpl::GetDocumentBoundWeakPtr() { std::unique_ptr<WebSchedulingTaskQueue> FrameSchedulerImpl::CreateWebSchedulingTaskQueue( WebSchedulingPriority priority) { - // Use QueueTraits here that are the same as postMessage, which is one current - // method for scheduling script. - scoped_refptr<MainThreadTaskQueue> task_queue = + // The QueueTraits for scheduler.postTask() are similar to those of + // setTimeout() (deferrable queue traits + throttling for delayed tasks), with + // the following differences: + // 1. All delayed tasks are intensively throttled (no nesting-level exception + // or policy/flag opt-out) + // 2. There is no separate PrioritisationType (prioritization is based on the + // WebSchedulingPriority, which is only set for these task queues) + scoped_refptr<MainThreadTaskQueue> immediate_task_queue = frame_task_queue_controller_->NewWebSchedulingTaskQueue( - PausableTaskQueueTraits(), priority); - return std::make_unique<WebSchedulingTaskQueueImpl>(task_queue->AsWeakPtr()); + DeferrableTaskQueueTraits(), priority); + scoped_refptr<MainThreadTaskQueue> delayed_task_queue = + frame_task_queue_controller_->NewWebSchedulingTaskQueue( + DeferrableTaskQueueTraits() + .SetCanBeThrottled(true) + .SetCanBeIntensivelyThrottled(true), + priority); + return std::make_unique<MainThreadWebSchedulingTaskQueueImpl>( + immediate_task_queue->AsWeakPtr(), delayed_task_queue->AsWeakPtr()); } void FrameSchedulerImpl::OnWebSchedulingTaskQueuePriorityChanged( @@ -1356,6 +1423,18 @@ void FrameSchedulerImpl::OnWebSchedulingTaskQueuePriorityChanged( frame_task_queue_controller_->GetQueueEnabledVoter(queue)); } +void FrameSchedulerImpl::OnWebSchedulingTaskQueueDestroyed( + MainThreadTaskQueue* queue) { + if (queue->CanBeThrottled()) + RemoveThrottleableQueueFromBudgetPools(queue); + + CleanUpQueue(queue); + + // After this is called, the queue will be destroyed. Do not attempt + // to use it further. + frame_task_queue_controller_->RemoveWebSchedulingTaskQueue(queue); +} + const base::UnguessableToken& FrameSchedulerImpl::GetAgentClusterId() const { if (!delegate_) return base::UnguessableToken::Null(); diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h index fb3459936b3..3d605531049 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h @@ -11,7 +11,6 @@ #include <utility> #include "base/containers/flat_map.h" -#include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" @@ -19,7 +18,6 @@ #include "components/power_scheduler/power_mode_voter.h" #include "net/base/request_priority.h" #include "services/metrics/public/cpp/ukm_source_id.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/scheduler/common/tracing_helper.h" @@ -78,6 +76,8 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler, FrameScheduler::Delegate* delegate, base::trace_event::BlameContext* blame_context, FrameScheduler::FrameType frame_type); + FrameSchedulerImpl(const FrameSchedulerImpl&) = delete; + FrameSchedulerImpl& operator=(const FrameSchedulerImpl&) = delete; ~FrameSchedulerImpl() override; // FrameOrWorkerScheduler implementation: @@ -122,6 +122,7 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler, WebScopedVirtualTimePauser::VirtualTaskDuration duration) override; void OnFirstContentfulPaintInMainFrame() override; + void OnDomContentLoaded() override; void OnFirstMeaningfulPaint() override; void OnLoad() override; bool IsWaitingForContentfulPaint() const; @@ -199,6 +200,7 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler, std::unique_ptr<WebSchedulingTaskQueue> CreateWebSchedulingTaskQueue( WebSchedulingPriority) override; void OnWebSchedulingTaskQueuePriorityChanged(MainThreadTaskQueue*); + void OnWebSchedulingTaskQueueDestroyed(MainThreadTaskQueue*); const base::UnguessableToken& GetAgentClusterId() const; @@ -242,12 +244,14 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler, // loading in the frame until the reference is released during destruction. explicit PauseSubresourceLoadingHandleImpl( base::WeakPtr<FrameSchedulerImpl> frame_scheduler); + PauseSubresourceLoadingHandleImpl( + const PauseSubresourceLoadingHandleImpl&) = delete; + PauseSubresourceLoadingHandleImpl& operator=( + const PauseSubresourceLoadingHandleImpl&) = delete; ~PauseSubresourceLoadingHandleImpl() override; private: base::WeakPtr<FrameSchedulerImpl> frame_scheduler_; - - DISALLOW_COPY_AND_ASSIGN(PauseSubresourceLoadingHandleImpl); }; void DetachFromPageScheduler(); @@ -292,6 +296,8 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler, void NotifyDelegateAboutFeaturesAfterCurrentTask(); + void MoveTaskQueuesToCorrectWakeUpBudgetPool(); + // Create QueueTraits for the default (non-finch) task queues. static MainThreadTaskQueue::QueueTraits ThrottleableTaskQueueTraits(); static MainThreadTaskQueue::QueueTraits DeferrableTaskQueueTraits(); @@ -373,9 +379,12 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler, page_keep_active_for_tracing_; TraceableState<bool, TracingCategoryName::kInfo> + waiting_for_dom_content_loaded_; + TraceableState<bool, TracingCategoryName::kInfo> waiting_for_contentful_paint_; TraceableState<bool, TracingCategoryName::kInfo> waiting_for_meaningful_paint_; + TraceableState<bool, TracingCategoryName::kInfo> waiting_for_load_; std::unique_ptr<power_scheduler::PowerModeVoter> loading_power_mode_voter_; @@ -390,8 +399,6 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler, invalidating_on_bfcache_restore_weak_factory_{this}; mutable base::WeakPtrFactory<FrameSchedulerImpl> weak_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(FrameSchedulerImpl); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc index cdd2232bff4..16cb3343af1 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc @@ -16,6 +16,7 @@ #include "base/metrics/field_trial_param_associator.h" #include "base/metrics/field_trial_params.h" #include "base/run_loop.h" +#include "base/single_thread_task_runner.h" #include "base/task/sequence_manager/test/sequence_manager_for_test.h" #include "base/task/thread_pool.h" #include "base/test/bind.h" @@ -23,6 +24,7 @@ #include "base/test/scoped_command_line.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" +#include "base/time/time.h" #include "base/unguessable_token.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -58,6 +60,8 @@ namespace { constexpr base::TimeDelta kDefaultThrottledWakeUpInterval = PageSchedulerImpl::kDefaultThrottledWakeUpInterval; +constexpr base::TimeDelta kIntensiveThrottledWakeUpInterval = + PageSchedulerImpl::kIntensiveThrottledWakeUpInterval; constexpr auto kShortDelay = base::TimeDelta::FromMilliseconds(10); // This is a wrapper around MainThreadSchedulerImpl::CreatePageScheduler, that @@ -149,10 +153,11 @@ constexpr TaskType kAllFrameTaskTypes[] = { TaskType::kInternalHighPriorityLocalFrame, TaskType::kInternalInputBlocking, TaskType::kWakeLock, - TaskType::kWebGPU}; + TaskType::kWebGPU, + TaskType::kInternalPostMessageForwarding}; static_assert( - static_cast<int>(TaskType::kCount) == 79, + static_cast<int>(TaskType::kMaxValue) == 79, "When adding a TaskType, make sure that kAllFrameTaskTypes is updated."); void AppendToVectorTestTask(Vector<String>* vector, String value) { @@ -411,6 +416,27 @@ class FrameSchedulerImplTest : public testing::Test { PrioritisationType::kJavaScriptTimer)); } + scoped_refptr<MainThreadTaskQueue> + JavaScriptTimerNormalThrottleableTaskQueueForFrame( + FrameSchedulerImpl* frame_scheduler) { + return GetTaskQueueForFrame(frame_scheduler, + TaskType::kJavascriptTimerDelayedLowNesting); + } + + scoped_refptr<MainThreadTaskQueue> + JavaScriptTimerIntensivelyThrottleableTaskQueueForFrame( + FrameSchedulerImpl* frame_scheduler) { + return GetTaskQueueForFrame(frame_scheduler, + TaskType::kJavascriptTimerDelayedHighNesting); + } + + scoped_refptr<MainThreadTaskQueue> + JavaScriptTimerNonThrottleableTaskQueueForFrame( + FrameSchedulerImpl* frame_scheduler) { + return GetTaskQueueForFrame(frame_scheduler, + TaskType::kJavascriptTimerImmediate); + } + scoped_refptr<MainThreadTaskQueue> LoadingTaskQueue() { return GetTaskQueue(FrameSchedulerImpl::LoadingTaskQueueTraits()); } @@ -448,6 +474,12 @@ class FrameSchedulerImplTest : public testing::Test { return frame_scheduler_->GetTaskQueue(type); } + scoped_refptr<MainThreadTaskQueue> GetTaskQueueForFrame( + FrameSchedulerImpl* frame_scheduler, + TaskType type) { + return frame_scheduler->GetTaskQueue(type); + } + std::unique_ptr<ResourceLoadingTaskRunnerHandleImpl> GetResourceLoadingTaskRunnerHandleImpl() { return frame_scheduler_->CreateResourceLoadingTaskRunnerHandleImpl(); @@ -480,6 +512,21 @@ class FrameSchedulerImplTest : public testing::Test { /*is_web_history_inert_commit=*/false, navigation_type); } + void DidCommitProvisionalLoadForFrame( + FrameSchedulerImpl* frame_scheduler, + FrameScheduler::NavigationType navigation_type) { + frame_scheduler->DidCommitProvisionalLoad( + /*is_web_history_inert_commit=*/false, navigation_type); + } + + void OnDomContentLoadedForFrame(FrameSchedulerImpl* frame_scheduler) { + frame_scheduler->OnDomContentLoaded(); + } + + void OnLoadForFrame(FrameSchedulerImpl* frame_scheduler) { + frame_scheduler->OnLoad(); + } + base::test::ScopedFeatureList& scoped_feature_list() { return feature_list_; } base::test::ScopedFeatureList feature_list_; @@ -564,19 +611,9 @@ class FrameSchedulerImplTestWithIntensiveWakeUpThrottlingBase public: using Super = FrameSchedulerImplTest; - explicit FrameSchedulerImplTestWithIntensiveWakeUpThrottlingBase( - bool can_intensively_throttle_low_nesting_level) - : FrameSchedulerImplTest( - features::kIntensiveWakeUpThrottling, - // If |can_intensively_throttle_low_nesting_level| is true, set the - // feature param to "true". Otherwise, test the default behavior (no - // feature params). - can_intensively_throttle_low_nesting_level - ? base::FieldTrialParams( - {{kIntensiveWakeUpThrottling_CanIntensivelyThrottleLowNestingLevel_Name, - "true"}}) - : base::FieldTrialParams(), - {features::kStopInBackground}) {} + FrameSchedulerImplTestWithIntensiveWakeUpThrottlingBase() + : FrameSchedulerImplTest({features::kIntensiveWakeUpThrottling}, + {features::kStopInBackground}) {} void SetUp() override { Super::SetUp(); @@ -591,17 +628,12 @@ class FrameSchedulerImplTestWithIntensiveWakeUpThrottlingBase const int kNumTasks = 5; const base::TimeDelta kGracePeriod = GetIntensiveWakeUpThrottlingGracePeriod(); - const base::TimeDelta kIntensiveThrottlingDurationBetweenWakeUps = - GetIntensiveWakeUpThrottlingDurationBetweenWakeUps(); }; // Test param for FrameSchedulerImplTestWithIntensiveWakeUpThrottling struct IntensiveWakeUpThrottlingTestParam { // TaskType used to obtain TaskRunners from the FrameScheduler. TaskType task_type; - // Whether the feature param to allow throttling of timers with a low nesting - // level should be set to "true" at the beginning of the test. - bool can_intensively_throttle_low_nesting_level; // Whether it is expected that tasks will be intensively throttled. bool is_intensive_throttling_expected; }; @@ -610,28 +642,51 @@ class FrameSchedulerImplTestWithIntensiveWakeUpThrottling : public FrameSchedulerImplTestWithIntensiveWakeUpThrottlingBase, public ::testing::WithParamInterface<IntensiveWakeUpThrottlingTestParam> { public: - FrameSchedulerImplTestWithIntensiveWakeUpThrottling() - : FrameSchedulerImplTestWithIntensiveWakeUpThrottlingBase( - GetParam().can_intensively_throttle_low_nesting_level) {} + FrameSchedulerImplTestWithIntensiveWakeUpThrottling() = default; TaskType GetTaskType() const { return GetParam().task_type; } bool IsIntensiveThrottlingExpected() const { return GetParam().is_intensive_throttling_expected; } + // Get the TaskRunner from |frame_scheduler_| using the test's task type + // parameter. + scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() { + return GetTaskRunner(frame_scheduler_.get()); + } + + // Get the TaskRunner from the provided |frame_scheduler| using the test's + // task type parameter. + scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner( + FrameSchedulerImpl* frame_scheduler) { + const TaskType task_type = GetTaskType(); + if (task_type == TaskType::kExperimentalWebScheduling) { + test_web_scheduling_task_queues_.push_back( + frame_scheduler->CreateWebSchedulingTaskQueue( + WebSchedulingPriority::kUserVisiblePriority)); + return test_web_scheduling_task_queues_.back()->GetTaskRunner(); + } + return frame_scheduler->GetTaskRunner(task_type); + } + base::TimeDelta GetExpectedWakeUpInterval() const { if (IsIntensiveThrottlingExpected()) - return kIntensiveThrottlingDurationBetweenWakeUps; + return kIntensiveThrottledWakeUpInterval; return kDefaultThrottledWakeUpInterval; } + + private: + // Store web scheduling task queues that are created for tests so + // they do not get destroyed. Destroying them before their tasks finish + // running will break throttling. + Vector<std::unique_ptr<WebSchedulingTaskQueue>> + test_web_scheduling_task_queues_; }; class FrameSchedulerImplTestWithIntensiveWakeUpThrottlingPolicyOverride : public FrameSchedulerImplTestWithIntensiveWakeUpThrottlingBase { public: - FrameSchedulerImplTestWithIntensiveWakeUpThrottlingPolicyOverride() - : FrameSchedulerImplTestWithIntensiveWakeUpThrottlingBase( - /* can_intensively_throttle_low_nesting_level=*/false) {} + FrameSchedulerImplTestWithIntensiveWakeUpThrottlingPolicyOverride() = default; // This should only be called once per test, and prior to the // PageSchedulerImpl logic actually parsing the policy switch. @@ -657,14 +712,12 @@ class FrameSchedulerImplTestWithIntensiveWakeUpThrottlingPolicyOverride // We test both (ExplicitInit/LazyInit) of them. TEST_F(FrameSchedulerImplTest, PageVisible) { - ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true); EXPECT_FALSE(throttleable_task_queue()); LazyInitThrottleableTaskQueue(); EXPECT_FALSE(IsThrottled()); } TEST_F(FrameSchedulerImplTest, PageHidden_ExplicitInit) { - ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true); LazyInitThrottleableTaskQueue(); EXPECT_FALSE(IsThrottled()); page_scheduler_->SetPageVisible(false); @@ -672,14 +725,12 @@ TEST_F(FrameSchedulerImplTest, PageHidden_ExplicitInit) { } TEST_F(FrameSchedulerImplTest, PageHidden_LazyInit) { - ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(false); page_scheduler_->SetPageVisible(false); LazyInitThrottleableTaskQueue(); EXPECT_TRUE(IsThrottled()); } TEST_F(FrameSchedulerImplTest, PageHiddenThenVisible_ExplicitInit) { - ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(false); LazyInitThrottleableTaskQueue(); EXPECT_FALSE(IsThrottled()); page_scheduler_->SetPageVisible(false); @@ -692,7 +743,6 @@ TEST_F(FrameSchedulerImplTest, PageHiddenThenVisible_ExplicitInit) { TEST_F(FrameSchedulerImplTest, FrameHiddenThenVisible_CrossOrigin_ExplicitInit) { - ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true); LazyInitThrottleableTaskQueue(); EXPECT_FALSE(IsThrottled()); frame_scheduler_->SetFrameVisible(false); @@ -708,33 +758,13 @@ TEST_F(FrameSchedulerImplTest, } TEST_F(FrameSchedulerImplTest, FrameHidden_CrossOrigin_LazyInit) { - ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true); frame_scheduler_->SetFrameVisible(false); frame_scheduler_->SetCrossOriginToMainFrame(true); LazyInitThrottleableTaskQueue(); EXPECT_TRUE(IsThrottled()); } -TEST_F(FrameSchedulerImplTest, - FrameHidden_CrossOrigin_NoThrottling_ExplicitInit) { - ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(false); - LazyInitThrottleableTaskQueue(); - EXPECT_FALSE(IsThrottled()); - frame_scheduler_->SetFrameVisible(false); - frame_scheduler_->SetCrossOriginToMainFrame(true); - EXPECT_FALSE(IsThrottled()); -} - -TEST_F(FrameSchedulerImplTest, FrameHidden_CrossOrigin_NoThrottling_LazyInit) { - ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(false); - frame_scheduler_->SetFrameVisible(false); - frame_scheduler_->SetCrossOriginToMainFrame(true); - LazyInitThrottleableTaskQueue(); - EXPECT_FALSE(IsThrottled()); -} - TEST_F(FrameSchedulerImplTest, FrameHidden_SameOrigin_ExplicitInit) { - ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true); LazyInitThrottleableTaskQueue(); EXPECT_FALSE(IsThrottled()); frame_scheduler_->SetFrameVisible(false); @@ -742,14 +772,12 @@ TEST_F(FrameSchedulerImplTest, FrameHidden_SameOrigin_ExplicitInit) { } TEST_F(FrameSchedulerImplTest, FrameHidden_SameOrigin_LazyInit) { - ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true); frame_scheduler_->SetFrameVisible(false); LazyInitThrottleableTaskQueue(); EXPECT_FALSE(IsThrottled()); } TEST_F(FrameSchedulerImplTest, FrameVisible_CrossOrigin_ExplicitInit) { - ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true); LazyInitThrottleableTaskQueue(); EXPECT_FALSE(IsThrottled()); EXPECT_TRUE(throttleable_task_queue()); @@ -760,7 +788,6 @@ TEST_F(FrameSchedulerImplTest, FrameVisible_CrossOrigin_ExplicitInit) { } TEST_F(FrameSchedulerImplTest, FrameVisible_CrossOrigin_LazyInit) { - ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true); frame_scheduler_->SetFrameVisible(true); frame_scheduler_->SetCrossOriginToMainFrame(true); LazyInitThrottleableTaskQueue(); @@ -844,8 +871,6 @@ void RePostTask(scoped_refptr<base::SingleThreadTaskRunner> task_runner, // Disable the kStopInBackground feature because it hides the effect of // intensive wake up throttling. TEST_P(FrameSchedulerImplStopInBackgroundDisabledTest, ThrottledTaskExecution) { - constexpr auto kTaskPeriod = base::TimeDelta::FromSeconds(1); - // This TaskRunner is throttled. const scoped_refptr<base::SingleThreadTaskRunner> task_runner = frame_scheduler_->GetTaskRunner(GetParam()); @@ -859,7 +884,7 @@ TEST_P(FrameSchedulerImplStopInBackgroundDisabledTest, ThrottledTaskExecution) { int num_remaining_tasks = base::TimeDelta::FromSeconds( kIntensiveWakeUpThrottling_GracePeriodSeconds_Default) - .IntDiv(kTaskPeriod); + .IntDiv(kDefaultThrottledWakeUpInterval); task_runner->PostDelayedTask( FROM_HERE, base::BindOnce(&RePostTask, task_runner, kShortDelay, @@ -869,7 +894,7 @@ TEST_P(FrameSchedulerImplStopInBackgroundDisabledTest, ThrottledTaskExecution) { // A task should run every second. while (num_remaining_tasks > 0) { int previous_num_remaining_tasks = num_remaining_tasks; - task_environment_.FastForwardBy(kTaskPeriod); + task_environment_.FastForwardBy(kDefaultThrottledWakeUpInterval); EXPECT_EQ(previous_num_remaining_tasks - 1, num_remaining_tasks); } @@ -886,9 +911,8 @@ TEST_P(FrameSchedulerImplStopInBackgroundDisabledTest, ThrottledTaskExecution) { // otherwise. const base::TimeDelta expected_period_after_grace_period = (GetParam() == TaskType::kJavascriptTimerDelayedLowNesting) - ? kTaskPeriod - : base::TimeDelta::FromSeconds( - kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds_Default); + ? kDefaultThrottledWakeUpInterval + : kIntensiveThrottledWakeUpInterval; while (num_remaining_tasks > 0) { int previous_num_remaining_tasks = num_remaining_tasks; @@ -911,13 +935,13 @@ TEST_F(FrameSchedulerImplTest, FreezeForegroundOnlyTasks) { ForegroundOnlyTaskQueue()->GetTaskRunnerWithDefaultTaskType()->PostTask( FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter))); - page_scheduler_->SetPageVisible(false); + frame_scheduler_->SetFrameVisible(false); EXPECT_EQ(0, counter); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, counter); - page_scheduler_->SetPageVisible(true); + frame_scheduler_->SetFrameVisible(true); EXPECT_EQ(0, counter); base::RunLoop().RunUntilIdle(); @@ -2767,7 +2791,8 @@ class WebSchedulingTaskQueueTest : public FrameSchedulerImplTest { // - 'V': UserVisible // - 'B': Background void PostWebSchedulingTestTasks(Vector<String>* run_order, - const String& task_descriptor) { + const String& task_descriptor, + base::TimeDelta delay = base::TimeDelta()) { std::istringstream stream(task_descriptor.Utf8()); while (!stream.eof()) { std::string task; @@ -2787,9 +2812,11 @@ class WebSchedulingTaskQueueTest : public FrameSchedulerImplTest { EXPECT_FALSE(true); return; } - web_scheduling_task_runners_[static_cast<int>(priority)]->PostTask( - FROM_HERE, base::BindOnce(&AppendToVectorTestTask, run_order, - String::FromUTF8(task))); + web_scheduling_task_runners_[static_cast<int>(priority)]->PostDelayedTask( + FROM_HERE, + base::BindOnce(&AppendToVectorTestTask, run_order, + String::FromUTF8(task)), + delay); } } @@ -2821,12 +2848,26 @@ TEST_F(WebSchedulingTaskQueueTest, DynamicTaskPriorityOrder) { testing::ElementsAre("V1", "V2", "B1", "B2", "U1", "U2")); } -// Verify that tasks posted with TaskType::kJavascriptTimerDelayed* run at the -// expected time when throttled. +TEST_F(WebSchedulingTaskQueueTest, DynamicTaskPriorityOrderDelayedTasks) { + Vector<String> run_order; + + PostWebSchedulingTestTasks(&run_order, "U1 U2 V1 V2", + base::TimeDelta::FromMilliseconds(5)); + task_queues_[static_cast<int>(WebSchedulingPriority::kUserBlockingPriority)] + ->SetPriority(WebSchedulingPriority::kBackgroundPriority); + + task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(5)); + + EXPECT_THAT(run_order, testing::ElementsAre("V1", "V2", "U1", "U2")); +} + +// Verify that tasks posted with TaskType::kJavascriptTimerDelayed* and +// delayed web scheduling tasks run at the expected time when throttled. TEST_F(FrameSchedulerImplTest, ThrottledJSTimerTasksRunTime) { constexpr TaskType kJavaScriptTimerTaskTypes[] = { TaskType::kJavascriptTimerDelayedLowNesting, - TaskType::kJavascriptTimerDelayedHighNesting}; + TaskType::kJavascriptTimerDelayedHighNesting, + TaskType::kExperimentalWebScheduling}; // Snap the time to a multiple of 1 second. Otherwise, the exact run time // of throttled tasks after hiding the page will vary. @@ -2838,10 +2879,20 @@ TEST_F(FrameSchedulerImplTest, ThrottledJSTimerTasksRunTime) { std::map<TaskType, std::vector<base::TimeTicks>> run_times; - // Post tasks with each Javascript Timer Task Type. + // Create the web scheduler task queue outside of the scope of the for loop. + // This is necessary because otherwise the queue is deleted before tasks run, + // and this breaks throttling. + std::unique_ptr<WebSchedulingTaskQueue> web_scheduling_task_queue = + frame_scheduler_->CreateWebSchedulingTaskQueue( + WebSchedulingPriority::kUserVisiblePriority); + + // Post tasks with each Javascript Timer Task Type and with a + // WebSchedulingTaskQueue. for (TaskType task_type : kJavaScriptTimerTaskTypes) { const scoped_refptr<base::SingleThreadTaskRunner> task_runner = - frame_scheduler_->GetTaskRunner(task_type); + task_type == TaskType::kExperimentalWebScheduling + ? web_scheduling_task_queue->GetTaskRunner() + : frame_scheduler_->GetTaskRunner(task_type); // Note: Taking the address of an element in |run_times| is safe because // inserting elements in a map does not invalidate references. @@ -2950,12 +3001,12 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, // Throttled TaskRunner to which tasks are posted in this test. const scoped_refptr<base::SingleThreadTaskRunner> task_runner = - frame_scheduler_->GetTaskRunner(GetTaskType()); + GetTaskRunner(); // Snap the time to a multiple of - // |kIntensiveThrottlingDurationBetweenWakeUps|. Otherwise, the time at which + // |kIntensiveThrottledWakeUpInterval|. Otherwise, the time at which // tasks can run after throttling is enabled will vary. - FastForwardToAlignedTime(kIntensiveThrottlingDurationBetweenWakeUps); + FastForwardToAlignedTime(kIntensiveThrottledWakeUpInterval); const base::TimeTicks test_start = base::TimeTicks::Now(); // Hide the page. This starts the delay to throttle background wake ups. @@ -2975,12 +3026,13 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, } task_environment_.FastForwardBy(kGracePeriod); - EXPECT_THAT(run_times, testing::ElementsAre( - scope_start + base::TimeDelta::FromSeconds(1), - scope_start + base::TimeDelta::FromSeconds(2), - scope_start + base::TimeDelta::FromSeconds(3), - scope_start + base::TimeDelta::FromSeconds(4), - scope_start + base::TimeDelta::FromSeconds(5))); + EXPECT_THAT(run_times, + testing::ElementsAre( + scope_start + kDefaultThrottledWakeUpInterval, + scope_start + 2 * kDefaultThrottledWakeUpInterval, + scope_start + 3 * kDefaultThrottledWakeUpInterval, + scope_start + 4 * kDefaultThrottledWakeUpInterval, + scope_start + 5 * kDefaultThrottledWakeUpInterval)); } // After the grace period: @@ -3015,7 +3067,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, kShortDelay + i * kDefaultThrottledWakeUpInterval); } - FastForwardToAlignedTime(kIntensiveThrottlingDurationBetweenWakeUps); + FastForwardToAlignedTime(kIntensiveThrottledWakeUpInterval); if (IsIntensiveThrottlingExpected()) { const base::TimeTicks aligned_time = @@ -3046,7 +3098,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, base::BindOnce(&RecordRunTime, &run_times), kDefaultThrottledWakeUpInterval); - task_environment_.FastForwardBy(kIntensiveThrottlingDurationBetweenWakeUps); + task_environment_.FastForwardBy(kIntensiveThrottledWakeUpInterval); EXPECT_THAT(run_times, testing::ElementsAre(scope_start + GetExpectedWakeUpInterval())); @@ -3062,8 +3114,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, std::vector<base::TimeTicks> run_times; const base::TimeDelta kLongDelay = - kIntensiveThrottlingDurationBetweenWakeUps * 5 + - kDefaultThrottledWakeUpInterval; + kIntensiveThrottledWakeUpInterval * 5 + kDefaultThrottledWakeUpInterval; task_runner->PostDelayedTask( FROM_HERE, base::BindOnce(&RecordRunTime, &run_times), kLongDelay); @@ -3090,7 +3141,6 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, FROM_HERE, base::BindOnce(&RecordRunTime, &run_times), kDefaultThrottledWakeUpInterval * (i + 1)); } - page_scheduler_->OnTitleOrFaviconUpdated(); }), kDefaultThrottledWakeUpInterval); @@ -3128,12 +3178,12 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, // Throttled TaskRunner to which tasks are posted in this test. const scoped_refptr<base::SingleThreadTaskRunner> task_runner = - frame_scheduler_->GetTaskRunner(GetTaskType()); + GetTaskRunner(); // Snap the time to a multiple of - // |kIntensiveThrottlingDurationBetweenWakeUps|. Otherwise, the time at which + // |kIntensiveThrottledWakeUpInterval|. Otherwise, the time at which // tasks can run after throttling is enabled will vary. - FastForwardToAlignedTime(kIntensiveThrottlingDurationBetweenWakeUps); + FastForwardToAlignedTime(kIntensiveThrottledWakeUpInterval); const base::TimeTicks test_start = base::TimeTicks::Now(); // Hide the page. This starts the delay to throttle background wake ups. @@ -3176,7 +3226,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, base::BindOnce(&RecordRunTime, &run_times), kDefaultThrottledWakeUpInterval); - task_environment_.FastForwardBy(kIntensiveThrottlingDurationBetweenWakeUps); + task_environment_.FastForwardBy(kIntensiveThrottledWakeUpInterval); EXPECT_THAT(run_times, testing::ElementsAre(scope_start + GetExpectedWakeUpInterval())); } @@ -3195,11 +3245,11 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, kShortDelay + i * kDefaultThrottledWakeUpInterval); } - task_environment_.FastForwardBy(kIntensiveThrottlingDurationBetweenWakeUps); + task_environment_.FastForwardBy(kIntensiveThrottledWakeUpInterval); if (IsIntensiveThrottlingExpected()) { const base::TimeTicks aligned_time = - scope_start + kIntensiveThrottlingDurationBetweenWakeUps; + scope_start + kIntensiveThrottledWakeUpInterval; EXPECT_THAT(run_times, testing::ElementsAre(aligned_time, aligned_time, aligned_time, aligned_time, aligned_time)); @@ -3226,7 +3276,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, base::BindOnce(&RecordRunTime, &run_times), kDefaultThrottledWakeUpInterval); - task_environment_.FastForwardBy(kIntensiveThrottlingDurationBetweenWakeUps); + task_environment_.FastForwardBy(kIntensiveThrottledWakeUpInterval); EXPECT_THAT(run_times, testing::ElementsAre(scope_start + GetExpectedWakeUpInterval())); } @@ -3241,8 +3291,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, EXPECT_EQ(scope_start, test_start + base::TimeDelta::FromMinutes(8)); std::vector<base::TimeTicks> run_times; - const base::TimeDelta kLongDelay = - kIntensiveThrottlingDurationBetweenWakeUps * 6; + const base::TimeDelta kLongDelay = kIntensiveThrottledWakeUpInterval * 6; task_runner->PostDelayedTask(FROM_HERE, base::BindOnce(&RecordRunTime, &run_times), kLongDelay - kShortDelay); @@ -3303,7 +3352,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, ManySameOriginFrames) { ASSERT_FALSE(frame_scheduler_->IsCrossOriginToMainFrame()); const scoped_refptr<base::SingleThreadTaskRunner> task_runner = - frame_scheduler_->GetTaskRunner(GetTaskType()); + GetTaskRunner(); // Create a FrameScheduler that is same-origin with the main frame, and an // associated throttled TaskRunner. @@ -3313,12 +3362,12 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, FrameScheduler::FrameType::kSubframe); ASSERT_FALSE(other_frame_scheduler->IsCrossOriginToMainFrame()); const scoped_refptr<base::SingleThreadTaskRunner> other_task_runner = - other_frame_scheduler->GetTaskRunner(GetTaskType()); + GetTaskRunner(other_frame_scheduler.get()); // Snap the time to a multiple of - // |kIntensiveThrottlingDurationBetweenWakeUps|. Otherwise, the time at which + // |kIntensiveThrottledWakeUpInterval|. Otherwise, the time at which // tasks can run after throttling is enabled will vary. - FastForwardToAlignedTime(kIntensiveThrottlingDurationBetweenWakeUps); + FastForwardToAlignedTime(kIntensiveThrottledWakeUpInterval); // Hide the page and wait until the intensive throttling grace period has // elapsed. @@ -3342,10 +3391,9 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, // last minute. The second task is 1-minute aligned if the TaskType supports // intensive throttling, or 1-second aligned otherwise. if (IsIntensiveThrottlingExpected()) { - EXPECT_THAT(run_times, - testing::ElementsAre( - post_time + 2 * kDefaultThrottledWakeUpInterval, - post_time + kIntensiveThrottlingDurationBetweenWakeUps)); + EXPECT_THAT(run_times, testing::ElementsAre( + post_time + 2 * kDefaultThrottledWakeUpInterval, + post_time + kIntensiveThrottledWakeUpInterval)); } else { EXPECT_THAT( run_times, @@ -3360,19 +3408,19 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, constexpr int kNumTasks = 3; // |task_runner| is throttled. const scoped_refptr<base::SingleThreadTaskRunner> task_runner = - frame_scheduler_->GetTaskRunner(GetTaskType()); + GetTaskRunner(); // |other_task_runner| is throttled. It belongs to a different frame on the // same page. const auto other_frame_scheduler = CreateFrameScheduler( page_scheduler_.get(), frame_scheduler_delegate_.get(), nullptr, FrameScheduler::FrameType::kSubframe); const scoped_refptr<base::SingleThreadTaskRunner> other_task_runner = - frame_scheduler_->GetTaskRunner(GetTaskType()); + GetTaskRunner(other_frame_scheduler.get()); // Fast-forward the time to a multiple of - // |kIntensiveThrottlingDurationBetweenWakeUps|. Otherwise, + // |kIntensiveThrottledWakeUpInterval|. Otherwise, // the time at which tasks can run after throttling is enabled will vary. - FastForwardToAlignedTime(kIntensiveThrottlingDurationBetweenWakeUps); + FastForwardToAlignedTime(kIntensiveThrottledWakeUpInterval); // Hide the page and wait until the intensive throttling grace period has // elapsed. @@ -3384,36 +3432,23 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, // Wake ups are intensively throttled, since there is no throttling opt-out. const base::TimeTicks scope_start = base::TimeTicks::Now(); std::vector<base::TimeTicks> run_times; - for (int i = 1; i < kNumTasks + 1; ++i) { - task_runner->PostDelayedTask(FROM_HERE, - base::BindOnce(&RecordRunTime, &run_times), - i * kShortDelay); - } - for (int i = 1; i < kNumTasks + 1; ++i) { - task_runner->PostDelayedTask( - FROM_HERE, base::BindOnce(&RecordRunTime, &run_times), - kDefaultThrottledWakeUpInterval + i * kShortDelay); - } + task_runner->PostDelayedTask( + FROM_HERE, base::BindOnce(&RecordRunTime, &run_times), kShortDelay); + task_runner->PostDelayedTask(FROM_HERE, + base::BindOnce(&RecordRunTime, &run_times), + kDefaultThrottledWakeUpInterval + kShortDelay); task_environment_.FastForwardUntilNoTasksRemain(); if (IsIntensiveThrottlingExpected()) { - // Note: Wake ups can be unaligned when there is no recent wake up. - EXPECT_THAT( - run_times, - testing::ElementsAre( - scope_start + kDefaultThrottledWakeUpInterval, - scope_start + kDefaultThrottledWakeUpInterval, - scope_start + kDefaultThrottledWakeUpInterval, - scope_start + kIntensiveThrottlingDurationBetweenWakeUps, - scope_start + kIntensiveThrottlingDurationBetweenWakeUps, - scope_start + kIntensiveThrottlingDurationBetweenWakeUps)); - } else { + // Note: Intensive throttling is not applied on the 1st task since there + // is no recent wake up. EXPECT_THAT(run_times, testing::ElementsAre( scope_start + kDefaultThrottledWakeUpInterval, + scope_start + kIntensiveThrottledWakeUpInterval)); + } else { + EXPECT_THAT(run_times, + testing::ElementsAre( scope_start + kDefaultThrottledWakeUpInterval, - scope_start + kDefaultThrottledWakeUpInterval, - scope_start + 2 * kDefaultThrottledWakeUpInterval, - scope_start + 2 * kDefaultThrottledWakeUpInterval, scope_start + 2 * kDefaultThrottledWakeUpInterval)); } } @@ -3462,44 +3497,31 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, } // Fast-forward so that there is no recent wake up. Then, align the time on - // |kIntensiveThrottlingDurationBetweenWakeUps| to simplify expectations. - task_environment_.FastForwardBy(kIntensiveThrottlingDurationBetweenWakeUps); - FastForwardToAlignedTime(kIntensiveThrottlingDurationBetweenWakeUps); + // |kIntensiveThrottledWakeUpInterval| to simplify expectations. + task_environment_.FastForwardBy(kIntensiveThrottledWakeUpInterval); + FastForwardToAlignedTime(kIntensiveThrottledWakeUpInterval); { // Wake ups are intensively throttled, since there is no throttling opt-out. const base::TimeTicks scope_start = base::TimeTicks::Now(); std::vector<base::TimeTicks> run_times; - for (int i = 1; i < kNumTasks + 1; ++i) { - task_runner->PostDelayedTask(FROM_HERE, - base::BindOnce(&RecordRunTime, &run_times), - i * kShortDelay); - } - for (int i = 1; i < kNumTasks + 1; ++i) { - task_runner->PostDelayedTask( - FROM_HERE, base::BindOnce(&RecordRunTime, &run_times), - kDefaultThrottledWakeUpInterval + i * kShortDelay); - } + task_runner->PostDelayedTask( + FROM_HERE, base::BindOnce(&RecordRunTime, &run_times), kShortDelay); + task_runner->PostDelayedTask(FROM_HERE, + base::BindOnce(&RecordRunTime, &run_times), + kDefaultThrottledWakeUpInterval + kShortDelay); task_environment_.FastForwardUntilNoTasksRemain(); if (IsIntensiveThrottlingExpected()) { - // Note: Wake ups can be unaligned when there is no recent wake up. - EXPECT_THAT( - run_times, - testing::ElementsAre( - scope_start + kDefaultThrottledWakeUpInterval, - scope_start + kDefaultThrottledWakeUpInterval, - scope_start + kDefaultThrottledWakeUpInterval, - scope_start + kIntensiveThrottlingDurationBetweenWakeUps, - scope_start + kIntensiveThrottlingDurationBetweenWakeUps, - scope_start + kIntensiveThrottlingDurationBetweenWakeUps)); - } else { + // Note: Intensive throttling is not applied on the 1st task since there + // is no recent wake up. EXPECT_THAT(run_times, testing::ElementsAre( scope_start + kDefaultThrottledWakeUpInterval, + scope_start + kIntensiveThrottledWakeUpInterval)); + } else { + EXPECT_THAT(run_times, + testing::ElementsAre( scope_start + kDefaultThrottledWakeUpInterval, - scope_start + kDefaultThrottledWakeUpInterval, - scope_start + 2 * kDefaultThrottledWakeUpInterval, - scope_start + 2 * kDefaultThrottledWakeUpInterval, scope_start + 2 * kDefaultThrottledWakeUpInterval)); } } @@ -3511,7 +3533,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, FrameChangesOriginType) { EXPECT_FALSE(frame_scheduler_->IsCrossOriginToMainFrame()); const scoped_refptr<base::SingleThreadTaskRunner> task_runner = - frame_scheduler_->GetTaskRunner(GetTaskType()); + GetTaskRunner(); // Create a new FrameScheduler that remains cross-origin with the main frame // throughout the test. @@ -3521,12 +3543,12 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, FrameScheduler::FrameType::kSubframe); cross_origin_frame_scheduler->SetCrossOriginToMainFrame(true); const scoped_refptr<base::SingleThreadTaskRunner> cross_origin_task_runner = - cross_origin_frame_scheduler->GetTaskRunner(GetTaskType()); + GetTaskRunner(cross_origin_frame_scheduler.get()); // Snap the time to a multiple of - // |kIntensiveThrottlingDurationBetweenWakeUps|. Otherwise, the time at which + // |kIntensiveThrottledWakeUpInterval|. Otherwise, the time at which // tasks can run after throttling is enabled will vary. - FastForwardToAlignedTime(kIntensiveThrottlingDurationBetweenWakeUps); + FastForwardToAlignedTime(kIntensiveThrottledWakeUpInterval); // Hide the page and wait until the intensive throttling grace period has // elapsed. @@ -3563,7 +3585,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, EXPECT_EQ(1, cross_origin_counter); } - FastForwardToAlignedTime(kIntensiveThrottlingDurationBetweenWakeUps); + FastForwardToAlignedTime(kIntensiveThrottledWakeUpInterval); EXPECT_EQ(1, counter); EXPECT_EQ(1, cross_origin_counter); } @@ -3572,8 +3594,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, // Post delayed tasks with long delays that aren't aligned with the wake up // interval. They should run at aligned times, since they are cross-origin. const base::TimeDelta kLongUnalignedDelay = - 5 * kIntensiveThrottlingDurationBetweenWakeUps + - kDefaultThrottledWakeUpInterval; + 5 * kIntensiveThrottledWakeUpInterval + kDefaultThrottledWakeUpInterval; int counter = 0; task_runner->PostDelayedTask( FROM_HERE, @@ -3599,7 +3620,7 @@ TEST_P(FrameSchedulerImplTestWithIntensiveWakeUpThrottling, EXPECT_EQ(1, cross_origin_counter); } - FastForwardToAlignedTime(kIntensiveThrottlingDurationBetweenWakeUps); + FastForwardToAlignedTime(kIntensiveThrottledWakeUpInterval); EXPECT_EQ(1, counter); EXPECT_EQ(1, cross_origin_counter); } @@ -3611,22 +3632,15 @@ INSTANTIATE_TEST_SUITE_P( testing::Values( IntensiveWakeUpThrottlingTestParam{ /* task_type=*/TaskType::kJavascriptTimerDelayedLowNesting, - /* can_intensively_throttle_low_nesting_level=*/false, /* is_intensive_throttling_expected=*/false}, IntensiveWakeUpThrottlingTestParam{ - /* task_type=*/TaskType::kJavascriptTimerDelayedLowNesting, - /* can_intensively_throttle_low_nesting_level=*/true, + /* task_type=*/TaskType::kJavascriptTimerDelayedHighNesting, /* is_intensive_throttling_expected=*/true}, IntensiveWakeUpThrottlingTestParam{ - /* task_type=*/TaskType::kJavascriptTimerDelayedHighNesting, - /* can_intensively_throttle_low_nesting_level=*/false, + /* task_type=*/TaskType::kExperimentalWebScheduling, /* is_intensive_throttling_expected=*/true}), [](const testing::TestParamInfo<IntensiveWakeUpThrottlingTestParam>& info) { - const std::string task_type = - TaskTypeNames::TaskTypeToString(info.param.task_type); - if (info.param.can_intensively_throttle_low_nesting_level) - return task_type + "_can_intensively_throttle_low_nesting_level"; - return task_type; + return TaskTypeNames::TaskTypeToString(info.param.task_type); }); TEST_F(FrameSchedulerImplTestWithIntensiveWakeUpThrottlingPolicyOverride, @@ -3638,13 +3652,6 @@ TEST_F(FrameSchedulerImplTestWithIntensiveWakeUpThrottlingPolicyOverride, EXPECT_EQ(base::TimeDelta::FromSeconds( kIntensiveWakeUpThrottling_GracePeriodSeconds_Default), GetIntensiveWakeUpThrottlingGracePeriod()); - EXPECT_EQ( - base::TimeDelta::FromSeconds( - kIntensiveWakeUpThrottling_DurationBetweenWakeUpsSeconds_Default), - GetIntensiveWakeUpThrottlingDurationBetweenWakeUps()); - EXPECT_EQ( - kIntensiveWakeUpThrottling_CanIntensivelyThrottleLowNestingLevel_Default, - CanIntensivelyThrottleLowNestingLevel()); } TEST_F(FrameSchedulerImplTestWithIntensiveWakeUpThrottlingPolicyOverride, @@ -3653,6 +3660,469 @@ TEST_F(FrameSchedulerImplTestWithIntensiveWakeUpThrottlingPolicyOverride, EXPECT_FALSE(IsIntensiveWakeUpThrottlingEnabled()); } +class DeprioritizeDOMTimerTest : public FrameSchedulerImplTest { + public: + DeprioritizeDOMTimerTest(DeprioritizeDOMTimersPhase phase) + : FrameSchedulerImplTest( + blink::scheduler::kDeprioritizeDOMTimersDuringPageLoading, + base::FieldTrialParams( + {{"phase", blink::scheduler::kDeprioritizeDOMTimersPhase + .GetName(phase)}}), + {}) {} + + void SetUp() override { + FrameSchedulerImplTest::SetUp(); + scheduler_of_main_frame_ = CreateFrameScheduler( + page_scheduler_.get(), frame_scheduler_delegate_.get(), nullptr, + FrameScheduler::FrameType::kMainFrame); + } + + void TearDown() override { + scheduler_of_main_frame_.reset(); + FrameSchedulerImplTest::TearDown(); + } + + void ExpectJavaScriptTimerTaskQueuePriorityToBe( + FrameSchedulerImpl* frame_scheduler, + TaskQueue::QueuePriority expected_priority) { + EXPECT_EQ( + JavaScriptTimerNormalThrottleableTaskQueueForFrame(frame_scheduler) + ->GetTaskQueue() + ->GetQueuePriority(), + expected_priority); + EXPECT_EQ( + JavaScriptTimerIntensivelyThrottleableTaskQueueForFrame(frame_scheduler) + ->GetTaskQueue() + ->GetQueuePriority(), + expected_priority); + EXPECT_EQ(JavaScriptTimerNonThrottleableTaskQueueForFrame(frame_scheduler) + ->GetTaskQueue() + ->GetQueuePriority(), + expected_priority); + } + + protected: + std::unique_ptr<FrameSchedulerImpl> scheduler_of_main_frame_; +}; + +class DeprioritizeDOMTimerUntilDOMContentLoadedTest + : public DeprioritizeDOMTimerTest { + public: + DeprioritizeDOMTimerUntilDOMContentLoadedTest() + : DeprioritizeDOMTimerTest( + DeprioritizeDOMTimersPhase::kOnDOMContentLoaded) {} +}; + +// Test whether the JavaScript timer task queues' priorities are properly +// updated on DOMContentLoaded event for frame load and reloads. +TEST_F(DeprioritizeDOMTimerUntilDOMContentLoadedTest, + MainAndNonMainFrameLoadAndReload) { + FrameSchedulerImpl* frame_schedulers[2] = {scheduler_of_main_frame_.get(), + frame_scheduler_.get()}; + for (FrameSchedulerImpl* frame_scheduler : frame_schedulers) { + // Initial priority is low. + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler, TaskQueue::QueuePriority::kLowPriority); + + // Priority is set to normal when DOMContentLoaded triggered. + OnDomContentLoadedForFrame(frame_scheduler); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler, TaskQueue::QueuePriority::kNormalPriority); + + // After reload navigation, priority is reset to low. + DidCommitProvisionalLoadForFrame(frame_scheduler, + FrameScheduler::NavigationType::kReload); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler, TaskQueue::QueuePriority::kLowPriority); + + // Priority is set to normal when DOMContentLoaded triggered. + OnDomContentLoadedForFrame(frame_scheduler); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler, TaskQueue::QueuePriority::kNormalPriority); + + // After other type navigation, priority is reset to low. + DidCommitProvisionalLoadForFrame(frame_scheduler, + FrameScheduler::NavigationType::kOther); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler, TaskQueue::QueuePriority::kLowPriority); + + // Priority is set to normal when DOMContentLoaded triggered. + OnDomContentLoadedForFrame(frame_scheduler); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler, TaskQueue::QueuePriority::kNormalPriority); + } +} + +class DeprioritizeDOMTimerUntilFCPTest : public DeprioritizeDOMTimerTest { + public: + DeprioritizeDOMTimerUntilFCPTest() + : DeprioritizeDOMTimerTest( + DeprioritizeDOMTimersPhase::kFirstContentfulPaint) {} +}; + +// Test whether the JavaScript timer task queues' priorities are properly +// updated when FCP is triggered for frame load and reloads. +TEST_F(DeprioritizeDOMTimerUntilFCPTest, MainAndNonMainFrameLoadAndReload) { + // Initial priorities are low. + ExpectJavaScriptTimerTaskQueuePriorityToBe( + scheduler_of_main_frame_.get(), TaskQueue::QueuePriority::kLowPriority); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler_.get(), TaskQueue::QueuePriority::kLowPriority); + + // Priority is set to normal when FCP triggered. + scheduler_of_main_frame_->OnFirstContentfulPaintInMainFrame(); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + scheduler_of_main_frame_.get(), + TaskQueue::QueuePriority::kNormalPriority); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler_.get(), TaskQueue::QueuePriority::kNormalPriority); + + // After reload type navigation, priority is reset to low. + DidCommitProvisionalLoadForFrame(scheduler_of_main_frame_.get(), + FrameScheduler::NavigationType::kReload); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + scheduler_of_main_frame_.get(), TaskQueue::QueuePriority::kLowPriority); + + DidCommitProvisionalLoadForFrame(frame_scheduler_.get(), + FrameScheduler::NavigationType::kReload); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler_.get(), TaskQueue::QueuePriority::kLowPriority); + + // Priority is set to normal when FCP triggered. + scheduler_of_main_frame_->OnFirstContentfulPaintInMainFrame(); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + scheduler_of_main_frame_.get(), + TaskQueue::QueuePriority::kNormalPriority); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler_.get(), TaskQueue::QueuePriority::kNormalPriority); + + // After other type navigation, priority is reset to low. + DidCommitProvisionalLoadForFrame(scheduler_of_main_frame_.get(), + FrameScheduler::NavigationType::kOther); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + scheduler_of_main_frame_.get(), TaskQueue::QueuePriority::kLowPriority); + + DidCommitProvisionalLoadForFrame(frame_scheduler_.get(), + FrameScheduler::NavigationType::kOther); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler_.get(), TaskQueue::QueuePriority::kLowPriority); + + // Priority is set to normal when FCP triggered. + scheduler_of_main_frame_->OnFirstContentfulPaintInMainFrame(); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + scheduler_of_main_frame_.get(), + TaskQueue::QueuePriority::kNormalPriority); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler_.get(), TaskQueue::QueuePriority::kNormalPriority); +} + +// Test that if FCP is not triggered, the JavaScript timer task queues' +// priorities are updated when load is triggered. +TEST_F(DeprioritizeDOMTimerUntilFCPTest, FCPNotTriggered) { + FrameSchedulerImpl* frame_schedulers[2] = {scheduler_of_main_frame_.get(), + frame_scheduler_.get()}; + for (FrameSchedulerImpl* frame_scheduler : frame_schedulers) { + // Initial priority is low. + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler, TaskQueue::QueuePriority::kLowPriority); + + // Priority is set to normal on load event. + OnLoadForFrame(frame_scheduler); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler, TaskQueue::QueuePriority::kNormalPriority); + + // After reload type navigation, priority is reset to low. + DidCommitProvisionalLoadForFrame(frame_scheduler, + FrameScheduler::NavigationType::kReload); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler, TaskQueue::QueuePriority::kLowPriority); + + // Priority is set to normal on load event. + OnLoadForFrame(frame_scheduler); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler, TaskQueue::QueuePriority::kNormalPriority); + + // After other type navigation, priority is reset to low. + DidCommitProvisionalLoadForFrame(frame_scheduler, + FrameScheduler::NavigationType::kOther); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler, TaskQueue::QueuePriority::kLowPriority); + + // Priority is set to normal on load event. + OnLoadForFrame(frame_scheduler); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler, TaskQueue::QueuePriority::kNormalPriority); + } +} + +class DeprioritizeDOMTimerUntilLoadedTest : public DeprioritizeDOMTimerTest { + public: + DeprioritizeDOMTimerUntilLoadedTest() + : DeprioritizeDOMTimerTest(DeprioritizeDOMTimersPhase::kOnLoad) {} +}; + +// Test whether the JavaScript timer task queues' priorities are properly +// updated on load event for frame load and reloads. +TEST_F(DeprioritizeDOMTimerUntilLoadedTest, MainAndNonMainFrameLoadAndReload) { + FrameSchedulerImpl* frame_schedulers[2] = {scheduler_of_main_frame_.get(), + frame_scheduler_.get()}; + for (FrameSchedulerImpl* frame_scheduler : frame_schedulers) { + // Initial priority is low. + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler, TaskQueue::QueuePriority::kLowPriority); + + // Priority is set to normal on load event. + OnLoadForFrame(frame_scheduler); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler, TaskQueue::QueuePriority::kNormalPriority); + + // After reload type navigation, priority is reset to low. + DidCommitProvisionalLoadForFrame(frame_scheduler, + FrameScheduler::NavigationType::kReload); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler, TaskQueue::QueuePriority::kLowPriority); + + // Priority is set to normal on load event. + OnLoadForFrame(frame_scheduler); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler, TaskQueue::QueuePriority::kNormalPriority); + + // After other type navigation, priority is reset to low. + DidCommitProvisionalLoadForFrame(frame_scheduler, + FrameScheduler::NavigationType::kOther); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler, TaskQueue::QueuePriority::kLowPriority); + + // Priority is set to normal on load event. + OnLoadForFrame(frame_scheduler); + ExpectJavaScriptTimerTaskQueuePriorityToBe( + frame_scheduler, TaskQueue::QueuePriority::kNormalPriority); + } +} + +// Verify that non-delayed kExperimentalWebScheduling tasks are not throttled. +TEST_F(FrameSchedulerImplTest, ImmediateWebSchedulingTasksAreNotThrottled) { + std::vector<base::TimeTicks> run_times; + + // Make sure we are *not* aligned to a 1 second boundary by aligning to a 1 + // second boundary and moving past it a bit. If we were throttled, even + // non-delayed tasks will need to wait until the next aligned interval to run. + FastForwardToAlignedTime(base::TimeDelta::FromSeconds(1)); + task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(1)); + + const base::TimeTicks start = base::TimeTicks::Now(); + + // Hide the page to start throttling timers. + page_scheduler_->SetPageVisible(false); + + // Post a non-delayed task to a web scheduling task queue. + const scoped_refptr<base::SingleThreadTaskRunner> task_runner = + frame_scheduler_ + ->CreateWebSchedulingTaskQueue( + WebSchedulingPriority::kUserVisiblePriority) + ->GetTaskRunner(); + task_runner->PostTask(FROM_HERE, base::BindOnce(&RecordRunTime, &run_times)); + + // Run any ready tasks, which includes our non-delayed non-throttled web + // scheduling task. If we are throttled, our task will not run. + base::RunLoop().RunUntilIdle(); + + EXPECT_THAT(run_times, testing::ElementsAre(start)); +} + +class FrameSchedulerImplThrottleForegroundTimersEnabledTest + : public FrameSchedulerImplTest { + public: + FrameSchedulerImplThrottleForegroundTimersEnabledTest() + : FrameSchedulerImplTest({kThrottleForegroundTimers}, {}) {} +}; + +TEST_F(FrameSchedulerImplThrottleForegroundTimersEnabledTest, + ForegroundPageTimerThrottling) { + page_scheduler_->SetPageVisible(true); + + // Snap the time to a multiple of 1 second. + FastForwardToAlignedTime(base::TimeDelta::FromSeconds(1)); + const base::TimeTicks start = base::TimeTicks::Now(); + + std::vector<base::TimeTicks> run_times; + const scoped_refptr<base::SingleThreadTaskRunner> task_runner = + frame_scheduler_->GetTaskRunner( + TaskType::kJavascriptTimerDelayedLowNesting); + + for (int i = 0; i < 5; i++) { + task_runner->PostDelayedTask(FROM_HERE, + base::BindOnce(&RecordRunTime, &run_times), + base::TimeDelta::FromMilliseconds(50) * i); + } + + // Make posted tasks run. + task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(5)); + + EXPECT_THAT(run_times, + testing::ElementsAre( + start, start + base::TimeDelta::FromMilliseconds(100), + start + base::TimeDelta::FromMilliseconds(100), + start + base::TimeDelta::FromMilliseconds(200), + start + base::TimeDelta::FromMilliseconds(200))); +} + +// Make sure the normal throttling (1 wake up per second) is applied when the +// page becomes non-visible +TEST_F(FrameSchedulerImplThrottleForegroundTimersEnabledTest, + BackgroundPageTimerThrottling) { + page_scheduler_->SetPageVisible(false); + + // Snap the time to a multiple of 1 second. + FastForwardToAlignedTime(base::TimeDelta::FromSeconds(1)); + const base::TimeTicks start = base::TimeTicks::Now(); + + std::vector<base::TimeTicks> run_times; + const scoped_refptr<base::SingleThreadTaskRunner> task_runner = + frame_scheduler_->GetTaskRunner( + TaskType::kJavascriptTimerDelayedLowNesting); + + for (int i = 0; i < 5; i++) { + task_runner->PostDelayedTask(FROM_HERE, + base::BindOnce(&RecordRunTime, &run_times), + base::TimeDelta::FromMilliseconds(50) * i); + } + + // Make posted tasks run. + task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(5)); + + EXPECT_THAT(run_times, + testing::ElementsAre( + start, start + base::TimeDelta::FromMilliseconds(1000), + start + base::TimeDelta::FromMilliseconds(1000), + start + base::TimeDelta::FromMilliseconds(1000), + start + base::TimeDelta::FromMilliseconds(1000))); +} + +TEST_F(FrameSchedulerImplThrottleForegroundTimersEnabledTest, + HiddenAudiblePageimerThrottling) { + page_scheduler_->SetPageVisible(false); + page_scheduler_->AudioStateChanged(/*is_audio_playing=*/true); + + // Snap the time to a multiple of 1 second. + FastForwardToAlignedTime(base::TimeDelta::FromSeconds(1)); + const base::TimeTicks start = base::TimeTicks::Now(); + + std::vector<base::TimeTicks> run_times; + const scoped_refptr<base::SingleThreadTaskRunner> task_runner = + frame_scheduler_->GetTaskRunner( + TaskType::kJavascriptTimerDelayedLowNesting); + + for (int i = 0; i < 5; i++) { + task_runner->PostDelayedTask(FROM_HERE, + base::BindOnce(&RecordRunTime, &run_times), + base::TimeDelta::FromMilliseconds(50) * i); + } + + // Make posted tasks run. + task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(5)); + + EXPECT_THAT(run_times, + testing::ElementsAre( + start, start + base::TimeDelta::FromMilliseconds(100), + start + base::TimeDelta::FromMilliseconds(100), + start + base::TimeDelta::FromMilliseconds(200), + start + base::TimeDelta::FromMilliseconds(200))); +} + +TEST_F(FrameSchedulerImplThrottleForegroundTimersEnabledTest, + VisibleCrossOriginFrameThrottling) { + std::unique_ptr<FrameSchedulerImpl> cross_origin_frame_scheduler = + CreateFrameScheduler(page_scheduler_.get(), + frame_scheduler_delegate_.get(), nullptr, + FrameScheduler::FrameType::kSubframe); + page_scheduler_->SetPageVisible(true); + cross_origin_frame_scheduler->SetCrossOriginToMainFrame(true); + const scoped_refptr<base::SingleThreadTaskRunner> cross_origin_task_runner = + cross_origin_frame_scheduler->GetTaskRunner( + TaskType::kJavascriptTimerDelayedLowNesting); + + cross_origin_frame_scheduler->SetFrameVisible(true); + // Snap the time to a multiple of 1 second. + FastForwardToAlignedTime(base::TimeDelta::FromSeconds(1)); + const base::TimeTicks start = base::TimeTicks::Now(); + + std::vector<base::TimeTicks> run_times; + for (int i = 0; i < 5; i++) { + cross_origin_task_runner->PostDelayedTask( + FROM_HERE, base::BindOnce(&RecordRunTime, &run_times), + base::TimeDelta::FromMilliseconds(50) * i); + } + + // Make posted tasks run. + task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(5)); + + EXPECT_THAT(run_times, + testing::ElementsAre( + start, start + base::TimeDelta::FromMilliseconds(100), + start + base::TimeDelta::FromMilliseconds(100), + start + base::TimeDelta::FromMilliseconds(200), + start + base::TimeDelta::FromMilliseconds(200))); +} + +TEST_F(FrameSchedulerImplThrottleForegroundTimersEnabledTest, + HiddenCrossOriginFrameThrottling) { + std::unique_ptr<FrameSchedulerImpl> cross_origin_frame_scheduler = + CreateFrameScheduler(page_scheduler_.get(), + frame_scheduler_delegate_.get(), nullptr, + FrameScheduler::FrameType::kSubframe); + page_scheduler_->SetPageVisible(true); + cross_origin_frame_scheduler->SetCrossOriginToMainFrame(true); + const scoped_refptr<base::SingleThreadTaskRunner> cross_origin_task_runner = + cross_origin_frame_scheduler->GetTaskRunner( + TaskType::kJavascriptTimerDelayedLowNesting); + + cross_origin_frame_scheduler->SetFrameVisible(false); + // Snap the time to a multiple of 1 second. + FastForwardToAlignedTime(base::TimeDelta::FromSeconds(1)); + const base::TimeTicks start = base::TimeTicks::Now(); + + std::vector<base::TimeTicks> run_times; + for (int i = 0; i < 5; i++) { + cross_origin_task_runner->PostDelayedTask( + FROM_HERE, base::BindOnce(&RecordRunTime, &run_times), + base::TimeDelta::FromMilliseconds(50) * i); + } + + // Make posted tasks run. + task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(5)); + + EXPECT_THAT(run_times, + testing::ElementsAre( + start, start + base::TimeDelta::FromMilliseconds(1000), + start + base::TimeDelta::FromMilliseconds(1000), + start + base::TimeDelta::FromMilliseconds(1000), + start + base::TimeDelta::FromMilliseconds(1000))); +} + +class FrameSchedulerImplDisablePrioritizedPostMessageForwarding + : public FrameSchedulerImplTest { + public: + FrameSchedulerImplDisablePrioritizedPostMessageForwarding() + : FrameSchedulerImplTest({kDisablePrioritizedPostMessageForwarding}, {}) { + } +}; + +TEST_F(FrameSchedulerImplTest, PostMessageForwardingHasControlPriority) { + auto task_queue = GetTaskQueue(TaskType::kInternalPostMessageForwarding); + + EXPECT_EQ(TaskQueue::QueuePriority::kVeryHighPriority, + task_queue->GetTaskQueue()->GetQueuePriority()); +} + +TEST_F(FrameSchedulerImplDisablePrioritizedPostMessageForwarding, + PostMessageForwardingHasNormalPriority) { + auto task_queue = GetTaskQueue(TaskType::kInternalPostMessageForwarding); + + EXPECT_EQ(TaskQueue::QueuePriority::kNormalPriority, + task_queue->GetTaskQueue()->GetQueuePriority()); +} + } // namespace frame_scheduler_impl_unittest } // namespace scheduler } // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc index 00f4fd3f5ea..75d09d5ea19 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc @@ -14,7 +14,6 @@ #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/web_scheduling_task_queue_impl.h" #include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h" #include "third_party/blink/renderer/platform/wtf/vector.h" #include "third_party/perfetto/include/perfetto/tracing/traced_value.h" @@ -69,7 +68,7 @@ FrameTaskQueueController::NewWebSchedulingTaskQueue( QueueTraits queue_traits, WebSchedulingPriority priority) { // Note: we only track this |task_queue| in |all_task_queues_and_voters_|. - // It's interacted with through the WebSchedulingTaskQueueImpl that + // It's interacted with through the MainThreadWebSchedulingTaskQueueImpl that // will wrap it, rather than through this class like other task queues. scoped_refptr<MainThreadTaskQueue> task_queue = main_thread_scheduler_impl_->NewTaskQueue( @@ -82,6 +81,12 @@ FrameTaskQueueController::NewWebSchedulingTaskQueue( return task_queue; } +void FrameTaskQueueController::RemoveWebSchedulingTaskQueue( + MainThreadTaskQueue* queue) { + DCHECK(queue); + RemoveTaskQueueAndVoter(queue); +} + void FrameTaskQueueController::CreateTaskQueue( QueueTraits queue_traits) { DCHECK(!task_queues_.Contains(queue_traits.Key())); @@ -128,6 +133,23 @@ void FrameTaskQueueController::TaskQueueCreated( } } +void FrameTaskQueueController::RemoveTaskQueueAndVoter( + MainThreadTaskQueue* queue) { + DCHECK(task_queue_enabled_voters_.Contains(queue)); + task_queue_enabled_voters_.erase(queue); + + bool found_task_queue = false; + for (auto* it = all_task_queues_and_voters_.begin(); + it != all_task_queues_and_voters_.end(); ++it) { + if (it->first == queue) { + found_task_queue = true; + all_task_queues_and_voters_.erase(it); + break; + } + } + DCHECK(found_task_queue); +} + base::sequence_manager::TaskQueue::QueueEnabledVoter* FrameTaskQueueController::GetQueueEnabledVoter( const scoped_refptr<MainThreadTaskQueue>& task_queue) { @@ -144,19 +166,7 @@ bool FrameTaskQueueController::RemoveResourceLoadingTaskQueue( if (!resource_loading_task_queues_.Contains(task_queue)) return false; resource_loading_task_queues_.erase(task_queue); - DCHECK(task_queue_enabled_voters_.Contains(task_queue)); - task_queue_enabled_voters_.erase(task_queue); - - bool found_task_queue = false; - for (auto* it = all_task_queues_and_voters_.begin(); - it != all_task_queues_and_voters_.end(); ++it) { - if (it->first == task_queue.get()) { - found_task_queue = true; - all_task_queues_and_voters_.erase(it); - break; - } - } - DCHECK(found_task_queue); + RemoveTaskQueueAndVoter(task_queue.get()); return true; } diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h index fb24d8834c9..69f1219d4f2 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h @@ -9,7 +9,6 @@ #include <utility> #include "base/callback.h" -#include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h" @@ -53,19 +52,20 @@ class PLATFORM_EXPORT FrameTaskQueueController { class Delegate { public: Delegate() = default; + Delegate(const Delegate&) = delete; + Delegate& operator=(const Delegate&) = delete; virtual ~Delegate() = default; virtual void OnTaskQueueCreated( MainThreadTaskQueue*, base::sequence_manager::TaskQueue::QueueEnabledVoter*) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(Delegate); }; FrameTaskQueueController(MainThreadSchedulerImpl*, FrameSchedulerImpl*, Delegate*); + FrameTaskQueueController(const FrameTaskQueueController&) = delete; + FrameTaskQueueController& operator=(const FrameTaskQueueController&) = delete; ~FrameTaskQueueController(); // Return the task queue associated with the given queue traits, @@ -79,6 +79,8 @@ class PLATFORM_EXPORT FrameTaskQueueController { MainThreadTaskQueue::QueueTraits, WebSchedulingPriority); + void RemoveWebSchedulingTaskQueue(MainThreadTaskQueue*); + // Get the list of all task queue and voter pairs. const Vector<TaskQueueAndEnabledVoterPair>& GetAllTaskQueuesAndVoters() const; @@ -105,6 +107,12 @@ class PLATFORM_EXPORT FrameTaskQueueController { void TaskQueueCreated(const scoped_refptr<MainThreadTaskQueue>&); + // Removes a queue from |all_task_queues_and_voters_| and + // |task_queue_enabled_voters_|. This method enforces that the queue is in the + // collection before removal. Removes are linear in the total number of task + // queues. + void RemoveTaskQueueAndVoter(MainThreadTaskQueue*); + // Map a set of QueueTraits to a QueueType. // TODO(crbug.com/877245): Consider creating a new queue type kFrameNonLoading // and use it instead of this for new queue types. @@ -137,8 +145,6 @@ class PLATFORM_EXPORT FrameTaskQueueController { // The list of all task queue and voter pairs for all QueueTypeInternal queue // types. Vector<TaskQueueAndEnabledVoterPair> all_task_queues_and_voters_; - - DISALLOW_COPY_AND_ASSIGN(FrameTaskQueueController); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc index c06ef73e758..cfc6d2bd602 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc @@ -39,6 +39,9 @@ class FrameTaskQueueControllerTest : public testing::Test, base::test::TaskEnvironment::TimeSource::MOCK_TIME, base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED), task_queue_created_count_(0) {} + FrameTaskQueueControllerTest(const FrameTaskQueueControllerTest&) = delete; + FrameTaskQueueControllerTest& operator=(const FrameTaskQueueControllerTest&) = + delete; ~FrameTaskQueueControllerTest() override = default; @@ -124,8 +127,6 @@ class FrameTaskQueueControllerTest : public testing::Test, private: size_t task_queue_created_count_; - - DISALLOW_COPY_AND_ASSIGN(FrameTaskQueueControllerTest); }; TEST_F(FrameTaskQueueControllerTest, CreateAllTaskQueues) { @@ -286,6 +287,31 @@ TEST_F(FrameTaskQueueControllerTest, AddWebSchedulingTaskQueues) { task_queue->web_scheduling_priority().value()); } +TEST_F(FrameTaskQueueControllerTest, RemoveWebSchedulingTaskQueues) { + scoped_refptr<MainThreadTaskQueue> task_queue = + frame_task_queue_controller_->NewWebSchedulingTaskQueue( + QueueTraits(), WebSchedulingPriority::kUserBlockingPriority); + EXPECT_EQ(1u, + frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size()); + EXPECT_EQ(WebSchedulingPriority::kUserBlockingPriority, + task_queue->web_scheduling_priority().value()); + + scoped_refptr<MainThreadTaskQueue> task_queue2 = + frame_task_queue_controller_->NewWebSchedulingTaskQueue( + QueueTraits(), WebSchedulingPriority::kUserVisiblePriority); + EXPECT_EQ(2u, + frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size()); + EXPECT_EQ(WebSchedulingPriority::kUserVisiblePriority, + task_queue2->web_scheduling_priority().value()); + + frame_task_queue_controller_->RemoveWebSchedulingTaskQueue(task_queue.get()); + EXPECT_EQ(1u, + frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size()); + frame_task_queue_controller_->RemoveWebSchedulingTaskQueue(task_queue2.get()); + EXPECT_EQ(0u, + frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size()); +} + TEST_F(FrameTaskQueueControllerTest, AddMultipleSamePriorityWebSchedulingTaskQueues) { scoped_refptr<MainThreadTaskQueue> task_queue1 = diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h index f6a962a4ca9..2367d1610e7 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h @@ -5,7 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_IDLE_TIME_ESTIMATOR_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_IDLE_TIME_ESTIMATOR_H_ -#include "base/macros.h" #include "base/task/task_observer.h" #include "base/time/tick_clock.h" #include "cc/base/rolling_time_delta_history.h" @@ -22,6 +21,8 @@ class PLATFORM_EXPORT IdleTimeEstimator : public base::TaskObserver { const base::TickClock* time_source, int sample_count, double estimation_percentile); + IdleTimeEstimator(const IdleTimeEstimator&) = delete; + IdleTimeEstimator& operator=(const IdleTimeEstimator&) = delete; ~IdleTimeEstimator() override; @@ -54,8 +55,6 @@ class PLATFORM_EXPORT IdleTimeEstimator : public base::TaskObserver { base::TimeDelta cumulative_compositor_runtime_; int nesting_level_; bool did_commit_; - - DISALLOW_COPY_AND_ASSIGN(IdleTimeEstimator); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.cc index c53e2399302..e02a2f9924f 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.cc @@ -21,8 +21,6 @@ namespace scheduler { MAIN_THREAD_LOAD_METRIC_NAME ".Extension" #define DURATION_PER_TASK_TYPE_METRIC_NAME \ "RendererScheduler.TaskDurationPerTaskType2" -#define COUNT_PER_FRAME_METRIC_NAME_WITH_SAFEPOINT \ - "RendererScheduler.TaskCountPerFrameType.HasSafePoint" #define QUEUEING_TIME_PER_QUEUE_TYPE_METRIC_NAME \ "RendererScheduler.QueueingDurationPerQueueType" @@ -91,10 +89,9 @@ MainThreadMetricsHelper::MainThreadMetricsHelper( total_task_time_reporter_( "Scheduler.Experimental.Renderer.TotalTime.Wall.MainThread.Positive", "Scheduler.Experimental.Renderer.TotalTime.Wall.MainThread.Negative"), - main_thread_task_load_state_(MainThreadTaskLoadState::kUnknown), - current_task_slice_start_time_(now), - safepoints_in_current_toplevel_task_count_(0) { + main_thread_task_load_state_(MainThreadTaskLoadState::kUnknown) { main_thread_load_tracker_.Resume(now); + random_generator_.Seed(); if (renderer_backgrounded) { background_main_thread_load_tracker_.Resume(now); } else { @@ -143,37 +140,6 @@ void MainThreadMetricsHelper::ResetForTest(base::TimeTicks now) { kThreadLoadTrackerReportingInterval); } -void MainThreadMetricsHelper::OnSafepointEntered(base::TimeTicks now) { - current_task_slice_start_time_ = now; -} - -void MainThreadMetricsHelper::OnSafepointExited(base::TimeTicks now) { - safepoints_in_current_toplevel_task_count_++; - RecordTaskSliceMetrics(now); -} - -void MainThreadMetricsHelper::RecordTaskSliceMetrics(base::TimeTicks now) { - UMA_HISTOGRAM_TIMES("RendererScheduler.TasksWithSafepoints.TaskSliceTime", - now - current_task_slice_start_time_); -} - -void MainThreadMetricsHelper::RecordMetricsForTasksWithSafepoints( - const base::sequence_manager::TaskQueue::TaskTiming& task_timing) { - if (safepoints_in_current_toplevel_task_count_ == 0) - return; - - RecordTaskSliceMetrics(task_timing.end_time()); - - UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES( - "RendererScheduler.TasksWithSafepoints.TaskTime", - task_timing.wall_duration(), base::TimeDelta::FromMicroseconds(1), - base::TimeDelta::FromSeconds(1), 50); - UMA_HISTOGRAM_COUNTS_100( - "RendererScheduler.TasksWithSafepoints.SafepointCount", - safepoints_in_current_toplevel_task_count_); - safepoints_in_current_toplevel_task_count_ = 0; -} - void MainThreadMetricsHelper::RecordTaskMetrics( MainThreadTaskQueue* queue, const base::sequence_manager::Task& task, @@ -200,11 +166,6 @@ void MainThreadMetricsHelper::RecordTaskMetrics( last_reported_task_ = task_timing.end_time(); - UMA_HISTOGRAM_CUSTOM_COUNTS("RendererScheduler.TaskTime2", - base::saturated_cast<base::HistogramBase::Sample>( - duration.InMicroseconds()), - 1, 1000 * 1000, 50); - // We want to measure thread time here, but for efficiency reasons // we stick with wall time. main_thread_load_tracker_.RecordTaskTime(task_timing.start_time(), @@ -213,44 +174,16 @@ void MainThreadMetricsHelper::RecordTaskMetrics( task_timing.end_time()); background_main_thread_load_tracker_.RecordTaskTime(task_timing.start_time(), task_timing.end_time()); + // WARNING: All code below must be compatible with down-sampling. + constexpr double kSamplingProbabily = .01; + bool should_sample = random_generator_.RandDouble() < kSamplingProbabily; + if (!should_sample) + return; - if (safepoints_in_current_toplevel_task_count_ > 0) { - FrameStatus frame_status = - GetFrameStatus(queue ? queue->GetFrameScheduler() : nullptr); - - UMA_HISTOGRAM_ENUMERATION(COUNT_PER_FRAME_METRIC_NAME_WITH_SAFEPOINT, - frame_status, FrameStatus::kCount); - if (duration >= base::TimeDelta::FromMilliseconds(16)) { - UMA_HISTOGRAM_ENUMERATION(COUNT_PER_FRAME_METRIC_NAME_WITH_SAFEPOINT - ".LongerThan16ms", - frame_status, FrameStatus::kCount); - } - - if (duration >= base::TimeDelta::FromMilliseconds(50)) { - UMA_HISTOGRAM_ENUMERATION(COUNT_PER_FRAME_METRIC_NAME_WITH_SAFEPOINT - ".LongerThan50ms", - frame_status, FrameStatus::kCount); - } - - if (duration >= base::TimeDelta::FromMilliseconds(100)) { - UMA_HISTOGRAM_ENUMERATION(COUNT_PER_FRAME_METRIC_NAME_WITH_SAFEPOINT - ".LongerThan100ms", - frame_status, FrameStatus::kCount); - } - - if (duration >= base::TimeDelta::FromMilliseconds(150)) { - UMA_HISTOGRAM_ENUMERATION(COUNT_PER_FRAME_METRIC_NAME_WITH_SAFEPOINT - ".LongerThan150ms", - frame_status, FrameStatus::kCount); - } - - if (duration >= base::TimeDelta::FromSeconds(1)) { - UMA_HISTOGRAM_ENUMERATION(COUNT_PER_FRAME_METRIC_NAME_WITH_SAFEPOINT - ".LongerThan1s", - frame_status, FrameStatus::kCount); - } - RecordMetricsForTasksWithSafepoints(task_timing); - } + UMA_HISTOGRAM_CUSTOM_COUNTS("RendererScheduler.TaskTime2", + base::saturated_cast<base::HistogramBase::Sample>( + duration.InMicroseconds()), + 1, 1000 * 1000, 50); TaskType task_type = static_cast<TaskType>(task.task_type); UseCase use_case = diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.h index 4f60016f817..f4d0fc58e85 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.h @@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MAIN_THREAD_METRICS_HELPER_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MAIN_THREAD_METRICS_HELPER_H_ -#include "base/macros.h" +#include "base/rand_util.h" #include "base/time/time.h" #include "components/scheduling_metrics/task_duration_metric_reporter.h" #include "components/scheduling_metrics/total_duration_metric_reporter.h" @@ -43,21 +43,19 @@ class PLATFORM_EXPORT MainThreadMetricsHelper : public MetricsHelper { bool has_cpu_timing_for_each_task, base::TimeTicks now, bool renderer_backgrounded); + MainThreadMetricsHelper(const MainThreadMetricsHelper&) = delete; + MainThreadMetricsHelper& operator=(const MainThreadMetricsHelper&) = delete; ~MainThreadMetricsHelper(); void RecordTaskMetrics( MainThreadTaskQueue* queue, const base::sequence_manager::Task& task, const base::sequence_manager::TaskQueue::TaskTiming& task_timing); - void RecordTaskSliceMetrics(base::TimeTicks now); void OnRendererForegrounded(base::TimeTicks now); void OnRendererBackgrounded(base::TimeTicks now); void OnRendererShutdown(base::TimeTicks now); - void OnSafepointEntered(base::TimeTicks now); - void OnSafepointExited(base::TimeTicks now); - void RecordMainThreadTaskLoad(base::TimeTicks time, double load); void RecordForegroundMainThreadTaskLoad(base::TimeTicks time, double load); void RecordBackgroundMainThreadTaskLoad(base::TimeTicks time, double load); @@ -71,10 +69,6 @@ class PLATFORM_EXPORT MainThreadMetricsHelper : public MetricsHelper { void ReportLowThreadLoadForPageAlmostIdleSignal(int load_percentage); - // Record metrics of only top-level tasks with safepoints. - void RecordMetricsForTasksWithSafepoints( - const base::sequence_manager::TaskQueue::TaskTiming& task_timing); - MainThreadSchedulerImpl* main_thread_scheduler_; // NOT OWNED // Set to true when OnRendererShutdown is called. Used to ensure that metrics @@ -116,15 +110,7 @@ class PLATFORM_EXPORT MainThreadMetricsHelper : public MetricsHelper { scheduling_metrics::TotalDurationMetricReporter total_task_time_reporter_; MainThreadTaskLoadState main_thread_task_load_state_; - - base::TimeTicks current_task_slice_start_time_; - - // Number of safepoints during inside the current top-level tasks in which - // cooperative scheduling had a chance to run a task (as we don't necessarily - // run a task in each safepoint). - int safepoints_in_current_toplevel_task_count_; - - DISALLOW_COPY_AND_ASSIGN(MainThreadMetricsHelper); + base::InsecureRandomGenerator random_generator_; }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper_unittest.cc index b811e6ff87a..ad51f194b3e 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper_unittest.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper_unittest.cc @@ -5,7 +5,6 @@ #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.h" #include <memory> -#include "base/macros.h" #include "base/task/sequence_manager/test/fake_task.h" #include "base/task/sequence_manager/test/sequence_manager_for_test.h" #include "base/test/metrics/histogram_tester.h" @@ -52,6 +51,9 @@ class MainThreadMetricsHelperTest : public testing::Test { : task_environment_( base::test::TaskEnvironment::TimeSource::MOCK_TIME, base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED) {} + MainThreadMetricsHelperTest(const MainThreadMetricsHelperTest&) = delete; + MainThreadMetricsHelperTest& operator=(const MainThreadMetricsHelperTest&) = + delete; ~MainThreadMetricsHelperTest() override = default; @@ -241,8 +243,6 @@ class MainThreadMetricsHelperTest : public testing::Test { FakePageScheduler::Builder().SetIsAudioPlaying(true).Build(); std::unique_ptr<FakePageScheduler> throtting_exempt_view_ = FakePageScheduler::Builder().SetIsThrottlingExempt(true).Build(); - - DISALLOW_COPY_AND_ASSIGN(MainThreadMetricsHelperTest); }; TEST_F(MainThreadMetricsHelperTest, GetFrameStatusTest) { @@ -264,8 +264,5 @@ TEST_F(MainThreadMetricsHelperTest, GetFrameStatusTest) { } } -// TODO(crbug.com/754656): Add tests for -// RendererScheduler.TasksWithSafepoints histograms. - } // namespace scheduler } // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_perftest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_perftest.cc index ca954dbac31..50178bab279 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_perftest.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_perftest.cc @@ -28,6 +28,8 @@ constexpr char kTimePerTaskRun[] = "time_per_task_run"; class MainThreadPerfTest : public testing::Test { public: MainThreadPerfTest() = default; + MainThreadPerfTest(const MainThreadPerfTest&) = delete; + MainThreadPerfTest& operator=(const MainThreadPerfTest&) = delete; ~MainThreadPerfTest() override = default; void SetUp() override { @@ -46,8 +48,6 @@ class MainThreadPerfTest : public testing::Test { protected: std::unique_ptr<MainThreadSchedulerImpl> scheduler_; std::unique_ptr<ScopedSchedulerOverrider> scheduler_overrider_; - - DISALLOW_COPY_AND_ASSIGN(MainThreadPerfTest); }; TEST_F(MainThreadPerfTest, PostTaskPerformance) { diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.h index 9d1c2990a54..3b0a449bc05 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.h @@ -23,6 +23,9 @@ class PLATFORM_EXPORT MainThreadSchedulerHelper : public SchedulerHelper { MainThreadSchedulerHelper( base::sequence_manager::SequenceManager* sequence_manager, MainThreadSchedulerImpl* main_thread_scheduler); + MainThreadSchedulerHelper(const MainThreadSchedulerHelper&) = delete; + MainThreadSchedulerHelper& operator=(const MainThreadSchedulerHelper&) = + delete; ~MainThreadSchedulerHelper() override; scoped_refptr<MainThreadTaskQueue> NewTaskQueue( @@ -45,8 +48,6 @@ class PLATFORM_EXPORT MainThreadSchedulerHelper : public SchedulerHelper { const scoped_refptr<MainThreadTaskQueue> default_task_queue_; const scoped_refptr<MainThreadTaskQueue> control_task_queue_; - - DISALLOW_COPY_AND_ASSIGN(MainThreadSchedulerHelper); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc index 9a117a2acf4..b8f5e030998 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc @@ -42,7 +42,6 @@ #include "third_party/blink/renderer/platform/scheduler/common/process_state.h" #include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/agent_group_scheduler_impl.h" -#include "third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.h" #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.h" @@ -205,8 +204,6 @@ bool IsBlockingEvent(const blink::WebInputEvent& web_input_event) { blink::WebInputEvent::DispatchType::kBlocking; } -MainThreadSchedulerImpl* g_main_thread_scheduler = nullptr; - } // namespace MainThreadSchedulerImpl::MainThreadSchedulerImpl( @@ -253,8 +250,7 @@ MainThreadSchedulerImpl::MainThreadSchedulerImpl( TaskType::kMainThreadTaskQueueControl)), main_thread_only_(this, helper_.GetClock(), helper_.NowTicks()), any_thread_(this), - policy_may_need_update_(&any_thread_lock_), - notify_agent_strategy_task_posted_(&any_thread_lock_) { + policy_may_need_update_(&any_thread_lock_) { helper_.AttachToCurrentThread(); // Compositor task queue and default task queue should be managed by @@ -290,18 +286,10 @@ MainThreadSchedulerImpl::MainThreadSchedulerImpl( // TaskQueueThrottler requires some task runners, then initialize // TaskQueueThrottler after task queues/runners are initialized. - task_queue_throttler_ = - std::make_unique<TaskQueueThrottler>(this, &tracing_controller_); update_policy_closure_ = base::BindRepeating( &MainThreadSchedulerImpl::UpdatePolicy, weak_factory_.GetWeakPtr()); end_renderer_hidden_idle_period_closure_.Reset(base::BindRepeating( &MainThreadSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr())); - notify_agent_strategy_on_input_event_closure_ = base::BindRepeating( - &MainThreadSchedulerImpl::NotifyAgentSchedulerOnInputEvent, - weak_factory_.GetWeakPtr()); - agent_strategy_delay_callback_ = - base::BindRepeating(&MainThreadSchedulerImpl::OnAgentStrategyDelayPassed, - weak_factory_.GetWeakPtr()); TRACE_EVENT_OBJECT_CREATED_WITH_ID( TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "MainThreadScheduler", @@ -325,18 +313,13 @@ MainThreadSchedulerImpl::MainThreadSchedulerImpl( // we choose an arbitrary initial offset. main_thread_only().initial_virtual_time_ticks = base::TimeTicks() + base::TimeDelta::FromSeconds(10); - EnableVirtualTime(BaseTimeOverridePolicy::OVERRIDE); + EnableVirtualTime(); SetVirtualTimePolicy(VirtualTimePolicy::kPause); } - main_thread_only() - .compositor_priority_experiments.OnMainThreadSchedulerInitialized(); - main_thread_only().current_policy.find_in_page_priority() = find_in_page_budget_pool_controller_->CurrentTaskPriority(); - g_main_thread_scheduler = this; - // Explicitly set the priority of this queue since it is not managed by // the main thread scheduler. memory_purge_task_queue_->GetTaskQueue()->SetQueuePriority( @@ -367,13 +350,17 @@ MainThreadSchedulerImpl::~MainThreadSchedulerImpl() { // we could end up having stale pointers to the Blink heap which has been // terminated by this point. DCHECK(was_shutdown_); - - g_main_thread_scheduler = nullptr; } // static WebThreadScheduler* WebThreadScheduler::MainThreadScheduler() { - return g_main_thread_scheduler; + auto* main_thread = Thread::MainThread(); + // Enforce that this is not called before the main thread is initialized. + DCHECK(main_thread && main_thread->Scheduler()); + + // This can return nullptr if the main thread scheduler is not a + // MainThreadSchedulerImpl, which can happen in tests. + return main_thread->Scheduler()->GetWebMainThreadScheduler(); } MainThreadSchedulerImpl::MainThreadOnly::MainThreadOnly( @@ -669,11 +656,8 @@ void MainThreadSchedulerImpl::Shutdown() { base::TimeTicks now = tick_clock()->NowTicks(); main_thread_only().metrics_helper.OnRendererShutdown(now); - main_thread_only() - .compositor_priority_experiments.OnMainThreadSchedulerShutdown(); ShutdownAllQueues(); - task_queue_throttler_.reset(); // Shut down |helper_| first, so that the ForceUpdatePolicy() call // from |idle_helper_| early-outs and doesn't do anything. @@ -1363,16 +1347,6 @@ void MainThreadSchedulerImpl::UpdateForInputEventOnCompositorThread( break; } - // Make sure the per-agent scheduling strategy is notified that there was an - // input event. - if (type != WebInputEvent::Type::kMouseMove && - !notify_agent_strategy_task_posted_.IsSet() && - agent_scheduling_strategy_->ShouldNotifyOnInputEvent()) { - notify_agent_strategy_task_posted_.SetWhileLocked(true); - control_task_queue_->GetTaskRunnerWithDefaultTaskType()->PostTask( - FROM_HERE, notify_agent_strategy_on_input_event_closure_); - } - // Avoid unnecessary policy updates if the use case did not change. UseCase use_case = ComputeCurrentUseCase(now, &unused_policy_duration); @@ -1384,19 +1358,6 @@ void MainThreadSchedulerImpl::UpdateForInputEventOnCompositorThread( GetCompositorThreadOnly().last_input_type = type; } -void MainThreadSchedulerImpl::NotifyAgentSchedulerOnInputEvent() { - helper_.CheckOnValidThread(); - - if (agent_scheduling_strategy_->OnInputEvent() == - AgentSchedulingStrategy::ShouldUpdatePolicy::kYes && - !policy_may_need_update_.IsSet()) { - OnAgentStrategyUpdated(); - } - - base::AutoLock lock(any_thread_lock_); - notify_agent_strategy_task_posted_.SetWhileLocked(false); -} - void MainThreadSchedulerImpl::WillPostInputEventToMainThread( WebInputEvent::Type web_input_event_type, const WebInputEventAttribution& web_input_event_attribution) { @@ -1477,7 +1438,8 @@ bool MainThreadSchedulerImpl::ShouldYieldForHighPriorityWork() { if (pair.first->GetPrioritisationType() == MainThreadTaskQueue::QueueTraits::PrioritisationType:: kCompositor && - pair.first->GetTaskQueue()->HasTaskToRunImmediately()) + pair.first->GetTaskQueue() + ->HasTaskToRunImmediatelyOrReadyDelayedTask()) return true; } return main_thread_only().blocking_input_expected_soon; @@ -1665,8 +1627,6 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) { new_policy.should_prioritize_loading_with_compositing() = true; } - new_policy.should_disable_throttling() = main_thread_only().use_virtual_time; - new_policy.find_in_page_priority() = find_in_page_budget_pool_controller_->CurrentTaskPriority(); @@ -1694,15 +1654,6 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) { } } - if (new_policy.should_disable_throttling() != - main_thread_only().current_policy.should_disable_throttling()) { - if (new_policy.should_disable_throttling()) { - task_queue_throttler()->DisableThrottling(); - } else { - task_queue_throttler()->EnableThrottling(); - } - } - Policy old_policy = main_thread_only().current_policy; main_thread_only().current_policy = new_policy; @@ -1711,10 +1662,6 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) { UpdateStateForAllTaskQueues(old_policy); } -void MainThreadSchedulerImpl::OnAgentStrategyUpdated() { - UpdateStateForAllTaskQueues(absl::nullopt); -} - void MainThreadSchedulerImpl::UpdateStateForAllTaskQueues( absl::optional<Policy> previous_policy) { helper_.CheckOnValidThread(); @@ -1742,11 +1689,8 @@ void MainThreadSchedulerImpl::UpdateTaskQueueState( task_queue->GetTaskQueue()->SetQueuePriority(ComputePriority(task_queue)); if (task_queue_enabled_voter) { - bool is_enabled_for_agent = - agent_scheduling_strategy_->QueueEnabledState(*task_queue) - .value_or(true); task_queue_enabled_voter->SetVoteToEnable( - is_enabled_for_agent && new_policy.IsQueueEnabled(task_queue)); + new_policy.IsQueueEnabled(task_queue)); } // Make sure if there's no voter that the task queue is enabled. @@ -1879,13 +1823,6 @@ IdleTimeEstimator* MainThreadSchedulerImpl::GetIdleTimeEstimatorForTesting() { } base::TimeTicks MainThreadSchedulerImpl::EnableVirtualTime() { - return EnableVirtualTime(main_thread_only().initial_virtual_time.is_null() - ? BaseTimeOverridePolicy::DO_NOT_OVERRIDE - : BaseTimeOverridePolicy::OVERRIDE); -} - -base::TimeTicks MainThreadSchedulerImpl::EnableVirtualTime( - BaseTimeOverridePolicy policy) { if (main_thread_only().use_virtual_time) return main_thread_only().initial_virtual_time_ticks; main_thread_only().use_virtual_time = true; @@ -1895,11 +1832,8 @@ base::TimeTicks MainThreadSchedulerImpl::EnableVirtualTime( if (main_thread_only().initial_virtual_time_ticks.is_null()) main_thread_only().initial_virtual_time_ticks = tick_clock()->NowTicks(); virtual_time_domain_ = std::make_unique<AutoAdvancingVirtualTimeDomain>( - main_thread_only().initial_virtual_time + - main_thread_only().initial_virtual_time_offset, - main_thread_only().initial_virtual_time_ticks + - main_thread_only().initial_virtual_time_offset, - &helper_, policy); + main_thread_only().initial_virtual_time, + main_thread_only().initial_virtual_time_ticks, &helper_); RegisterTimeDomain(virtual_time_domain_.get()); DCHECK(!virtual_time_control_task_queue_); @@ -2025,11 +1959,6 @@ void MainThreadSchedulerImpl::SetInitialVirtualTime(base::Time time) { main_thread_only().initial_virtual_time = time; } -void MainThreadSchedulerImpl::SetInitialVirtualTimeOffset( - base::TimeDelta offset) { - main_thread_only().initial_virtual_time_offset = offset; -} - void MainThreadSchedulerImpl::ApplyVirtualTimePolicy() { switch (main_thread_only().virtual_time_policy) { case VirtualTimePolicy::kAdvance: @@ -2150,7 +2079,12 @@ void MainThreadSchedulerImpl::WriteIntoTraceLocked( VirtualTimePolicyToString(main_thread_only().virtual_time_policy)); dict.Add("virtual_time", main_thread_only().use_virtual_time); - dict.Add("page_schedulers", main_thread_only().page_schedulers); + dict.Add("page_schedulers", [&](perfetto::TracedValue context) { + auto array = std::move(context).WriteArray(); + for (const auto* page_scheduler : main_thread_only().page_schedulers) { + page_scheduler->WriteIntoTrace(array.AppendItem(), optional_now); + } + }); dict.Add("policy", main_thread_only().current_policy); @@ -2167,10 +2101,6 @@ void MainThreadSchedulerImpl::WriteIntoTraceLocked( dict.Add("user_model", any_thread().user_model); dict.Add("render_widget_scheduler_signals", render_widget_scheduler_signals_); - - dict.Add("task_queue_throttler", [&](perfetto::TracedValue context) { - task_queue_throttler_->WriteIntoTrace(std::move(context), optional_now); - }); } bool MainThreadSchedulerImpl::Policy::IsQueueEnabled( @@ -2198,7 +2128,6 @@ void MainThreadSchedulerImpl::Policy::WriteIntoTrace( dict.Add("rail_mode", RAILModeToString(rail_mode())); dict.Add("use_case", UseCaseToString(use_case())); - dict.Add("should_disable_throttling", should_disable_throttling()); dict.Add("should_defer_task_queues", should_defer_task_queues()); dict.Add("should_pause_task_queues", should_pause_task_queues()); dict.Add("should_pause_task_queues_for_android_webview", @@ -2298,36 +2227,6 @@ void MainThreadSchedulerImpl::OnMainFramePaint() { UpdatePolicyLocked(UpdateType::kMayEarlyOutIfPolicyUnchanged); } -void MainThreadSchedulerImpl::OnMainFrameLoad( - const FrameSchedulerImpl& frame_scheduler) { - helper_.CheckOnValidThread(); - if (agent_scheduling_strategy_->OnMainFrameLoad(frame_scheduler) == - AgentSchedulingStrategy::ShouldUpdatePolicy::kYes) { - OnAgentStrategyUpdated(); - }; -} - -void MainThreadSchedulerImpl::OnSetTimer( - const FrameSchedulerImpl& frame_scheduler, - base::TimeDelta delay) { - helper_.CheckOnValidThread(); - control_task_runner_->PostDelayedTask( - FROM_HERE, - base::BindOnce(agent_strategy_delay_callback_, - frame_scheduler.GetWeakPtr()), - delay); -} - -void MainThreadSchedulerImpl::OnAgentStrategyDelayPassed( - base::WeakPtr<const FrameSchedulerImpl> frame_scheduler) { - helper_.CheckOnValidThread(); - if (frame_scheduler && - agent_scheduling_strategy_->OnDelayPassed(*frame_scheduler) == - AgentSchedulingStrategy::ShouldUpdatePolicy::kYes) { - OnAgentStrategyUpdated(); - } -} - void MainThreadSchedulerImpl::ResetForNavigationLocked() { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "MainThreadSchedulerImpl::ResetForNavigationLocked"); @@ -2343,9 +2242,6 @@ void MainThreadSchedulerImpl::ResetForNavigationLocked() { main_thread_only().idle_time_estimator.Clear(); main_thread_only().have_reported_blocking_intervention_since_navigation = false; - for (PageSchedulerImpl* page_scheduler : main_thread_only().page_schedulers) { - page_scheduler->OnNavigation(); - } UpdatePolicyLocked(UpdateType::kMayEarlyOutIfPolicyUnchanged); UMA_HISTOGRAM_COUNTS_100("RendererScheduler.WebViewsPerScheduler", @@ -2566,8 +2462,7 @@ base::TimeTicks MainThreadSchedulerImpl::MonotonicallyIncreasingVirtualTime() { return GetActiveTimeDomain()->Now(); } -WebThreadScheduler* -MainThreadSchedulerImpl::GetWebMainThreadSchedulerForTest() { +WebThreadScheduler* MainThreadSchedulerImpl::GetWebMainThreadScheduler() { return this; } @@ -2638,22 +2533,6 @@ void MainThreadSchedulerImpl::RemovePageScheduler( UpdatePolicyLocked(UpdateType::kMayEarlyOutIfPolicyUnchanged); } -void MainThreadSchedulerImpl::OnFrameAdded( - const FrameSchedulerImpl& frame_scheduler) { - if (agent_scheduling_strategy_->OnFrameAdded(frame_scheduler) == - AgentSchedulingStrategy::ShouldUpdatePolicy::kYes) { - OnAgentStrategyUpdated(); - } -} - -void MainThreadSchedulerImpl::OnFrameRemoved( - const FrameSchedulerImpl& frame_scheduler) { - if (agent_scheduling_strategy_->OnFrameRemoved(frame_scheduler) == - AgentSchedulingStrategy::ShouldUpdatePolicy::kYes) { - OnAgentStrategyUpdated(); - } -} - void MainThreadSchedulerImpl::OnPageFrozen() { memory_purge_manager_.OnPageFrozen(); UpdatePolicy(); @@ -2881,6 +2760,12 @@ void MainThreadSchedulerImpl::RemoveTaskTimeObserver( helper_.RemoveTaskTimeObserver(task_time_observer); } +std::unique_ptr<CPUTimeBudgetPool> +MainThreadSchedulerImpl::CreateCPUTimeBudgetPoolForTesting(const char* name) { + return std::make_unique<CPUTimeBudgetPool>(name, &tracing_controller_, + tick_clock()->NowTicks()); +} + AutoAdvancingVirtualTimeDomain* MainThreadSchedulerImpl::GetVirtualTimeDomain() { return virtual_time_domain_.get(); @@ -3019,18 +2904,6 @@ MainThreadSchedulerImpl::ComputeCompositorPriorityFromUseCase() const { } } -void MainThreadSchedulerImpl::OnSafepointEntered() { - DCHECK(WTF::IsMainThread()); - DCHECK(!main_thread_only().IsInNestedRunloop()); - main_thread_only().metrics_helper.OnSafepointEntered(helper_.NowTicks()); -} - -void MainThreadSchedulerImpl::OnSafepointExited() { - DCHECK(WTF::IsMainThread()); - DCHECK(!main_thread_only().IsInNestedRunloop()); - main_thread_only().metrics_helper.OnSafepointExited(helper_.NowTicks()); -} - void MainThreadSchedulerImpl::ExecuteAfterCurrentTask( base::OnceClosure on_completion_task) { main_thread_only().on_task_completion_callbacks.push_back( diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h index b3543e7cb08..9420429c440 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h @@ -7,13 +7,11 @@ #include <map> #include <memory> -#include <random> #include <stack> #include "base/atomicops.h" #include "base/dcheck_is_on.h" #include "base/gtest_prod_util.h" -#include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/metrics/single_sample_metrics.h" #include "base/profiler/sample_metadata.h" @@ -31,7 +29,6 @@ #include "third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h" #include "third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h" #include "third_party/blink/renderer/platform/scheduler/common/tracing_helper.h" -#include "third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner.h" @@ -77,10 +74,10 @@ class FrameSchedulerImpl; class PageSchedulerImpl; class TaskQueueThrottler; class WebRenderWidgetSchedulingState; +class CPUTimeBudgetPool; class PLATFORM_EXPORT MainThreadSchedulerImpl : public ThreadSchedulerImpl, - public AgentSchedulingStrategy::Delegate, public IdleHelper::Delegate, public MainThreadSchedulerHelper::Observer, public RenderWidgetSignals::Observer, @@ -163,6 +160,8 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl MainThreadSchedulerImpl( std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager, absl::optional<base::Time> initial_virtual_time); + MainThreadSchedulerImpl(const MainThreadSchedulerImpl&) = delete; + MainThreadSchedulerImpl& operator=(const MainThreadSchedulerImpl&) = delete; ~MainThreadSchedulerImpl() override; @@ -233,7 +232,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl std::unique_ptr<ThreadScheduler::RendererPauseHandle> PauseScheduler() override; base::TimeTicks MonotonicallyIncreasingVirtualTime() override; - WebThreadScheduler* GetWebMainThreadSchedulerForTest() override; NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() override { return nullptr; } @@ -297,16 +295,9 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl using VirtualTimePolicy = PageScheduler::VirtualTimePolicy; - using BaseTimeOverridePolicy = - AutoAdvancingVirtualTimeDomain::BaseTimeOverridePolicy; - - // Tells the scheduler that all TaskQueues should use virtual time. Depending - // on the initial time, picks the policy to be either overriding or not. - base::TimeTicks EnableVirtualTime(); - // Tells the scheduler that all TaskQueues should use virtual time. Returns // the base::TimeTicks that virtual time offsets will be relative to. - base::TimeTicks EnableVirtualTime(BaseTimeOverridePolicy policy); + base::TimeTicks EnableVirtualTime(); bool IsVirtualTimeEnabled() const; // Migrates all task queues to real time. @@ -316,7 +307,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl bool VirtualTimeAllowedToAdvance() const; void SetVirtualTimePolicy(VirtualTimePolicy virtual_time_policy); void SetInitialVirtualTime(base::Time time); - void SetInitialVirtualTimeOffset(base::TimeDelta offset); void SetMaxVirtualTimeTaskStarvationCount(int max_task_starvation_count); base::TimeTicks IncrementVirtualTimePauseCount(); void DecrementVirtualTimePauseCount(); @@ -326,13 +316,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl void AddPageScheduler(PageSchedulerImpl*); void RemovePageScheduler(PageSchedulerImpl*); - void OnFrameAdded(const FrameSchedulerImpl& frame_scheduler); - void OnFrameRemoved(const FrameSchedulerImpl& frame_scheduler); - - AgentSchedulingStrategy& agent_scheduling_strategy() { - return *agent_scheduling_strategy_; - } - // Called by an associated PageScheduler when frozen or resumed. void OnPageFrozen(); void OnPageResumed(); @@ -379,14 +362,11 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl AutoAdvancingVirtualTimeDomain* GetVirtualTimeDomain(); - TaskQueueThrottler* task_queue_throttler() const { - return task_queue_throttler_.get(); - } + std::unique_ptr<CPUTimeBudgetPool> CreateCPUTimeBudgetPoolForTesting( + const char* name); // Virtual for test. virtual void OnMainFramePaint(); - void OnMainFrameLoad(const FrameSchedulerImpl& frame_scheduler); - void OnAgentStrategyUpdated(); void OnShutdownTaskQueue(const scoped_refptr<MainThreadTaskQueue>& queue); @@ -495,6 +475,9 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl kVirtual, }; + // WebThreadScheduler private implementation: + WebThreadScheduler* GetWebMainThreadScheduler() override; + static const char* TimeDomainTypeToString(TimeDomainType domain_type); void AddAgentGroupScheduler(AgentGroupSchedulerImpl*); @@ -527,11 +510,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl RAILMode& rail_mode() { return rail_mode_; } RAILMode rail_mode() const { return rail_mode_; } - bool& should_disable_throttling() { return should_disable_throttling_; } - bool should_disable_throttling() const { - return should_disable_throttling_; - } - bool& frozen_when_backgrounded() { return frozen_when_backgrounded_; } bool frozen_when_backgrounded() const { return frozen_when_backgrounded_; } @@ -578,7 +556,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl bool operator==(const Policy& other) const { return rail_mode_ == other.rail_mode_ && - should_disable_throttling_ == other.should_disable_throttling_ && frozen_when_backgrounded_ == other.frozen_when_backgrounded_ && should_prioritize_loading_with_compositing_ == other.should_prioritize_loading_with_compositing_ && @@ -601,7 +578,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl private: RAILMode rail_mode_{RAILMode::kAnimation}; - bool should_disable_throttling_{false}; bool frozen_when_backgrounded_{false}; bool should_prioritize_loading_with_compositing_{false}; bool should_freeze_compositor_task_queue_{false}; @@ -627,10 +603,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl MainThreadSchedulerImpl* scheduler_; // NOT OWNED }; - // AgentSchedulingStrategy::Delegate implementation: - void OnSetTimer(const FrameSchedulerImpl& frame_scheduler, - base::TimeDelta delay) override; - // IdleHelper::Delegate implementation: bool CanEnterLongIdlePeriod( base::TimeTicks now, @@ -639,8 +611,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl void OnIdlePeriodStarted() override; void OnIdlePeriodEnded() override; void OnPendingTasksChanged(bool has_tasks) override; - void OnSafepointEntered() override; - void OnSafepointExited() override; void DispatchRequestBeginMainFrameNotExpected(bool has_tasks); @@ -709,10 +679,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl void UpdateForInputEventOnCompositorThread(const WebInputEvent& event, InputEventState input_event_state); - // Notifies the per-agent scheduling strategy that an input event occurred. - void NotifyAgentSchedulerOnInputEvent(); - void OnAgentStrategyDelayPassed(base::WeakPtr<const FrameSchedulerImpl>); - // The task cost estimators and the UserModel need to be reset upon page // nagigation. This function does that. Must be called from the main thread. void ResetForNavigationLocked(); @@ -823,7 +789,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl MainThreadSchedulerHelper helper_; scoped_refptr<MainThreadTaskQueue> idle_helper_queue_; IdleHelper idle_helper_; - std::unique_ptr<TaskQueueThrottler> task_queue_throttler_; RenderWidgetSignals render_widget_scheduler_signals_; std::unique_ptr<FindInPageBudgetPoolController> @@ -861,12 +826,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl base::RepeatingClosure update_policy_closure_; DeadlineTaskRunner delayed_update_policy_runner_; CancelableClosureHolder end_renderer_hidden_idle_period_closure_; - base::RepeatingClosure notify_agent_strategy_on_input_event_closure_; - base::RepeatingCallback<void(base::WeakPtr<const FrameSchedulerImpl>)> - agent_strategy_delay_callback_; - - std::unique_ptr<AgentSchedulingStrategy> agent_scheduling_strategy_ = - AgentSchedulingStrategy::Create(*this); // We have decided to improve thread safety at the cost of some boilerplate // (the accessors) for the following data members. @@ -933,9 +892,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl base::Time initial_virtual_time; base::TimeTicks initial_virtual_time_ticks; - // This is used for cross origin navigations to account for virtual time - // advancing in the previous renderer. - base::TimeDelta initial_virtual_time_offset; VirtualTimePolicy virtual_time_policy; // In VirtualTimePolicy::kDeterministicLoading virtual time is only allowed @@ -1061,13 +1017,10 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl } PollableThreadSafeFlag policy_may_need_update_; - PollableThreadSafeFlag notify_agent_strategy_task_posted_; WTF::HashSet<AgentGroupSchedulerImpl*> agent_group_schedulers_; WebAgentGroupScheduler* current_agent_group_scheduler_{nullptr}; base::WeakPtrFactory<MainThreadSchedulerImpl> weak_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(MainThreadSchedulerImpl); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc index a6b55d5ebc2..61b5141a2c5 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc @@ -11,7 +11,6 @@ #include "base/bind.h" #include "base/callback.h" #include "base/callback_helpers.h" -#include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/metrics/field_trial_params.h" #include "base/run_loop.h" @@ -319,10 +318,9 @@ class MockPageSchedulerImpl : public PageSchedulerImpl { .WillByDefault(Return(true)); ON_CALL(*this, IsMainFrameLocal).WillByDefault(Return(true)); } - ~MockPageSchedulerImpl() override = default; - MockPageSchedulerImpl(const MockPageSchedulerImpl&) = delete; MockPageSchedulerImpl& operator=(const MockPageSchedulerImpl&) = delete; + ~MockPageSchedulerImpl() override = default; MOCK_METHOD(bool, RequestBeginMainFrameNotExpected, (bool)); MOCK_METHOD(bool, IsWaitingForMainFrameContentfulPaint, (), (const)); @@ -410,6 +408,10 @@ class MainThreadSchedulerImplTest : public testing::Test { MainThreadSchedulerImplTest() : MainThreadSchedulerImplTest({}, {}) {} + MainThreadSchedulerImplTest(const MainThreadSchedulerImplTest&) = delete; + MainThreadSchedulerImplTest& operator=(const MainThreadSchedulerImplTest&) = + delete; + ~MainThreadSchedulerImplTest() override = default; void SetUp() override { @@ -984,8 +986,6 @@ class MainThreadSchedulerImplTest : public testing::Test { bool simulate_throttleable_task_ran_; bool initially_ensure_usecase_none_ = true; uint64_t next_begin_frame_number_ = viz::BeginFrameArgs::kStartingFrameNumber; - - DISALLOW_COPY_AND_ASSIGN(MainThreadSchedulerImplTest); }; TEST_F(MainThreadSchedulerImplTest, TestPostDefaultTask) { @@ -2511,18 +2511,6 @@ TEST_F(MainThreadSchedulerImplTest, StopAndThrottleThrottleableQueue) { EXPECT_THAT(run_order, testing::ElementsAre()); } -TEST_F(MainThreadSchedulerImplTest, ThrottleAndPauseRenderer) { - Vector<String> run_order; - PostTestTasks(&run_order, "T1 T2"); - - MainThreadTaskQueue::ThrottleHandle handle = - throttleable_task_queue()->Throttle(); - base::RunLoop().RunUntilIdle(); - auto pause_handle = scheduler_->PauseRenderer(); - base::RunLoop().RunUntilIdle(); - EXPECT_THAT(run_order, testing::ElementsAre()); -} - TEST_F(MainThreadSchedulerImplTest, MultipleStopsNeedMultipleResumes) { Vector<String> run_order; PostTestTasks(&run_order, "T1 T2"); @@ -2740,8 +2728,7 @@ TEST_F( SYNCHRONIZED_GESTURE_ThrottleableTaskThrottling_ThrottleableQueuesStopped) { SimulateCompositorGestureStart(TouchEventPolicy::kSendTouchStart); - base::TimeTicks first_throttled_run_time = - TaskQueueThrottler::AlignedThrottledRunTime(Now()); + base::TimeTicks first_run_time = Now(); size_t count = 0; // With the compositor task taking 10ms, there is not enough time to run this @@ -2774,7 +2761,7 @@ TEST_F( // Before the policy is updated the queue will be enabled. Subsequently it // will be disabled until the throttled queue is pumped. - bool expect_queue_enabled = (i == 0) || (Now() > first_throttled_run_time); + bool expect_queue_enabled = (i == 0) || (Now() > first_run_time); if (paused) expect_queue_enabled = false; EXPECT_EQ(expect_queue_enabled, @@ -3142,8 +3129,7 @@ TEST_F( TEST_F(MainThreadSchedulerImplTest, EnableVirtualTime) { EXPECT_FALSE(scheduler_->IsVirtualTimeEnabled()); - scheduler_->EnableVirtualTime( - MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE); + scheduler_->EnableVirtualTime(); EXPECT_TRUE(scheduler_->IsVirtualTimeEnabled()); scoped_refptr<MainThreadTaskQueue> loading_tq = scheduler_->NewLoadingTaskQueue( @@ -3218,16 +3204,14 @@ TEST_F(MainThreadSchedulerImplTest, EnableVirtualTimeAfterThrottling) { frame_scheduler->SetFrameVisible(false); EXPECT_TRUE(throttleable_tq->IsThrottled()); - scheduler_->EnableVirtualTime( - MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE); + scheduler_->EnableVirtualTime(); EXPECT_EQ(throttleable_tq->GetTaskQueue()->GetTimeDomain(), scheduler_->GetVirtualTimeDomain()); - EXPECT_FALSE(throttleable_tq->IsThrottled()); + EXPECT_TRUE(throttleable_tq->IsThrottled()); } TEST_F(MainThreadSchedulerImplTest, DisableVirtualTimeForTesting) { - scheduler_->EnableVirtualTime( - MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE); + scheduler_->EnableVirtualTime(); scheduler_->DisableVirtualTimeForTesting(); EXPECT_EQ(scheduler_->DefaultTaskQueue()->GetTaskQueue()->GetTimeDomain(), scheduler_->real_time_domain()); @@ -3245,8 +3229,7 @@ TEST_F(MainThreadSchedulerImplTest, DisableVirtualTimeForTesting) { } TEST_F(MainThreadSchedulerImplTest, VirtualTimePauser) { - scheduler_->EnableVirtualTime( - MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE); + scheduler_->EnableVirtualTime(); scheduler_->SetVirtualTimePolicy( PageSchedulerImpl::VirtualTimePolicy::kDeterministicLoading); @@ -3266,8 +3249,7 @@ TEST_F(MainThreadSchedulerImplTest, VirtualTimePauser) { } TEST_F(MainThreadSchedulerImplTest, VirtualTimePauserNonInstantTask) { - scheduler_->EnableVirtualTime( - MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE); + scheduler_->EnableVirtualTime(); scheduler_->SetVirtualTimePolicy( PageSchedulerImpl::VirtualTimePolicy::kDeterministicLoading); @@ -3286,8 +3268,7 @@ TEST_F(MainThreadSchedulerImplTest, VirtualTimeWithOneQueueWithoutVirtualTime) { // This test ensures that we do not do anything strange like stopping // processing task queues after we encountered one task queue with // DoNotUseVirtualTime trait. - scheduler_->EnableVirtualTime( - MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE); + scheduler_->EnableVirtualTime(); scheduler_->SetVirtualTimePolicy( PageSchedulerImpl::VirtualTimePolicy::kDeterministicLoading); @@ -3345,11 +3326,11 @@ TEST_F(MainThreadSchedulerImplTest, Tracing) { CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_); scheduler_->AddPageScheduler(page_scheduler2.get()); - CPUTimeBudgetPool* time_budget_pool = - scheduler_->task_queue_throttler()->CreateCPUTimeBudgetPool("test"); + std::unique_ptr<CPUTimeBudgetPool> time_budget_pool = + scheduler_->CreateCPUTimeBudgetPoolForTesting("test"); - time_budget_pool->AddQueue(base::TimeTicks(), - throttleable_task_queue()->GetTaskQueue()); + throttleable_task_queue()->AddToBudgetPool(base::TimeTicks(), + time_budget_pool.get()); throttleable_task_runner_->PostTask(FROM_HERE, base::BindOnce(NullTask)); @@ -3604,8 +3585,7 @@ TEST_F(MainThreadSchedulerImplTest, TaskQueueReferenceClearedOnShutdown) { scheduler_->OnShutdownTaskQueue(queue1); - scheduler_->EnableVirtualTime( - MainThreadSchedulerImpl::BaseTimeOverridePolicy::DO_NOT_OVERRIDE); + scheduler_->EnableVirtualTime(); // Virtual time should be enabled for queue2, as it is a regular queue and // nothing should change for queue1 because it was shut down. @@ -3939,212 +3919,6 @@ TEST_F(VeryHighPriorityForCompositingAfterDelayExperimentTest, EXPECT_EQ(UseCase::kNone, CurrentUseCase()); } -class VeryHighPriorityForCompositingBudgetExperimentTest - : public MainThreadSchedulerImplTest { - public: - VeryHighPriorityForCompositingBudgetExperimentTest() - : MainThreadSchedulerImplTest({kVeryHighPriorityForCompositingBudget}, - {}) {} -}; - -TEST_F(VeryHighPriorityForCompositingBudgetExperimentTest, - TestCompositorPolicy_CompositorPriorityVeryHighToNormal) { - Vector<String> run_order; - PostTestTasks(&run_order, "I1 D1 C1 D2 C2 P1"); - EnableIdleTasks(); - base::RunLoop().RunUntilIdle(); - - // Compositor is at kVeryHighPriority Initially. - EXPECT_THAT(run_order, - testing::ElementsAre("P1", "C1", "C2", "D1", "D2", "I1")); - EXPECT_EQ(UseCase::kNone, CurrentUseCase()); - - // 1000ms BeginMainFrame compositor task will exhaust the budget. Compositor - // tasks will be run at normal priority. - DoMainFrame(); - RunSlowCompositorTask(); - - run_order.clear(); - PostTestTasks(&run_order, "I1 D1 C1 D2 C2 P1"); - EnableIdleTasks(); - base::RunLoop().RunUntilIdle(); - - EXPECT_THAT(run_order, - testing::ElementsAre("P1", "D1", "C1", "D2", "C2", "I1")); - EXPECT_EQ(UseCase::kNone, CurrentUseCase()); -} - -TEST_F(VeryHighPriorityForCompositingBudgetExperimentTest, - TestCompositorPolicy_CompositorPriorityNormalToVeryHigh) { - // 1000ms BeginMainFrame compositor task will exhaust the budget. - DoMainFrame(); - RunSlowCompositorTask(); - - Vector<String> run_order; - PostTestTasks(&run_order, "I1 D1 C1 D2 C2 P1"); - EnableIdleTasks(); - base::RunLoop().RunUntilIdle(); - - // Compositor is at kNormalPriority, it will inteleave with default tasks. - EXPECT_THAT(run_order, - testing::ElementsAre("P1", "D1", "C1", "D2", "C2", "I1")); - EXPECT_EQ(UseCase::kNone, CurrentUseCase()); - - // Recover the budget. - AdvanceTimeWithTask(12); - - run_order.clear(); - PostTestTasks(&run_order, "I1 D1 C1 D2 C2 P1"); - EnableIdleTasks(); - base::RunLoop().RunUntilIdle(); - - // Compositor is now at kVeryHighPriority, compositing tasks will run - // before default tasks. - EXPECT_THAT(run_order, - testing::ElementsAre("P1", "C1", "C2", "D1", "D2", "I1")); - EXPECT_EQ(UseCase::kNone, CurrentUseCase()); -} - -class DisableNonMainTimerQueuesUntilFMPTest - : public MainThreadSchedulerImplTest { - public: - DisableNonMainTimerQueuesUntilFMPTest() - : MainThreadSchedulerImplTest({{kPerAgentSchedulingExperiments, - {{"queues", "timer-queues"}, - {"method", "disable"}, - {"signal", "fmp"}}}}) {} -}; - -TEST_F(DisableNonMainTimerQueuesUntilFMPTest, DisablesOnlyNonMainTimerQueue) { - auto page_scheduler = - CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_); - - NiceMock<MockFrameDelegate> frame_delegate{}; - std::unique_ptr<FrameSchedulerImpl> frame_scheduler = - CreateFrameScheduler(page_scheduler.get(), &frame_delegate, nullptr, - FrameScheduler::FrameType::kSubframe); - - scoped_refptr<MainThreadTaskQueue> throttleable_tq = QueueForTaskType( - frame_scheduler.get(), TaskType::kJavascriptTimerDelayedLowNesting); - ForceUpdatePolicyAndGetCurrentUseCase(); - - EXPECT_FALSE(throttleable_tq->GetTaskQueue()->IsQueueEnabled()); - - ignore_result( - scheduler_->agent_scheduling_strategy().OnMainFrameFirstMeaningfulPaint( - *main_frame_scheduler_)); - ForceUpdatePolicyAndGetCurrentUseCase(); - - EXPECT_TRUE(throttleable_tq->GetTaskQueue()->IsQueueEnabled()); -} - -TEST_F(DisableNonMainTimerQueuesUntilFMPTest, - ShouldNotifyAgentStrategyOnInput) { - auto page_scheduler = - CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_); - - NiceMock<MockFrameDelegate> frame_delegate{}; - std::unique_ptr<FrameSchedulerImpl> frame_scheduler = - CreateFrameScheduler(page_scheduler.get(), &frame_delegate, nullptr, - FrameScheduler::FrameType::kSubframe); - - scoped_refptr<MainThreadTaskQueue> timer_tq = QueueForTaskType( - frame_scheduler.get(), TaskType::kJavascriptTimerDelayedLowNesting); - - FakeInputEvent mouse_move_event{WebInputEvent::Type::kMouseMove, - blink::WebInputEvent::kLeftButtonDown}; - FakeInputEvent mouse_down_event{WebInputEvent::Type::kMouseDown, - blink::WebInputEvent::kLeftButtonDown}; - InputEventState event_state{}; - - // Mouse move event should be ignored, meaning the queue should be disabled. - scheduler_->DidHandleInputEventOnCompositorThread(mouse_move_event, - event_state); - ForceUpdatePolicyAndGetCurrentUseCase(); - EXPECT_FALSE(timer_tq->GetTaskQueue()->IsQueueEnabled()); - - // Mouse down should cause MTSI to notify the agent scheduling strategy, which - // should re-enable the throttleable queue. - scheduler_->DidHandleInputEventOnCompositorThread(mouse_down_event, - event_state); - base::RunLoop().RunUntilIdle(); // Notification is posted to the main thread. - EXPECT_TRUE(timer_tq->GetTaskQueue()->IsQueueEnabled()); -} - -class BestEffortNonMainQueuesUntilOnLoadTest - : public MainThreadSchedulerImplTest { - public: - BestEffortNonMainQueuesUntilOnLoadTest() - : MainThreadSchedulerImplTest({{kPerAgentSchedulingExperiments, - {{"queues", "all-queues"}, - {"method", "best-effort"}, - {"signal", "onload"}}}}) {} -}; - -TEST_F(BestEffortNonMainQueuesUntilOnLoadTest, DeprioritizesAllNonMainQueues) { - auto page_scheduler = - CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_); - - NiceMock<MockFrameDelegate> frame_delegate{}; - std::unique_ptr<FrameSchedulerImpl> frame_scheduler = - CreateFrameScheduler(page_scheduler.get(), &frame_delegate, nullptr, - FrameScheduler::FrameType::kSubframe); - - scoped_refptr<MainThreadTaskQueue> non_timer_tq = - QueueForTaskType(frame_scheduler.get(), TaskType::kNetworking); - ForceUpdatePolicyAndGetCurrentUseCase(); - EXPECT_EQ(non_timer_tq->GetTaskQueue()->GetQueuePriority(), - TaskQueue::QueuePriority::kBestEffortPriority); - - scheduler_->OnMainFrameLoad(*main_frame_scheduler_); - - EXPECT_EQ(non_timer_tq->GetTaskQueue()->GetQueuePriority(), - TaskQueue::QueuePriority::kNormalPriority); -} - -class BestEffortNonMainQueuesUntilOnFMPTimeoutTest - : public MainThreadSchedulerImplTest { - public: - BestEffortNonMainQueuesUntilOnFMPTimeoutTest() - : MainThreadSchedulerImplTest({{kPerAgentSchedulingExperiments, - {{"queues", "all-queues"}, - {"method", "best-effort"}, - {"signal", "fmp"}, - {"delay_ms", "1000"}}}}) {} -}; - -TEST_F(BestEffortNonMainQueuesUntilOnFMPTimeoutTest, - DeprioritizesNonMainQueues) { - auto page_scheduler = CreatePageScheduler( - /* page_scheduler_delegate= */ nullptr, scheduler_.get(), - *agent_group_scheduler_); - - NiceMock<MockFrameDelegate> frame_delegate{}; - std::unique_ptr<FrameSchedulerImpl> frame_scheduler = CreateFrameScheduler( - page_scheduler.get(), &frame_delegate, /* blame_context= */ nullptr, - FrameScheduler::FrameType::kSubframe); - - scoped_refptr<MainThreadTaskQueue> non_timer_tq = - QueueForTaskType(frame_scheduler.get(), TaskType::kNetworking); - ForceUpdatePolicyAndGetCurrentUseCase(); - EXPECT_EQ(non_timer_tq->GetTaskQueue()->GetQueuePriority(), - TaskQueue::QueuePriority::kBestEffortPriority); - - ignore_result( - scheduler_->agent_scheduling_strategy().OnMainFrameFirstMeaningfulPaint( - *main_frame_scheduler_)); - - // Queue should still have lower priority, since we just started counting - // towards the timeout. - EXPECT_EQ(non_timer_tq->GetTaskQueue()->GetQueuePriority(), - TaskQueue::QueuePriority::kBestEffortPriority); - - test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(1000)); - - EXPECT_EQ(non_timer_tq->GetTaskQueue()->GetQueuePriority(), - TaskQueue::QueuePriority::kNormalPriority); -} - TEST_F(MainThreadSchedulerImplTest, ThrottleHandleThrottlesQueue) { EXPECT_FALSE(throttleable_task_queue()->IsThrottled()); { diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc index eed8a8c649e..f45ef3bc99a 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc @@ -115,7 +115,14 @@ MainThreadTaskQueue::MainThreadTaskQueue( agent_group_scheduler_(params.agent_group_scheduler), frame_scheduler_(params.frame_scheduler) { task_queue_ = base::MakeRefCounted<TaskQueue>(std::move(impl), spec); + // Throttling needs |should_notify_observers| to get task timing. + DCHECK(!params.queue_traits.can_be_throttled || spec.should_notify_observers) + << "Throttled queue is not supported with |!should_notify_observers|"; if (task_queue_->HasImpl() && spec.should_notify_observers) { + if (params.queue_traits.can_be_throttled) { + throttler_.emplace(task_queue_.get(), + main_thread_scheduler_->GetTickClock()); + } // TaskQueueImpl may be null for tests. // TODO(scheduler-dev): Consider mapping directly to // MainThreadSchedulerImpl::OnTaskStarted/Completed. At the moment this @@ -128,7 +135,9 @@ MainThreadTaskQueue::MainThreadTaskQueue( } } -MainThreadTaskQueue::~MainThreadTaskQueue() = default; +MainThreadTaskQueue::~MainThreadTaskQueue() { + DCHECK(!wake_up_budget_pool_); +} void MainThreadTaskQueue::OnTaskStarted( const base::sequence_manager::Task& task, @@ -149,8 +158,10 @@ void MainThreadTaskQueue::OnTaskCompleted( void MainThreadTaskQueue::OnTaskRunTimeReported( TaskQueue::TaskTiming* task_timing) { - main_thread_scheduler_->task_queue_throttler()->OnTaskRunTimeReported( - task_queue_.get(), task_timing->start_time(), task_timing->end_time()); + if (throttler_) { + throttler_->OnTaskRunTimeReported(task_timing->start_time(), + task_timing->end_time()); + } } void MainThreadTaskQueue::DetachFromMainThreadScheduler() { @@ -191,6 +202,7 @@ void MainThreadTaskQueue::DetachOnIPCTaskPostedWhileInBackForwardCache() { void MainThreadTaskQueue::ShutdownTaskQueue() { ClearReferencesToSchedulers(); + throttler_.reset(); task_queue_->ShutdownTaskQueue(); } @@ -212,11 +224,6 @@ WebAgentGroupScheduler* MainThreadTaskQueue::GetAgentGroupScheduler() { void MainThreadTaskQueue::ClearReferencesToSchedulers() { if (main_thread_scheduler_) { main_thread_scheduler_->OnShutdownTaskQueue(this); - - if (main_thread_scheduler_->task_queue_throttler()) { - main_thread_scheduler_->task_queue_throttler()->ShutdownTaskQueue( - task_queue_.get()); - } } main_thread_scheduler_ = nullptr; agent_group_scheduler_ = nullptr; @@ -251,6 +258,10 @@ void MainThreadTaskQueue::SetWebSchedulingPriority( frame_scheduler_->OnWebSchedulingTaskQueuePriorityChanged(this); } +void MainThreadTaskQueue::OnWebSchedulingTaskQueueDestroyed() { + frame_scheduler_->OnWebSchedulingTaskQueueDestroyed(this); +} + absl::optional<WebSchedulingPriority> MainThreadTaskQueue::web_scheduling_priority() const { return web_scheduling_priority_; @@ -258,8 +269,7 @@ MainThreadTaskQueue::web_scheduling_priority() const { bool MainThreadTaskQueue::IsThrottled() const { if (main_thread_scheduler_) { - return main_thread_scheduler_->task_queue_throttler()->IsThrottled( - task_queue_.get()); + return throttler_.has_value() && throttler_->IsThrottled(); } else { // When the frame detaches the task queue is removed from the throttler. return false; @@ -268,32 +278,29 @@ bool MainThreadTaskQueue::IsThrottled() const { MainThreadTaskQueue::ThrottleHandle MainThreadTaskQueue::Throttle() { DCHECK(CanBeThrottled()); - return ThrottleHandle( - task_queue_.get()->AsWeakPtr(), - main_thread_scheduler_->task_queue_throttler()->AsWeakPtr()); + return ThrottleHandle(AsWeakPtr()); } void MainThreadTaskQueue::AddToBudgetPool(base::TimeTicks now, BudgetPool* pool) { - pool->AddQueue(now, task_queue_.get()); + pool->AddThrottler(now, &throttler_.value()); } void MainThreadTaskQueue::RemoveFromBudgetPool(base::TimeTicks now, BudgetPool* pool) { - pool->RemoveQueue(now, task_queue_.get()); + pool->RemoveThrottler(now, &throttler_.value()); } -void MainThreadTaskQueue::SetImmediateWakeUpForTest() { - if (main_thread_scheduler_) { - main_thread_scheduler_->task_queue_throttler()->OnQueueNextWakeUpChanged( - task_queue_.get(), base::TimeTicks()); - } +void MainThreadTaskQueue::SetWakeUpBudgetPool( + WakeUpBudgetPool* wake_up_budget_pool) { + wake_up_budget_pool_ = wake_up_budget_pool; } void MainThreadTaskQueue::WriteIntoTrace(perfetto::TracedValue context) const { auto dict = std::move(context).WriteDictionary(); dict.Add("type", queue_type_); dict.Add("traits", queue_traits_); + dict.Add("throttler", throttler_); } void MainThreadTaskQueue::QueueTraits::WriteIntoTrace( diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h index 6f5c7c7aabe..5c6edb27fc5 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h @@ -13,6 +13,7 @@ #include "base/task/sequence_manager/task_queue_impl.h" #include "base/task/sequence_manager/time_domain.h" #include "net/base/request_priority.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h" #include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/agent_group_scheduler_impl.h" @@ -41,6 +42,7 @@ class TaskQueueThrottlerTest; class FrameSchedulerImpl; class MainThreadSchedulerImpl; +class WakeUpBudgetPool; // TODO(kdillon): Remove ref-counting of MainThreadTaskQueues as it's no longer // needed. @@ -100,29 +102,25 @@ class PLATFORM_EXPORT MainThreadTaskQueue // the queue will remain throttled as long as the handle is alive. class ThrottleHandle { public: - ThrottleHandle(base::WeakPtr<TaskQueue> task_queue, - base::WeakPtr<TaskQueueThrottler> throttler) - : task_queue_(std::move(task_queue)), throttler_(std::move(throttler)) { - if (task_queue_ && throttler_) - throttler_->IncreaseThrottleRefCount(task_queue_.get()); + explicit ThrottleHandle(base::WeakPtr<MainThreadTaskQueue> task_queue) + : task_queue_(std::move(task_queue)) { + if (task_queue_) + task_queue_->throttler_->IncreaseThrottleRefCount(); } ~ThrottleHandle() { - if (task_queue_ && throttler_) - throttler_->DecreaseThrottleRefCount(task_queue_.get()); + if (task_queue_) + task_queue_->throttler_->DecreaseThrottleRefCount(); } // Move-only. ThrottleHandle(ThrottleHandle&& other) - : task_queue_(std::move(other.task_queue_)), - throttler_(std::move(other.throttler_)) { + : task_queue_(std::move(other.task_queue_)) { other.task_queue_ = nullptr; - other.throttler_ = nullptr; } ThrottleHandle& operator=(ThrottleHandle&&); private: - base::WeakPtr<TaskQueue> task_queue_; - base::WeakPtr<TaskQueueThrottler> throttler_; + base::WeakPtr<MainThreadTaskQueue> task_queue_; }; // Returns name of the given queue type. Returned string has application @@ -165,8 +163,9 @@ class PLATFORM_EXPORT MainThreadTaskQueue kHighPriorityLocalFrame = 8, kCompositor = 9, // Main-thread only. kInput = 10, + kPostMessageForwarding = 11, - kCount = 11 + kCount = 12 }; // kPrioritisationTypeWidthBits is the number of bits required @@ -181,6 +180,7 @@ class PLATFORM_EXPORT MainThreadTaskQueue "Wrong Instanstiation for kPrioritisationTypeWidthBits"); QueueTraits(const QueueTraits&) = default; + QueueTraits& operator=(const QueueTraits&) = default; QueueTraits SetCanBeDeferred(bool value) { can_be_deferred = value; @@ -458,6 +458,8 @@ class PLATFORM_EXPORT MainThreadTaskQueue void SetWebSchedulingPriority(WebSchedulingPriority priority); absl::optional<WebSchedulingPriority> web_scheduling_priority() const; + void OnWebSchedulingTaskQueueDestroyed(); + // TODO(kdillon): Improve MTTQ API surface so that we no longer // need to expose the raw pointer to the queue. TaskQueue* GetTaskQueue() { return task_queue_.get(); } @@ -485,9 +487,8 @@ class PLATFORM_EXPORT MainThreadTaskQueue void AddToBudgetPool(base::TimeTicks now, BudgetPool* pool); void RemoveFromBudgetPool(base::TimeTicks now, BudgetPool* pool); - // This method is only used for tests. If this queue is throttled it will - // notify the throttler that this queue should wake immediately. - void SetImmediateWakeUpForTest(); + void SetWakeUpBudgetPool(WakeUpBudgetPool* wake_up_budget_pool); + WakeUpBudgetPool* GetWakeUpBudgetPool() const { return wake_up_budget_pool_; } base::WeakPtr<MainThreadTaskQueue> AsWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); @@ -511,6 +512,9 @@ class PLATFORM_EXPORT MainThreadTaskQueue const QueueCreationParams& params, MainThreadSchedulerImpl* main_thread_scheduler); + MainThreadTaskQueue(const MainThreadTaskQueue&) = delete; + MainThreadTaskQueue& operator=(const MainThreadTaskQueue&) = delete; + ~MainThreadTaskQueue(); private: @@ -527,6 +531,7 @@ class PLATFORM_EXPORT MainThreadTaskQueue void ClearReferencesToSchedulers(); scoped_refptr<TaskQueue> task_queue_; + absl::optional<TaskQueueThrottler> throttler_; const QueueType queue_type_; const QueueTraits queue_traits_; @@ -553,9 +558,10 @@ class PLATFORM_EXPORT MainThreadTaskQueue // be set to a different value afterwards (except in tests). FrameSchedulerImpl* frame_scheduler_; // NOT OWNED - base::WeakPtrFactory<MainThreadTaskQueue> weak_ptr_factory_{this}; + // The WakeUpBudgetPool for this TaskQueue, if any. + WakeUpBudgetPool* wake_up_budget_pool_{nullptr}; // NOT OWNED - DISALLOW_COPY_AND_ASSIGN(MainThreadTaskQueue); + base::WeakPtrFactory<MainThreadTaskQueue> weak_ptr_factory_{this}; }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_unittest.cc index 5865e9999f4..712e2d0a85a 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_unittest.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_unittest.cc @@ -10,7 +10,6 @@ #include "base/bind.h" #include "base/location.h" -#include "base/macros.h" #include "base/message_loop/message_pump.h" #include "base/message_loop/message_pump_type.h" #include "base/run_loop.h" @@ -48,6 +47,8 @@ class MockTaskObserver : public Thread::TaskObserver { class MainThreadTest : public testing::Test { public: MainThreadTest() = default; + MainThreadTest(const MainThreadTest&) = delete; + MainThreadTest& operator=(const MainThreadTest&) = delete; void SetUp() override { clock_.Advance(base::TimeDelta::FromMicroseconds(5000)); @@ -77,8 +78,6 @@ class MainThreadTest : public testing::Test { std::unique_ptr<MainThreadSchedulerImpl> scheduler_; std::unique_ptr<ScopedSchedulerOverrider> scheduler_overrider_; Thread* thread_; - - DISALLOW_COPY_AND_ASSIGN(MainThreadTest); }; TEST_F(MainThreadTest, TestTaskObserver) { diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_web_scheduling_task_queue_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_web_scheduling_task_queue_impl.cc new file mode 100644 index 00000000000..a14b6e55102 --- /dev/null +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_web_scheduling_task_queue_impl.cc @@ -0,0 +1,81 @@ +// Copyright 2019 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 "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_web_scheduling_task_queue_impl.h" + +#include "third_party/blink/public/platform/task_type.h" +#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h" + +namespace blink { +namespace scheduler { + +MainThreadWebSchedulingTaskQueueImpl::WebSchedulingTaskRunner:: + WebSchedulingTaskRunner( + scoped_refptr<base::SingleThreadTaskRunner> immediate_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> delayed_task_runner) + : immediate_task_runner_(std::move(immediate_task_runner)), + delayed_task_runner_(std::move(delayed_task_runner)) {} + +bool MainThreadWebSchedulingTaskQueueImpl::WebSchedulingTaskRunner:: + PostDelayedTask(const base::Location& location, + base::OnceClosure task, + base::TimeDelta delay) { + return GetTaskRunnerForDelay(delay)->PostDelayedTask(location, + std::move(task), delay); +} + +bool MainThreadWebSchedulingTaskQueueImpl::WebSchedulingTaskRunner:: + PostNonNestableDelayedTask(const base::Location& location, + base::OnceClosure task, + base::TimeDelta delay) { + return GetTaskRunnerForDelay(delay)->PostNonNestableDelayedTask( + location, std::move(task), delay); +} + +bool MainThreadWebSchedulingTaskQueueImpl::WebSchedulingTaskRunner:: + RunsTasksInCurrentSequence() const { + DCHECK_EQ(immediate_task_runner_->RunsTasksInCurrentSequence(), + delayed_task_runner_->RunsTasksInCurrentSequence()); + return immediate_task_runner_->RunsTasksInCurrentSequence(); +} + +base::SingleThreadTaskRunner* MainThreadWebSchedulingTaskQueueImpl:: + WebSchedulingTaskRunner::GetTaskRunnerForDelay(base::TimeDelta delay) { + return delay > base::TimeDelta() ? delayed_task_runner_.get() + : immediate_task_runner_.get(); +} + +MainThreadWebSchedulingTaskQueueImpl::MainThreadWebSchedulingTaskQueueImpl( + base::WeakPtr<MainThreadTaskQueue> immediate_task_queue, + base::WeakPtr<MainThreadTaskQueue> delayed_task_queue) + : task_runner_(base::MakeRefCounted<WebSchedulingTaskRunner>( + immediate_task_queue->CreateTaskRunner( + TaskType::kExperimentalWebScheduling), + delayed_task_queue->CreateTaskRunner( + TaskType::kExperimentalWebScheduling))), + immediate_task_queue_(std::move(immediate_task_queue)), + delayed_task_queue_(std::move(delayed_task_queue)) {} + +MainThreadWebSchedulingTaskQueueImpl::~MainThreadWebSchedulingTaskQueueImpl() { + if (immediate_task_queue_) + immediate_task_queue_->OnWebSchedulingTaskQueueDestroyed(); + if (delayed_task_queue_) + delayed_task_queue_->OnWebSchedulingTaskQueueDestroyed(); +} + +void MainThreadWebSchedulingTaskQueueImpl::SetPriority( + WebSchedulingPriority priority) { + if (immediate_task_queue_) + immediate_task_queue_->SetWebSchedulingPriority(priority); + if (delayed_task_queue_) + delayed_task_queue_->SetWebSchedulingPriority(priority); +} + +scoped_refptr<base::SingleThreadTaskRunner> +MainThreadWebSchedulingTaskQueueImpl::GetTaskRunner() { + return task_runner_; +} + +} // namespace scheduler +} // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_web_scheduling_task_queue_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_web_scheduling_task_queue_impl.h new file mode 100644 index 00000000000..33ac23e160c --- /dev/null +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_web_scheduling_task_queue_impl.h @@ -0,0 +1,69 @@ +// Copyright 2019 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. + +#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MAIN_THREAD_WEB_SCHEDULING_TASK_QUEUE_IMPL_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MAIN_THREAD_WEB_SCHEDULING_TASK_QUEUE_IMPL_H_ + +#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_task_queue.h" + +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "base/single_thread_task_runner.h" +#include "third_party/blink/renderer/platform/platform_export.h" +#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h" + +namespace blink { +namespace scheduler { + +class MainThreadTaskQueue; + +class PLATFORM_EXPORT MainThreadWebSchedulingTaskQueueImpl + : public WebSchedulingTaskQueue { + public: + MainThreadWebSchedulingTaskQueueImpl( + base::WeakPtr<MainThreadTaskQueue> immediate_task_queue, + base::WeakPtr<MainThreadTaskQueue> delayed_task_queue); + ~MainThreadWebSchedulingTaskQueueImpl() override; + + void SetPriority(WebSchedulingPriority) override; + + scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override; + + private: + // In order to throttle delayed tasks in the background, we manage two + // MainThreadTaskQueues and their associated TaskRunners---one for delayed + // tasks and one for non-delayed tasks (immediate). Rather than exposing this + // to the web scheduling layer, we implement a simple custom TaskRunner that + // handles picking the appropriate underlying TaskRunner based on the delay + // value and return that in GetTaskRunner(). + class WebSchedulingTaskRunner : public base::SingleThreadTaskRunner { + public: + WebSchedulingTaskRunner( + scoped_refptr<base::SingleThreadTaskRunner> immediate_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> delayed_task_runner); + + bool PostDelayedTask(const base::Location& location, + base::OnceClosure task, + base::TimeDelta delay) override; + bool PostNonNestableDelayedTask(const base::Location& from_here, + base::OnceClosure task, + base::TimeDelta delay) override; + bool RunsTasksInCurrentSequence() const override; + + private: + base::SingleThreadTaskRunner* GetTaskRunnerForDelay(base::TimeDelta delay); + + const scoped_refptr<base::SingleThreadTaskRunner> immediate_task_runner_; + const scoped_refptr<base::SingleThreadTaskRunner> delayed_task_runner_; + }; + + scoped_refptr<WebSchedulingTaskRunner> task_runner_; + base::WeakPtr<MainThreadTaskQueue> immediate_task_queue_; + base::WeakPtr<MainThreadTaskQueue> delayed_task_queue_; +}; + +} // namespace scheduler +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MAIN_THREAD_WEB_SCHEDULING_TASK_QUEUE_IMPL_H_ diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h index 70508be6a54..c2393d0566f 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h @@ -5,7 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MEMORY_PURGE_MANAGER_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MEMORY_PURGE_MANAGER_H_ -#include "base/macros.h" #include "base/single_thread_task_runner.h" #include "base/timer/timer.h" #include "third_party/blink/renderer/platform/platform_export.h" @@ -17,6 +16,8 @@ namespace blink { class PLATFORM_EXPORT MemoryPurgeManager { public: MemoryPurgeManager(scoped_refptr<base::SingleThreadTaskRunner> task_runner); + MemoryPurgeManager(const MemoryPurgeManager&) = delete; + MemoryPurgeManager& operator=(const MemoryPurgeManager&) = delete; ~MemoryPurgeManager(); // Called when a page is created or destroyed, to maintain the total count of @@ -100,8 +101,6 @@ class PLATFORM_EXPORT MemoryPurgeManager { // Timer to delay memory purging. base::OneShotTimer purge_timer_; - - DISALLOW_COPY_AND_ASSIGN(MemoryPurgeManager); }; } // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc index 9e5bb83e57f..c298db2747e 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc @@ -26,6 +26,8 @@ class MemoryPurgeManagerTest : public testing::Test { : task_environment_(base::test::TaskEnvironment::MainThreadType::UI, base::test::TaskEnvironment::TimeSource::MOCK_TIME), memory_purge_manager_(task_environment_.GetMainThreadTaskRunner()) {} + MemoryPurgeManagerTest(const MemoryPurgeManagerTest&) = delete; + MemoryPurgeManagerTest& operator=(const MemoryPurgeManagerTest&) = delete; void SetUp() override { memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>( @@ -67,8 +69,6 @@ class MemoryPurgeManagerTest : public testing::Test { void OnMemoryPressure(base::MemoryPressureListener::MemoryPressureLevel) { memory_pressure_count_++; } - - DISALLOW_COPY_AND_ASSIGN(MemoryPurgeManagerTest); }; // Verify that OnPageFrozen() triggers a memory pressure notification in a diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc index 5a3caa8f6e9..08564b41eee 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc @@ -19,7 +19,9 @@ #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/scheduler/common/features.h" #include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h" +#include "third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h" #include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h" +#include "third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h" #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" @@ -42,11 +44,6 @@ constexpr double kDefaultMaxBackgroundBudgetLevelInSeconds = 3; constexpr double kDefaultInitialBackgroundBudgetInSeconds = 1; constexpr double kDefaultMaxBackgroundThrottlingDelayInSeconds = 0; -// Given that we already align timers to 1Hz, do not report throttling if -// it is under 3s. -constexpr base::TimeDelta kMinimalBackgroundThrottlingDurationToReport = - base::TimeDelta::FromSeconds(3); - // Delay for fully throttling the page after backgrounding. constexpr base::TimeDelta kThrottlingDelayAfterBackgrounding = base::TimeDelta::FromSeconds(10); @@ -69,6 +66,12 @@ constexpr base::TimeDelta kDefaultDelayForBackgroundAndNetworkIdleTabFreezing = constexpr base::TimeDelta kThrottledWakeUpDuration = base::TimeDelta::FromMilliseconds(3); +// The duration for which intensive throttling should be inhibited for +// same-origin frames when the page title or favicon is updated. +constexpr base::TimeDelta + kTimeToInhibitIntensiveThrottlingOnTitleOrFaviconUpdate = + base::TimeDelta::FromSeconds(3); + constexpr base::TimeDelta kDefaultDelayForTrackingIPCsPostedToCachedFrames = base::TimeDelta::FromSeconds(15); @@ -167,6 +170,7 @@ base::TimeDelta GetTimeToDelayIPCTrackingWhileStoredInBackForwardCache() { } // namespace constexpr base::TimeDelta PageSchedulerImpl::kDefaultThrottledWakeUpInterval; +constexpr base::TimeDelta PageSchedulerImpl::kIntensiveThrottledWakeUpInterval; PageSchedulerImpl::PageSchedulerImpl( PageScheduler::Delegate* delegate, @@ -179,7 +183,6 @@ PageSchedulerImpl::PageSchedulerImpl( main_thread_scheduler_->GetTickClock()->NowTicks()), audio_state_(AudioState::kSilent), is_frozen_(false), - reported_background_throttling_since_navigation_(false), opted_out_from_aggressive_throttling_(false), nested_runloop_(false), is_main_frame_local_(false), @@ -187,13 +190,16 @@ PageSchedulerImpl::PageSchedulerImpl( are_wake_ups_intensively_throttled_(false), keep_active_(main_thread_scheduler_->SchedulerKeepActive()), had_recent_title_or_favicon_update_(false), - focused_(delegate ? delegate->IsFocused() : true), delegate_(delegate), delay_for_background_tab_freezing_(GetDelayForBackgroundTabFreezing()), freeze_on_network_idle_enabled_(base::FeatureList::IsEnabled( blink::features::kFreezeBackgroundTabOnNetworkIdle)), delay_for_background_and_network_idle_tab_freezing_( - GetDelayForBackgroundAndNetworkIdleTabFreezing()) { + GetDelayForBackgroundAndNetworkIdleTabFreezing()), + throttle_foreground_timers_( + base::FeatureList::IsEnabled(kThrottleForegroundTimers)), + foreground_timers_throttled_wake_up_interval_( + GetForegroundTimersThrottledWakeUpInterval()) { page_lifecycle_state_tracker_ = std::make_unique<PageLifecycleStateTracker>( this, kDefaultPageVisibility == PageVisibilityState::kVisible ? PageLifecycleState::kActive @@ -219,15 +225,6 @@ PageSchedulerImpl::~PageSchedulerImpl() { frame_scheduler->DetachFromPageScheduler(); } main_thread_scheduler_->RemovePageScheduler(this); - - if (cpu_time_budget_pool_) - cpu_time_budget_pool_->Close(); - if (HasWakeUpBudgetPools()) { - for (WakeUpBudgetPool* pool : AllWakeUpBudgetPools()) { - DCHECK(pool); - pool->Close(); - } - } } // static @@ -271,6 +268,7 @@ void PageSchedulerImpl::SetPageVisible(bool page_visible) { for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_) frame_scheduler->SetPageVisibilityForTracing(page_visibility_); + MoveTaskQueuesToCorrectWakeUpBudgetPoolAndUpdate(); UpdatePolicyOnVisibilityChange(NotificationPolicy::kDoNotNotifyFrames); NotifyFrames(); @@ -366,13 +364,6 @@ void PageSchedulerImpl::SetPageBackForwardCached( } } -void PageSchedulerImpl::OnFocusChanged(bool focused) { - DCHECK_NE(focused_, focused); - - focused_ = focused; - NotifyFrames(); -} - void PageSchedulerImpl::SetUpIPCTaskDetection() { DCHECK(is_stored_in_back_forward_cache_); has_ipc_detection_enabled_ = true; @@ -432,7 +423,6 @@ void PageSchedulerImpl::RegisterFrameSchedulerImpl( MaybeInitializeBackgroundCPUTimeBudgetPool(&lazy_now); frame_schedulers_.insert(frame_scheduler); - main_thread_scheduler_->OnFrameAdded(*frame_scheduler); frame_scheduler->UpdatePolicy(); } @@ -449,11 +439,6 @@ std::unique_ptr<blink::FrameScheduler> PageSchedulerImpl::CreateFrameScheduler( void PageSchedulerImpl::Unregister(FrameSchedulerImpl* frame_scheduler) { DCHECK(frame_schedulers_.find(frame_scheduler) != frame_schedulers_.end()); frame_schedulers_.erase(frame_scheduler); - main_thread_scheduler_->OnFrameRemoved(*frame_scheduler); -} - -void PageSchedulerImpl::OnNavigation() { - reported_background_throttling_since_navigation_ = false; } void PageSchedulerImpl::ReportIntervention(const String& message) { @@ -476,10 +461,6 @@ void PageSchedulerImpl::SetInitialVirtualTime(base::Time time) { main_thread_scheduler_->SetInitialVirtualTime(time); } -void PageSchedulerImpl::SetInitialVirtualTimeOffset(base::TimeDelta offset) { - main_thread_scheduler_->SetInitialVirtualTimeOffset(offset); -} - bool PageSchedulerImpl::VirtualTimeAllowedToAdvance() const { return main_thread_scheduler_->VirtualTimeAllowedToAdvance(); } @@ -507,6 +488,7 @@ void PageSchedulerImpl::AudioStateChanged(bool is_audio_playing) { SetPageFrozenImpl(false, NotificationPolicy::kDoNotNotifyFrames); NotifyFrames(); main_thread_scheduler_->OnAudioStateChanged(); + MoveTaskQueuesToCorrectWakeUpBudgetPoolAndUpdate(); } else { if (audio_state_ != AudioState::kAudible) return; @@ -529,6 +511,7 @@ void PageSchedulerImpl::OnAudioSilent() { if (IsBackgrounded()) { page_lifecycle_state_tracker_->SetPageLifecycleState( PageLifecycleState::kHiddenBackgrounded); + MoveTaskQueuesToCorrectWakeUpBudgetPoolAndUpdate(); } if (ShouldFreezePage()) { main_thread_scheduler_->ControlTaskRunner()->PostDelayedTask( @@ -599,8 +582,14 @@ void PageSchedulerImpl::OnTraceLogEnabled() { } } -bool PageSchedulerImpl::IsPageFocused() const { - return focused_; +void PageSchedulerImpl::OnFirstContentfulPaintInMainFrame() { + // Now we get the FCP notification here only for the main frame, notify all + // frames within the page to recompute priority for JS timer tasks. + if (base::FeatureList::IsEnabled(kDeprioritizeDOMTimersDuringPageLoading) && + kDeprioritizeDOMTimersPhase.Get() == + DeprioritizeDOMTimersPhase::kFirstContentfulPaint) { + NotifyFrames(); + } } bool PageSchedulerImpl::IsWaitingForMainFrameContentfulPaint() const { @@ -621,54 +610,84 @@ bool PageSchedulerImpl::IsWaitingForMainFrameMeaningfulPaint() const { }); } -void PageSchedulerImpl::WriteIntoTrace(perfetto::TracedValue context) const { +void PageSchedulerImpl::WriteIntoTrace(perfetto::TracedValue context, + base::TimeTicks now) const { auto dict = std::move(context).WriteDictionary(); dict.Add("page_visible", page_visibility_ == PageVisibilityState::kVisible); dict.Add("is_audio_playing", IsAudioPlaying()); dict.Add("is_frozen", is_frozen_); - dict.Add("reported_background_throttling_since_navigation", - reported_background_throttling_since_navigation_); dict.Add("is_page_freezable", IsBackgrounded()); + dict.Add("cpu_time_budget_pool", [&](perfetto::TracedValue context) { + cpu_time_budget_pool_->WriteIntoTrace(std::move(context), now); + }); + dict.Add("normal_wake_up_budget_pool", [&](perfetto::TracedValue context) { + normal_wake_up_budget_pool_->WriteIntoTrace(std::move(context), now); + }); + dict.Add("same_origin_intensive_wake_up_budget_pool", + [&](perfetto::TracedValue context) { + same_origin_intensive_wake_up_budget_pool_->WriteIntoTrace( + std::move(context), now); + }); + dict.Add("cross_origin_intensive_wake_up_budget_pool", + [&](perfetto::TracedValue context) { + cross_origin_intensive_wake_up_budget_pool_->WriteIntoTrace( + std::move(context), now); + }); + dict.Add("frame_schedulers", frame_schedulers_); } void PageSchedulerImpl::AddQueueToWakeUpBudgetPool( MainThreadTaskQueue* task_queue, FrameOriginType frame_origin_type, + bool frame_visible, base::sequence_manager::LazyNow* lazy_now) { - task_queue->AddToBudgetPool( - lazy_now->Now(), GetWakeUpBudgetPool(task_queue, frame_origin_type)); + DCHECK(!task_queue->GetWakeUpBudgetPool()); + WakeUpBudgetPool* wake_up_budget_pool = + GetWakeUpBudgetPool(task_queue, frame_origin_type, frame_visible); + task_queue->AddToBudgetPool(lazy_now->Now(), wake_up_budget_pool); + task_queue->SetWakeUpBudgetPool(wake_up_budget_pool); } void PageSchedulerImpl::RemoveQueueFromWakeUpBudgetPool( MainThreadTaskQueue* task_queue, - FrameOriginType frame_origin_type, base::sequence_manager::LazyNow* lazy_now) { - task_queue->RemoveFromBudgetPool( - lazy_now->Now(), GetWakeUpBudgetPool(task_queue, frame_origin_type)); + if (!task_queue->GetWakeUpBudgetPool()) + return; + task_queue->RemoveFromBudgetPool(lazy_now->Now(), + task_queue->GetWakeUpBudgetPool()); + task_queue->SetWakeUpBudgetPool(nullptr); } WakeUpBudgetPool* PageSchedulerImpl::GetWakeUpBudgetPool( MainThreadTaskQueue* task_queue, - FrameOriginType frame_origin_type) { - if (!task_queue->CanBeIntensivelyThrottled()) - return normal_wake_up_budget_pool_; - - switch (frame_origin_type) { - case FrameOriginType::kMainFrame: - case FrameOriginType::kSameOriginToMainFrame: - return same_origin_intensive_wake_up_budget_pool_; - case FrameOriginType::kCrossOriginToMainFrame: - return cross_origin_intensive_wake_up_budget_pool_; - case FrameOriginType::kCount: - NOTREACHED(); - return nullptr; + FrameOriginType frame_origin_type, + bool frame_visible) { + const bool can_be_intensively_throttled = + task_queue->CanBeIntensivelyThrottled(); + const bool is_same_origin = + frame_origin_type == FrameOriginType::kMainFrame || + frame_origin_type == FrameOriginType::kSameOriginToMainFrame; + + if (IsBackgrounded()) { + if (can_be_intensively_throttled) { + if (is_same_origin) + return same_origin_intensive_wake_up_budget_pool_.get(); + else + return cross_origin_intensive_wake_up_budget_pool_.get(); + } + return normal_wake_up_budget_pool_.get(); } + + if (!is_same_origin && !frame_visible) + return cross_origin_hidden_normal_wake_up_budget_pool_.get(); + + return normal_wake_up_budget_pool_.get(); } CPUTimeBudgetPool* PageSchedulerImpl::background_cpu_time_budget_pool() { - return cpu_time_budget_pool_; + return cpu_time_budget_pool_.get(); } void PageSchedulerImpl::MaybeInitializeBackgroundCPUTimeBudgetPool( @@ -676,12 +695,8 @@ void PageSchedulerImpl::MaybeInitializeBackgroundCPUTimeBudgetPool( if (cpu_time_budget_pool_) return; - if (!RuntimeEnabledFeatures::ExpensiveBackgroundTimerThrottlingEnabled()) - return; - - cpu_time_budget_pool_ = - main_thread_scheduler_->task_queue_throttler()->CreateCPUTimeBudgetPool( - "background"); + cpu_time_budget_pool_ = std::make_unique<CPUTimeBudgetPool>( + "background", &tracing_controller_, lazy_now->Now()); BackgroundThrottlingSettings settings = GetBackgroundThrottlingSettings(); @@ -707,13 +722,16 @@ void PageSchedulerImpl::MaybeInitializeWakeUpBudgetPools( return; normal_wake_up_budget_pool_ = - main_thread_scheduler_->task_queue_throttler()->CreateWakeUpBudgetPool( - "Page - Normal Wake Up Throttling"); + std::make_unique<WakeUpBudgetPool>("Page - Normal Wake Up Throttling"); + cross_origin_hidden_normal_wake_up_budget_pool_ = + std::make_unique<WakeUpBudgetPool>( + "Page - Normal Wake Up Throttling - Hidden & Crosss-Origin to Main " + "Frame"); same_origin_intensive_wake_up_budget_pool_ = - main_thread_scheduler_->task_queue_throttler()->CreateWakeUpBudgetPool( + std::make_unique<WakeUpBudgetPool>( "Page - Intensive Wake Up Throttling - Same-Origin as Main Frame"); cross_origin_intensive_wake_up_budget_pool_ = - main_thread_scheduler_->task_queue_throttler()->CreateWakeUpBudgetPool( + std::make_unique<WakeUpBudgetPool>( "Page - Intensive Wake Up Throttling - Cross-Origin to Main Frame"); // The Wake Up Duration and Unaligned Wake Ups Allowance are constant and set @@ -722,34 +740,12 @@ void PageSchedulerImpl::MaybeInitializeWakeUpBudgetPools( for (WakeUpBudgetPool* pool : AllWakeUpBudgetPools()) pool->SetWakeUpDuration(kThrottledWakeUpDuration); - if (IsIntensiveWakeUpThrottlingEnabled()) { - same_origin_intensive_wake_up_budget_pool_ - ->AllowUnalignedWakeUpIfNoRecentWakeUp(); - } + same_origin_intensive_wake_up_budget_pool_ + ->AllowLowerAlignmentIfNoRecentWakeUp(kDefaultThrottledWakeUpInterval); UpdateWakeUpBudgetPools(lazy_now); } -void PageSchedulerImpl::OnThrottlingReported( - base::TimeDelta throttling_duration) { - if (throttling_duration < kMinimalBackgroundThrottlingDurationToReport) - return; - - if (reported_background_throttling_since_navigation_) - return; - reported_background_throttling_since_navigation_ = true; - - String message = String::Format( - "Timer tasks have taken too much time while the page was in the " - "background. " - "As a result, they have been deferred for %.3f seconds. " - "See https://www.chromestatus.com/feature/6172836527865856 " - "for more details", - throttling_duration.InSecondsF()); - - delegate_->ReportIntervention(message); -} - void PageSchedulerImpl::UpdatePolicyOnVisibilityChange( NotificationPolicy notification_policy) { base::sequence_manager::LazyNow lazy_now( @@ -762,18 +758,15 @@ void PageSchedulerImpl::UpdatePolicyOnVisibilityChange( are_wake_ups_intensively_throttled_ = false; do_intensively_throttle_wake_ups_callback_.Cancel(); - UpdateWakeUpBudgetPools(&lazy_now); } else { if (cpu_time_budget_pool_) { main_thread_scheduler_->ControlTaskRunner()->PostDelayedTask( FROM_HERE, do_throttle_cpu_time_callback_.GetCallback(), kThrottlingDelayAfterBackgrounding); } - if (IsIntensiveWakeUpThrottlingEnabled()) { - main_thread_scheduler_->ControlTaskRunner()->PostDelayedTask( - FROM_HERE, do_intensively_throttle_wake_ups_callback_.GetCallback(), - GetIntensiveWakeUpThrottlingGracePeriod()); - } + main_thread_scheduler_->ControlTaskRunner()->PostDelayedTask( + FROM_HERE, do_intensively_throttle_wake_ups_callback_.GetCallback(), + GetIntensiveWakeUpThrottlingGracePeriod()); } if (notification_policy == NotificationPolicy::kNotifyFrames) NotifyFrames(); @@ -790,8 +783,6 @@ void PageSchedulerImpl::DoThrottleCPUTime() { } void PageSchedulerImpl::DoIntensivelyThrottleWakeUps() { - DCHECK(IsIntensiveWakeUpThrottlingEnabled()); - do_intensively_throttle_wake_ups_callback_.Cancel(); are_wake_ups_intensively_throttled_ = true; @@ -816,31 +807,21 @@ void PageSchedulerImpl::UpdateCPUTimeBudgetPool( void PageSchedulerImpl::OnTitleOrFaviconUpdated() { if (!HasWakeUpBudgetPools()) return; - if (are_wake_ups_intensively_throttled_ && !opted_out_from_aggressive_throttling_) { // When the title of favicon is updated, intensive throttling is inhibited // for same-origin frames. This enables alternating effects meant to grab // the user's attention. Cross-origin frames are not affected, since they // shouldn't be able to observe that the page title or favicon was updated. - base::TimeDelta time_to_inhibit_intensive_throttling = - GetTimeToInhibitIntensiveThrottlingOnTitleOrFaviconUpdate(); - - if (time_to_inhibit_intensive_throttling.is_zero()) { - // No inhibiting to be done. - return; - } - had_recent_title_or_favicon_update_ = true; base::sequence_manager::LazyNow lazy_now( main_thread_scheduler_->tick_clock()); UpdateWakeUpBudgetPools(&lazy_now); - // Re-enable intensive throttling from a delayed task. reset_had_recent_title_or_favicon_update_.Cancel(); main_thread_scheduler_->ControlTaskRunner()->PostDelayedTask( FROM_HERE, reset_had_recent_title_or_favicon_update_.GetCallback(), - time_to_inhibit_intensive_throttling); + kTimeToInhibitIntensiveThrottlingOnTitleOrFaviconUpdate); } } @@ -854,15 +835,15 @@ void PageSchedulerImpl::ResetHadRecentTitleOrFaviconUpdate() { NotifyFrames(); } -base::TimeDelta PageSchedulerImpl::GetIntensiveWakeUpThrottlingDuration( - bool is_same_origin) { +base::TimeDelta PageSchedulerImpl::GetIntensiveWakeUpThrottlingInterval( + bool is_same_origin) const { // Title and favicon changes only affect the same_origin wake up budget pool. if (is_same_origin && had_recent_title_or_favicon_update_) return kDefaultThrottledWakeUpInterval; if (are_wake_ups_intensively_throttled_ && !opted_out_from_aggressive_throttling_) - return GetIntensiveWakeUpThrottlingDurationBetweenWakeUps(); + return kIntensiveThrottledWakeUpInterval; else return kDefaultThrottledWakeUpInterval; } @@ -872,10 +853,16 @@ void PageSchedulerImpl::UpdateWakeUpBudgetPools( if (!same_origin_intensive_wake_up_budget_pool_) return; + normal_wake_up_budget_pool_->SetWakeUpInterval( + lazy_now->Now(), IsBackgrounded() + ? kDefaultThrottledWakeUpInterval + : foreground_timers_throttled_wake_up_interval_); + cross_origin_hidden_normal_wake_up_budget_pool_->SetWakeUpInterval( + lazy_now->Now(), kDefaultThrottledWakeUpInterval); same_origin_intensive_wake_up_budget_pool_->SetWakeUpInterval( - lazy_now->Now(), GetIntensiveWakeUpThrottlingDuration(true)); + lazy_now->Now(), GetIntensiveWakeUpThrottlingInterval(true)); cross_origin_intensive_wake_up_budget_pool_->SetWakeUpInterval( - lazy_now->Now(), GetIntensiveWakeUpThrottlingDuration(false)); + lazy_now->Now(), GetIntensiveWakeUpThrottlingInterval(false)); } void PageSchedulerImpl::NotifyFrames() { @@ -1064,6 +1051,8 @@ WebScopedVirtualTimePauser PageSchedulerImpl::CreateWebScopedVirtualTimePauser( bool PageSchedulerImpl::HasWakeUpBudgetPools() const { // All WakeUpBudgetPools should be initialized together. DCHECK_EQ(!!normal_wake_up_budget_pool_, + !!cross_origin_hidden_normal_wake_up_budget_pool_); + 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_); @@ -1071,11 +1060,23 @@ bool PageSchedulerImpl::HasWakeUpBudgetPools() const { return !!normal_wake_up_budget_pool_; } +void PageSchedulerImpl::MoveTaskQueuesToCorrectWakeUpBudgetPoolAndUpdate() { + for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_) + frame_scheduler->MoveTaskQueuesToCorrectWakeUpBudgetPool(); + + // Update the WakeUpBudgetPools' interval everytime task queues change their + // attached WakeUpBudgetPools + base::sequence_manager::LazyNow lazy_now( + main_thread_scheduler_->tick_clock()); + UpdateWakeUpBudgetPools(&lazy_now); +} + 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_}; + return {normal_wake_up_budget_pool_.get(), + cross_origin_hidden_normal_wake_up_budget_pool_.get(), + same_origin_intensive_wake_up_budget_pool_.get(), + cross_origin_intensive_wake_up_budget_pool_.get()}; } // static diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h index 24b41b7ccae..4cd26620811 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h @@ -7,13 +7,12 @@ #include <memory> -#include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "base/observer_list.h" #include "base/task/sequence_manager/task_queue.h" #include "base/time/time.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/renderer/platform/platform_export.h" +#include "third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.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/agent_group_scheduler_impl.h" @@ -50,11 +49,17 @@ class WakeUpBudgetPool; class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler { public: - // Interval between throttled wake ups, when intensive throttling is disabled. + // Interval between throttled wake ups, without intensive throttling. static constexpr base::TimeDelta kDefaultThrottledWakeUpInterval = base::TimeDelta::FromSeconds(1); + // Interval between throttled wake ups, with intensive throttling. + static constexpr base::TimeDelta kIntensiveThrottledWakeUpInterval = + base::TimeDelta::FromMinutes(1); + PageSchedulerImpl(PageScheduler::Delegate*, AgentGroupSchedulerImpl&); + PageSchedulerImpl(const PageSchedulerImpl&) = delete; + PageSchedulerImpl& operator=(const PageSchedulerImpl&) = delete; ~PageSchedulerImpl() override; @@ -63,7 +68,6 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler { void SetPageVisible(bool page_visible) override; void SetPageFrozen(bool) override; void SetPageBackForwardCached(bool) override; - void OnFocusChanged(bool focused) override; void SetKeepActive(bool) override; bool IsMainFrameLocal() const override; void SetIsMainFrameLocal(bool is_local) override; @@ -85,7 +89,6 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler { bool VirtualTimeAllowedToAdvance() const override; void SetVirtualTimePolicy(VirtualTimePolicy) override; void SetInitialVirtualTime(base::Time time) override; - void SetInitialVirtualTimeOffset(base::TimeDelta offset) override; void GrantVirtualTimeBudget( base::TimeDelta budget, base::OnceClosure budget_exhausted_callback) override; @@ -121,13 +124,12 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler { AgentGroupSchedulerImpl& GetAgentGroupScheduler() override; void Unregister(FrameSchedulerImpl*); - void OnNavigation(); void OnThrottlingStatusUpdated(); void OnTraceLogEnabled(); - bool IsPageFocused() const; + void OnFirstContentfulPaintInMainFrame(); // Virtual for testing. virtual bool IsWaitingForMainFrameContentfulPaint() const; @@ -151,7 +153,9 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler { // frame it not a local one. FrameSchedulerImpl* SelectFrameForUkmAttribution(); - void WriteIntoTrace(perfetto::TracedValue context) const; + bool ThrottleForegroundTimers() const { return throttle_foreground_timers_; } + + void WriteIntoTrace(perfetto::TracedValue context, base::TimeTicks now) const; base::WeakPtr<PageSchedulerImpl> GetWeakPtr() { return weak_factory_.GetWeakPtr(); @@ -196,6 +200,9 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler { public: explicit PageLifecycleStateTracker(PageSchedulerImpl*, PageLifecycleState); + PageLifecycleStateTracker(const PageLifecycleStateTracker&) = delete; + PageLifecycleStateTracker& operator=(const PageLifecycleStateTracker&) = + delete; ~PageLifecycleStateTracker() = default; void SetPageLifecycleState(PageLifecycleState); @@ -211,8 +218,6 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler { PageSchedulerImpl* page_scheduler_impl_; PageLifecycleState current_state_; - - DISALLOW_COPY_AND_ASSIGN(PageLifecycleStateTracker); }; void RegisterFrameSchedulerImpl(FrameSchedulerImpl* frame_scheduler); @@ -232,22 +237,22 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler { // a part of foregrounding the page. void SetPageFrozenImpl(bool frozen, NotificationPolicy notification_policy); - // 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. + // Adds or removes a |task_queue| from the WakeUpBudgetPool. When the + // FrameOriginType or visibility of a FrameScheduler changes, it should remove + // all its TaskQueues from their current WakeUpBudgetPool and add them back to + // the appropriate WakeUpBudgetPool. void AddQueueToWakeUpBudgetPool(MainThreadTaskQueue* task_queue, FrameOriginType frame_origin_type, + bool frame_visible, 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 |task_queue| which belongs to a - // frame with |frame_origin_type|. + // frame with |frame_origin_type| and visibility |frame_visible|. WakeUpBudgetPool* GetWakeUpBudgetPool(MainThreadTaskQueue* task_queue, - FrameOriginType frame_origin_type); + FrameOriginType frame_origin_type, + bool frame_visible); // Initializes WakeUpBudgetPools, if not already initialized. void MaybeInitializeWakeUpBudgetPools( base::sequence_manager::LazyNow* lazy_now); @@ -256,8 +261,6 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler { void MaybeInitializeBackgroundCPUTimeBudgetPool( base::sequence_manager::LazyNow* lazy_now); - void OnThrottlingReported(base::TimeDelta throttling_duration); - // Depending on page visibility, either turns throttling off, or schedules a // call to enable it after a grace period. void UpdatePolicyOnVisibilityChange(NotificationPolicy notification_policy); @@ -265,7 +268,8 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler { // Adjusts settings of budget pools depending on current state of the page. void UpdateCPUTimeBudgetPool(base::sequence_manager::LazyNow* lazy_now); void UpdateWakeUpBudgetPools(base::sequence_manager::LazyNow* lazy_now); - base::TimeDelta GetIntensiveWakeUpThrottlingDuration(bool is_same_origin); + base::TimeDelta GetIntensiveWakeUpThrottlingInterval( + bool is_same_origin) const; // Callback for marking page is silent after a delay since last audible // signal. @@ -298,8 +302,12 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler { // Returns true if WakeUpBudgetPools were initialized. bool HasWakeUpBudgetPools() const; + // Notify frames to move their task queues to the appropriate + // WakeUpBudgetPool. + void MoveTaskQueuesToCorrectWakeUpBudgetPoolAndUpdate(); + // Returns all WakeUpBudgetPools owned by this PageSchedulerImpl. - static constexpr int kNumWakeUpBudgetPools = 3; + static constexpr int kNumWakeUpBudgetPools = 4; std::array<WakeUpBudgetPool*, kNumWakeUpBudgetPools> AllWakeUpBudgetPools(); TraceableVariableController tracing_controller_; @@ -311,7 +319,6 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler { base::TimeTicks page_visibility_changed_time_; AudioState audio_state_; bool is_frozen_; - bool reported_background_throttling_since_navigation_; bool opted_out_from_aggressive_throttling_; bool nested_runloop_; bool is_main_frame_local_; @@ -319,22 +326,38 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler { bool are_wake_ups_intensively_throttled_; bool keep_active_; bool had_recent_title_or_favicon_update_; - bool focused_; - CPUTimeBudgetPool* cpu_time_budget_pool_ = nullptr; + std::unique_ptr<CPUTimeBudgetPool> cpu_time_budget_pool_; // Wake up budget pools for each throttling scenario: // - // Same-origin frame Cross-origin frame - // Normal throttling only 1 1 - // Normal and intensive throttling 2 3 + // For background pages: + // Same-origin frame Cross-origin frame + // Normal throttling only 1 1 + // Normal and intensive throttling 3 4 + // + // For foreground pages: + // Same-origin frame 1 + // Visible cross-origin frame 1 + // Hidden cross-origin frame 2 // - // 1: This pool allows 1-second aligned wake ups. - WakeUpBudgetPool* normal_wake_up_budget_pool_ = nullptr; - // 2: This pool allows 1-second aligned wake ups if the page is not + // Task queues attched to these pools will be updated when: + // * Page background state changes + // * Frame visibility changes + // * Frame origin changes + // + // 1: This pool allows 1-second aligned wake ups when the page is backgrounded + // or |foreground_timers_throttled_wake_up_interval_| aligned wake ups when + // the page is foregrounded. + std::unique_ptr<WakeUpBudgetPool> normal_wake_up_budget_pool_; + // 2: This pool allows 1-second aligned wake ups for hidden frames in + // foreground pages. + std::unique_ptr<WakeUpBudgetPool> + cross_origin_hidden_normal_wake_up_budget_pool_; + // 3: This pool allows 1-second aligned wake ups if the page is not // intensively throttled of if there hasn't been a wake up in the last // 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 + std::unique_ptr<WakeUpBudgetPool> same_origin_intensive_wake_up_budget_pool_; + // 4: 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 @@ -343,7 +366,7 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler { // 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; + std::unique_ptr<WakeUpBudgetPool> cross_origin_intensive_wake_up_budget_pool_; PageScheduler::Delegate* delegate_; CancelableClosureHolder do_throttle_cpu_time_callback_; @@ -360,14 +383,17 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler { // Delay after which a background page can be frozen if network is idle. const base::TimeDelta delay_for_background_and_network_idle_tab_freezing_; + // Whether foreground timers should be always throttled. + const bool throttle_foreground_timers_; + // Interval between throttled wake ups on a foreground page. + const base::TimeDelta foreground_timers_throttled_wake_up_interval_; + bool is_stored_in_back_forward_cache_ = false; TaskHandle set_ipc_posted_handler_task_; base::TimeTicks stored_in_back_forward_cache_timestamp_; std::unique_ptr<PageLifecycleStateTracker> page_lifecycle_state_tracker_; base::WeakPtrFactory<PageSchedulerImpl> weak_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(PageSchedulerImpl); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc index 03f4d864a40..e7252d20c92 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc @@ -21,7 +21,6 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/features.h" -#include "third_party/blink/renderer/platform/scheduler/common/features.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h" @@ -83,7 +82,6 @@ class MockPageSchedulerDelegate : public PageScheduler::Delegate { void SetLocalMainFrameNetworkIsAlmostIdle(bool idle) { idle_ = idle; } bool LocalMainFrameNetworkIsAlmostIdle() const override { return idle_; } - bool IsFocused() const override { return true; } private: void ReportIntervention(const WTF::String&) override {} @@ -1130,13 +1128,11 @@ void InitializeTrialParams() { } // namespace TEST_F(PageSchedulerImplTest, BackgroundTimerThrottling) { - ScopedExpensiveBackgroundTimerThrottlingForTest - budget_background_throttling_enabler(true); - InitializeTrialParams(); page_scheduler_ = CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_); EXPECT_FALSE(page_scheduler_->IsCPUTimeThrottled()); + base::TimeTicks start_time = test_task_runner_->NowTicks(); Vector<base::TimeTicks> run_times; frame_scheduler_ = @@ -1185,21 +1181,18 @@ TEST_F(PageSchedulerImplTest, BackgroundTimerThrottling) { test_task_runner_->FastForwardUntilNoTasksRemain(); // Check that tasks are aligned and throttled. - EXPECT_THAT( - run_times, - ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(16), - base::TimeTicks() + base::TimeDelta::FromSeconds(26))); + EXPECT_THAT(run_times, + ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(16), + start_time + base::TimeDelta::FromSeconds(25))); base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting(); } TEST_F(PageSchedulerImplTest, OpenWebSocketExemptsFromBudgetThrottling) { - ScopedExpensiveBackgroundTimerThrottlingForTest - budget_background_throttling_enabler(true); - InitializeTrialParams(); std::unique_ptr<PageSchedulerImpl> page_scheduler = CreatePageScheduler(nullptr, scheduler_.get(), *agent_group_scheduler_); + base::TimeTicks start_time = test_task_runner_->NowTicks(); Vector<base::TimeTicks> run_times; @@ -1227,11 +1220,10 @@ TEST_F(PageSchedulerImplTest, OpenWebSocketExemptsFromBudgetThrottling) { FastForwardTo(base::TimeTicks() + base::TimeDelta::FromMilliseconds(55500)); // Check that tasks are throttled. - EXPECT_THAT( - run_times, - ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(21), - base::TimeTicks() + base::TimeDelta::FromSeconds(26), - base::TimeTicks() + base::TimeDelta::FromSeconds(51))); + EXPECT_THAT(run_times, + ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(21), + start_time + base::TimeDelta::FromSeconds(25), + start_time + base::TimeDelta::FromSeconds(50))); run_times.clear(); FrameScheduler::SchedulingAffectingFeatureHandle websocket_feature = @@ -1299,9 +1291,10 @@ TEST_F(PageSchedulerImplTest, OpenWebSocketExemptsFromBudgetThrottling) { // WebSocket is closed, budget-based throttling now applies. EXPECT_THAT( run_times, - ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(84), - base::TimeTicks() + base::TimeDelta::FromSeconds(109), - base::TimeTicks() + base::TimeDelta::FromSeconds(134))); + ElementsAre( + base::TimeTicks() + base::TimeDelta::FromMilliseconds(84500), + base::TimeTicks() + base::TimeDelta::FromMilliseconds(109500), + base::TimeTicks() + base::TimeDelta::FromMilliseconds(134500))); base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting(); } @@ -1747,88 +1740,6 @@ TEST_F(PageSchedulerImplPageTransitionTest, UnorderedElementsAreArray(GetExpectedBuckets())); } -class PageSchedulerImplThrottleVisibleNotFocusedTimersEnabledTest - : public PageSchedulerImplTest { - public: - PageSchedulerImplThrottleVisibleNotFocusedTimersEnabledTest() - : PageSchedulerImplTest( - {blink::features::kStopInBackground, - blink::scheduler::kThrottleVisibleNotFocusedTimers}, - {}) {} -}; - -TEST_F(PageSchedulerImplThrottleVisibleNotFocusedTimersEnabledTest, - PageVisibleWithFocus) { - page_scheduler_->SetPageVisible(true); - if (!page_scheduler_->IsPageFocused()) - page_scheduler_->OnFocusChanged(true); - - int run_count = 0; - ThrottleableTaskQueue()->GetTaskRunnerWithDefaultTaskType()->PostDelayedTask( - FROM_HERE, - MakeRepeatingTask( - ThrottleableTaskQueue()->GetTaskRunnerWithDefaultTaskType(), - &run_count, base::TimeDelta::FromMilliseconds(20)), - base::TimeDelta::FromMilliseconds(20)); - - test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1)); - EXPECT_EQ(50, run_count); - - // Create a new frame when the page has focus - int frame_run_count = 0; - std::unique_ptr<FrameSchedulerImpl> frame_scheduler2 = - CreateFrameScheduler(page_scheduler_.get(), nullptr, nullptr, - FrameScheduler::FrameType::kSubframe); - ThrottleableTaskQueueForScheduler(frame_scheduler2.get()) - ->GetTaskRunnerWithDefaultTaskType() - ->PostDelayedTask( - FROM_HERE, - MakeRepeatingTask( - ThrottleableTaskQueueForScheduler(frame_scheduler2.get()) - ->GetTaskRunnerWithDefaultTaskType(), - &frame_run_count, base::TimeDelta::FromMilliseconds(20)), - base::TimeDelta::FromMilliseconds(20)); - - test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1)); - EXPECT_EQ(50, frame_run_count); -} - -TEST_F(PageSchedulerImplThrottleVisibleNotFocusedTimersEnabledTest, - PageVisibleWithoutFocus) { - page_scheduler_->SetPageVisible(true); - if (page_scheduler_->IsPageFocused()) - page_scheduler_->OnFocusChanged(false); - - int run_count = 0; - ThrottleableTaskQueue()->GetTaskRunnerWithDefaultTaskType()->PostDelayedTask( - FROM_HERE, - MakeRepeatingTask( - ThrottleableTaskQueue()->GetTaskRunnerWithDefaultTaskType(), - &run_count, base::TimeDelta::FromMilliseconds(20)), - base::TimeDelta::FromMilliseconds(20)); - - test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1)); - EXPECT_EQ(1, run_count); - - // Create a new frame when the page doesn't have focus - int frame_run_count = 0; - std::unique_ptr<FrameSchedulerImpl> frame_scheduler2 = - CreateFrameScheduler(page_scheduler_.get(), nullptr, nullptr, - FrameScheduler::FrameType::kSubframe); - ThrottleableTaskQueueForScheduler(frame_scheduler2.get()) - ->GetTaskRunnerWithDefaultTaskType() - ->PostDelayedTask( - FROM_HERE, - MakeRepeatingTask( - ThrottleableTaskQueueForScheduler(frame_scheduler2.get()) - ->GetTaskRunnerWithDefaultTaskType(), - &frame_run_count, base::TimeDelta::FromMilliseconds(20)), - base::TimeDelta::FromMilliseconds(20)); - - test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1)); - EXPECT_EQ(1, frame_run_count); -} - } // namespace page_scheduler_impl_unittest } // namespace scheduler } // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h index 4c4863cb99f..84b1675979a 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h @@ -26,6 +26,8 @@ class PLATFORM_EXPORT PendingUserInput { public: Monitor() = default; + Monitor(const Monitor&) = delete; + Monitor& operator=(const Monitor&) = delete; void OnEnqueue(WebInputEvent::Type, const WebInputEventAttribution&); void OnDequeue(WebInputEvent::Type, const WebInputEventAttribution&); @@ -45,18 +47,16 @@ class PLATFORM_EXPORT PendingUserInput { // A mapping between attributions to pending events. HashMap<AttributionGroup, EventCounter> pending_events_; - - DISALLOW_COPY_AND_ASSIGN(Monitor); }; PendingUserInput() = delete; + PendingUserInput(const PendingUserInput&) = delete; + PendingUserInput& operator=(const PendingUserInput&) = delete; // Returns true if the given blink event type is considered to be sampled // from a continuous source. // https://wicg.github.io/is-input-pending/#continuousevents static bool IsContinuousEventType(WebInputEvent::Type); - - DISALLOW_COPY_AND_ASSIGN(PendingUserInput); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/render_widget_signals_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/render_widget_signals_unittest.cc index f08de3f8c10..7c32074ba6f 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/render_widget_signals_unittest.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/render_widget_signals_unittest.cc @@ -6,7 +6,6 @@ #include <memory> -#include "base/macros.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/scheduler/web_render_widget_scheduling_state.h" @@ -23,14 +22,13 @@ namespace render_widget_signals_unittest { class MockObserver : public RenderWidgetSignals::Observer { public: MockObserver() = default; + MockObserver(const MockObserver&) = delete; + MockObserver& operator=(const MockObserver&) = delete; ~MockObserver() override = default; MOCK_METHOD1(SetAllRenderWidgetsHidden, void(bool hidden)); MOCK_METHOD1(SetHasVisibleRenderWidgetWithTouchHandler, void(bool has_visible_render_widget_with_touch_handler)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockObserver); }; class RenderWidgetSignalsTest : public testing::Test { diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/resource_loading_task_runner_handle_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/resource_loading_task_runner_handle_impl.h index bc24b079541..a270655fc64 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/resource_loading_task_runner_handle_impl.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/resource_loading_task_runner_handle_impl.h @@ -23,6 +23,11 @@ class PLATFORM_EXPORT ResourceLoadingTaskRunnerHandleImpl static std::unique_ptr<ResourceLoadingTaskRunnerHandleImpl> WrapTaskRunner( scoped_refptr<MainThreadTaskQueue> task_runner); + ResourceLoadingTaskRunnerHandleImpl( + const ResourceLoadingTaskRunnerHandleImpl&) = delete; + ResourceLoadingTaskRunnerHandleImpl& operator=( + const ResourceLoadingTaskRunnerHandleImpl&) = delete; + scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() const override; void DidChangeRequestPriority(net::RequestPriority priority) override; @@ -38,8 +43,6 @@ class PLATFORM_EXPORT ResourceLoadingTaskRunnerHandleImpl private: scoped_refptr<MainThreadTaskQueue> task_queue_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - - DISALLOW_COPY_AND_ASSIGN(ResourceLoadingTaskRunnerHandleImpl); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc index b0565ab37ae..f25ef8ff04b 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc @@ -151,8 +151,8 @@ const char* TaskTypeNames::TaskTypeToString(TaskType task_type) { return "WakeLock"; case TaskType::kWebGPU: return "WebGPU"; - case TaskType::kCount: - return "Count"; + case TaskType::kInternalPostMessageForwarding: + return "InternalPostMessageForwarding"; } // FrameSchedulerImpl should not call this for invalid TaskTypes. NOTREACHED(); diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/user_model.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/user_model.h index 9e5667de0c0..a849d07df67 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/user_model.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/user_model.h @@ -5,7 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_USER_MODEL_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_USER_MODEL_H_ -#include "base/macros.h" #include "third_party/blink/public/common/input/web_input_event.h" #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" #include "third_party/blink/renderer/platform/platform_export.h" @@ -20,6 +19,8 @@ class PLATFORM_EXPORT UserModel { public: UserModel(); + UserModel(const UserModel&) = delete; + UserModel& operator=(const UserModel&) = delete; // Tells us that the system started processing an input event. Must be paired // with a call to DidFinishProcessingInputEvent. @@ -77,8 +78,6 @@ class PLATFORM_EXPORT UserModel { base::TimeTicks last_reset_time_; bool is_gesture_active_; // This typically means the user's finger is down. bool is_gesture_expected_; - - DISALLOW_COPY_AND_ASSIGN(UserModel); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_task_queue_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_task_queue_impl.cc deleted file mode 100644 index 30b6e4b4ea3..00000000000 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_task_queue_impl.cc +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2019 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 "third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_task_queue_impl.h" - -#include "third_party/blink/public/platform/task_type.h" -#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h" - -namespace blink { -namespace scheduler { - -WebSchedulingTaskQueueImpl::WebSchedulingTaskQueueImpl( - base::WeakPtr<MainThreadTaskQueue> task_queue) - : task_runner_( - task_queue->CreateTaskRunner(TaskType::kExperimentalWebScheduling)), - task_queue_(std::move(task_queue)) {} - -void WebSchedulingTaskQueueImpl::SetPriority(WebSchedulingPriority priority) { - if (task_queue_) - task_queue_->SetWebSchedulingPriority(priority); -} - -scoped_refptr<base::SingleThreadTaskRunner> -WebSchedulingTaskQueueImpl::GetTaskRunner() { - return task_runner_; -} - -} // namespace scheduler -} // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_task_queue_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_task_queue_impl.h deleted file mode 100644 index a4da9eaf1af..00000000000 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_task_queue_impl.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2019 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_WEB_SCHEDULING_TASK_QUEUE_IMPL_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_WEB_SCHEDULING_TASK_QUEUE_IMPL_H_ - -#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_task_queue.h" - -#include "base/memory/scoped_refptr.h" -#include "base/memory/weak_ptr.h" -#include "base/single_thread_task_runner.h" -#include "third_party/blink/renderer/platform/platform_export.h" -#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h" - -namespace blink { -namespace scheduler { - -class MainThreadTaskQueue; - -class PLATFORM_EXPORT WebSchedulingTaskQueueImpl - : public WebSchedulingTaskQueue { - public: - WebSchedulingTaskQueueImpl(base::WeakPtr<MainThreadTaskQueue>); - ~WebSchedulingTaskQueueImpl() override = default; - - void SetPriority(WebSchedulingPriority) override; - - scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override; - - private: - const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - base::WeakPtr<MainThreadTaskQueue> task_queue_; -}; - -} // namespace scheduler -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_WEB_SCHEDULING_TASK_QUEUE_IMPL_H_ diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/widget_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/widget_scheduler.h index 83a5fdecb26..c1a0e56c194 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/widget_scheduler.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/widget_scheduler.h @@ -19,6 +19,8 @@ class MainThreadTaskQueue; class WidgetScheduler : public WebWidgetScheduler { public: WidgetScheduler(MainThreadSchedulerImpl*); + WidgetScheduler(const WidgetScheduler&) = delete; + WidgetScheduler& operator=(const WidgetScheduler&) = delete; ~WidgetScheduler() override; scoped_refptr<base::SingleThreadTaskRunner> InputTaskRunner() override; @@ -27,8 +29,6 @@ class WidgetScheduler : public WebWidgetScheduler { scoped_refptr<base::SingleThreadTaskRunner> input_task_runner_; std::unique_ptr<base::sequence_manager::TaskQueue::QueueEnabledVoter> input_task_queue_enabled_voter_; - - DISALLOW_COPY_AND_ASSIGN(WidgetScheduler); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/aggregated_metric_reporter.h b/chromium/third_party/blink/renderer/platform/scheduler/public/aggregated_metric_reporter.h index ff9335fdf5e..18c32d68bbf 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/public/aggregated_metric_reporter.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/public/aggregated_metric_reporter.h @@ -8,7 +8,6 @@ #include <array> #include "base/gtest_prod_util.h" -#include "base/macros.h" #include "base/metrics/histogram.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" @@ -51,6 +50,8 @@ class AggregatedMetricReporter { static_cast<int>(TaskClass::kCount) + 1, base::HistogramBase::kUmaTargetedHistogramFlag), aggregator) {} + AggregatedMetricReporter(const AggregatedMetricReporter&) = delete; + AggregatedMetricReporter& operator=(const AggregatedMetricReporter&) = delete; ~AggregatedMetricReporter() {} @@ -82,8 +83,6 @@ class AggregatedMetricReporter { AggregatorFuncPtr aggregator_; THREAD_CHECKER(thread_checker_); - - DISALLOW_COPY_AND_ASSIGN(AggregatedMetricReporter); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/cooperative_scheduling_manager.h b/chromium/third_party/blink/renderer/platform/scheduler/public/cooperative_scheduling_manager.h index 6f6f4222208..302eb4cadc0 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/public/cooperative_scheduling_manager.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/public/cooperative_scheduling_manager.h @@ -36,6 +36,9 @@ class PLATFORM_EXPORT CooperativeSchedulingManager { static CooperativeSchedulingManager* Instance(); CooperativeSchedulingManager(); + CooperativeSchedulingManager(const CooperativeSchedulingManager&) = delete; + CooperativeSchedulingManager& operator=(const CooperativeSchedulingManager&) = + delete; virtual ~CooperativeSchedulingManager() = default; // Returns true if reentry is allowed in the current C++ stack. @@ -65,8 +68,6 @@ class PLATFORM_EXPORT CooperativeSchedulingManager { base::TimeTicks wait_until_; const base::TickClock* clock_; bool feature_enabled_ = true; - - DISALLOW_COPY_AND_ASSIGN(CooperativeSchedulingManager); }; inline void CooperativeSchedulingManager::Safepoint() { diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/event_loop.h b/chromium/third_party/blink/renderer/platform/scheduler/public/event_loop.h index d2ee089685f..4e48ffb5f28 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/public/event_loop.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/public/event_loop.h @@ -59,6 +59,9 @@ class PLATFORM_EXPORT EventLoop final : public WTF::RefCounted<EventLoop> { USING_FAST_MALLOC(EventLoop); public: + EventLoop(const EventLoop&) = delete; + EventLoop& operator=(const EventLoop&) = delete; + // Queues |cb| to the backing v8::MicrotaskQueue. void EnqueueMicrotask(base::OnceClosure cb); @@ -97,8 +100,6 @@ class PLATFORM_EXPORT EventLoop final : public WTF::RefCounted<EventLoop> { Deque<base::OnceClosure> pending_microtasks_; std::unique_ptr<v8::MicrotaskQueue> microtask_queue_; HashSet<FrameOrWorkerScheduler*> schedulers_; - - DISALLOW_COPY_AND_ASSIGN(EventLoop); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h index 8b7cf123371..eb4ccddc93f 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h @@ -10,11 +10,13 @@ #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/scheduler/public/scheduling_lifecycle_state.h" #include "third_party/blink/renderer/platform/scheduler/public/scheduling_policy.h" +#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/hash_map.h" namespace blink { class FrameScheduler; +class WebSchedulingTaskQueue; // This is the base class of FrameScheduler and WorkerScheduler. class PLATFORM_EXPORT FrameOrWorkerScheduler { @@ -41,13 +43,13 @@ class PLATFORM_EXPORT FrameOrWorkerScheduler { public: LifecycleObserverHandle(FrameOrWorkerScheduler* scheduler, Observer* observer); + LifecycleObserverHandle(const LifecycleObserverHandle&) = delete; + LifecycleObserverHandle& operator=(const LifecycleObserverHandle&) = delete; ~LifecycleObserverHandle(); private: base::WeakPtr<FrameOrWorkerScheduler> scheduler_; Observer* observer_; - - DISALLOW_COPY_AND_ASSIGN(LifecycleObserverHandle); }; // RAII handle which should be kept alive as long as the feature is active @@ -58,11 +60,11 @@ class PLATFORM_EXPORT FrameOrWorkerScheduler { public: SchedulingAffectingFeatureHandle() = default; SchedulingAffectingFeatureHandle(SchedulingAffectingFeatureHandle&&); - inline ~SchedulingAffectingFeatureHandle() { reset(); } - SchedulingAffectingFeatureHandle& operator=( SchedulingAffectingFeatureHandle&&); + inline ~SchedulingAffectingFeatureHandle() { reset(); } + explicit operator bool() const { return scheduler_.get(); } inline void reset() { @@ -81,8 +83,6 @@ class PLATFORM_EXPORT FrameOrWorkerScheduler { SchedulingPolicy::Feature feature_ = SchedulingPolicy::Feature::kMaxValue; SchedulingPolicy policy_; base::WeakPtr<FrameOrWorkerScheduler> scheduler_; - - DISALLOW_COPY_AND_ASSIGN(SchedulingAffectingFeatureHandle); }; virtual ~FrameOrWorkerScheduler(); @@ -118,6 +118,9 @@ class PLATFORM_EXPORT FrameOrWorkerScheduler { Observer*) WARN_UNUSED_RESULT; + virtual std::unique_ptr<WebSchedulingTaskQueue> CreateWebSchedulingTaskQueue( + WebSchedulingPriority) = 0; + virtual FrameScheduler* ToFrameScheduler() { return nullptr; } base::WeakPtr<FrameOrWorkerScheduler> GetWeakPtr(); diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h index ffba694c427..15f3c0b9e19 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h @@ -17,7 +17,6 @@ #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h" -#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h" #include "third_party/blink/renderer/platform/wtf/hash_set.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -32,7 +31,6 @@ class WebAgentGroupScheduler; } // namespace scheduler class PageScheduler; -class WebSchedulingTaskQueue; class FrameScheduler : public FrameOrWorkerScheduler { public: @@ -130,9 +128,6 @@ class FrameScheduler : public FrameOrWorkerScheduler { virtual std::unique_ptr<scheduler::WebResourceLoadingTaskRunnerHandle> CreateResourceLoadingMaybeUnfreezableTaskRunnerHandle() = 0; - virtual std::unique_ptr<WebSchedulingTaskQueue> CreateWebSchedulingTaskQueue( - WebSchedulingPriority) = 0; - // Returns the parent PageScheduler. virtual PageScheduler* GetPageScheduler() const = 0; @@ -160,6 +155,10 @@ class FrameScheduler : public FrameOrWorkerScheduler { virtual void DidCommitProvisionalLoad(bool is_web_history_inert_commit, NavigationType navigation_type) = 0; + // Tells the scheduler that the "DOMContentLoaded" event has occurred for this + // frame. + virtual void OnDomContentLoaded() = 0; + // Tells the scheduler that the first contentful paint has occurred for this // frame. Only for main frames. virtual void OnFirstContentfulPaintInMainFrame() = 0; diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/page_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/public/page_scheduler.h index 795ed1f870a..00a40ddbc25 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/public/page_scheduler.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/public/page_scheduler.h @@ -38,8 +38,6 @@ class PLATFORM_EXPORT PageScheduler { // Returns true iff the network is idle for the local main frame. // Always returns false if the main frame is remote. virtual bool LocalMainFrameNetworkIsAlmostIdle() const { return true; } - // Returns if the page has focus. - virtual bool IsFocused() const = 0; }; virtual ~PageScheduler() = default; @@ -53,8 +51,6 @@ class PLATFORM_EXPORT PageScheduler { virtual void SetPageFrozen(bool) = 0; // Handles operations required for storing the page in the back-forward cache. virtual void SetPageBackForwardCached(bool) = 0; - // Handle page focus changed. - virtual void OnFocusChanged(bool focused) = 0; // Tells the scheduler about "keep-alive" state which can be due to: // service workers, shared workers, or fetch keep-alive. // If true, then the scheduler should not freeze relevant task queues. @@ -121,10 +117,6 @@ class PLATFORM_EXPORT PageScheduler { // This is used to set initial Date.now() while in virtual time mode. virtual void SetInitialVirtualTime(base::Time time) = 0; - // This is used for cross origin navigations to account for virtual time - // advancing in the previous renderer. - virtual void SetInitialVirtualTimeOffset(base::TimeDelta offset) = 0; - // Sets the virtual time policy, which is applied imemdiatly to all child // FrameSchedulers. virtual void SetVirtualTimePolicy(VirtualTimePolicy) = 0; diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h b/chromium/third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h index cfbe0ea5ae0..2f3e648b284 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h @@ -17,8 +17,8 @@ namespace blink { inline bool PostCrossThreadTask(base::SequencedTaskRunner& task_runner, const base::Location& location, WTF::CrossThreadOnceClosure task) { - return task_runner.PostDelayedTask( - location, ConvertToBaseOnceCallback(std::move(task)), base::TimeDelta()); + return task_runner.PostTask(location, + ConvertToBaseOnceCallback(std::move(task))); } inline bool PostDelayedCrossThreadTask(base::SequencedTaskRunner& task_runner, diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/thread.h b/chromium/third_party/blink/renderer/platform/scheduler/public/thread.h index 7512cc93e53..621b1fbc4da 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/public/thread.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/public/thread.h @@ -27,7 +27,6 @@ #include <stdint.h> #include "base/callback_forward.h" -#include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "base/task/task_observer.h" #include "base/threading/thread.h" @@ -110,6 +109,8 @@ class PLATFORM_EXPORT Thread { static Thread* CompositorThread(); Thread(); + Thread(const Thread&) = delete; + Thread& operator=(const Thread&) = delete; virtual ~Thread(); // Must be called immediately after the construction. @@ -164,8 +165,6 @@ class PLATFORM_EXPORT Thread { // This is used to identify the actual Thread instance. This should be // used only in Platform, and other users should ignore this. virtual bool IsSimpleMainThread() const { return false; } - - DISALLOW_COPY_AND_ASSIGN(Thread); }; } // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/thread_cpu_throttler.h b/chromium/third_party/blink/renderer/platform/scheduler/public/thread_cpu_throttler.h index 06f559fad9f..78e1eec2153 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/public/thread_cpu_throttler.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/public/thread_cpu_throttler.h @@ -7,7 +7,6 @@ #include <memory> -#include "base/macros.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" @@ -29,6 +28,9 @@ class PLATFORM_EXPORT ThreadCPUThrottler final { public: static ThreadCPUThrottler* GetInstance(); + ThreadCPUThrottler(const ThreadCPUThrottler&) = delete; + ThreadCPUThrottler& operator=(const ThreadCPUThrottler&) = delete; + // |rate| is a slow-down factor - passing 2.0 will make // everything two times slower. // Any rate less or equal to 1.0 disables throttling and @@ -42,8 +44,6 @@ class PLATFORM_EXPORT ThreadCPUThrottler final { class ThrottlingThread; std::unique_ptr<ThrottlingThread> throttling_thread_; - - DISALLOW_COPY_AND_ASSIGN(ThreadCPUThrottler); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h index a7e2d1ef069..1c87da1aef6 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h @@ -154,19 +154,20 @@ class PLATFORM_EXPORT ThreadScheduler { // Associates |isolate| to the scheduler. virtual void SetV8Isolate(v8::Isolate* isolate) = 0; - virtual void OnSafepointEntered() {} - virtual void OnSafepointExited() {} - // Test helpers. + virtual scheduler::NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() = 0; + + private: + // For GetWebMainThreadScheduler(). + friend class scheduler::WebThreadScheduler; + // Return a reference to an underlying main thread WebThreadScheduler object. // Can be null if there is no underlying main thread WebThreadScheduler // (e.g. worker threads). - virtual scheduler::WebThreadScheduler* GetWebMainThreadSchedulerForTest() { + virtual scheduler::WebThreadScheduler* GetWebMainThreadScheduler() { return nullptr; } - - virtual scheduler::NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() = 0; }; } // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/thread_type.h b/chromium/third_party/blink/renderer/platform/scheduler/public/thread_type.h index f562745458d..e6898971e91 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/public/thread_type.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/public/thread_type.h @@ -32,7 +32,7 @@ enum class ThreadType { kRealtimeAudioWorkletThread = 19, kSemiRealtimeAudioWorkletThread = 20, - kCount = 21 + kMaxValue = kSemiRealtimeAudioWorkletThread, }; BLINK_PLATFORM_EXPORT const char* GetNameForThreadType(ThreadType); diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h b/chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h index 049ecb25117..04e618dee8c 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h @@ -10,8 +10,7 @@ namespace blink { -// Priorities for the experimental scheduling API (see -// https://github.com/WICG/main-thread-scheduling). +// https://wicg.github.io/scheduling-apis/#sec-task-priorities enum class WebSchedulingPriority { kUserBlockingPriority = 0, kUserVisiblePriority = 1, diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_task_queue.h b/chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_task_queue.h index 0f580027676..50d783ae68d 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_task_queue.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_task_queue.h @@ -12,9 +12,9 @@ namespace blink { -// This class is used by the experimental Scheduling API to submit tasks to the -// platform's scheduler through prioritized task queues (see -// https://github.com/WICG/main-thread-scheduling). +// This class is used by the Prioritized Task Scheduling API to submit tasks to +// the platform's scheduler through prioritized task queues (see +// https://wicg.github.io/scheduling-apis/). class PLATFORM_EXPORT WebSchedulingTaskQueue { public: virtual ~WebSchedulingTaskQueue() = default; diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h index c4221032c66..e369684e390 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h @@ -35,12 +35,12 @@ class PLATFORM_EXPORT WorkerScheduler : public FrameOrWorkerScheduler { public: PauseHandle(base::WeakPtr<WorkerScheduler>); + PauseHandle(const PauseHandle&) = delete; + PauseHandle& operator=(const PauseHandle&) = delete; ~PauseHandle(); private: base::WeakPtr<WorkerScheduler> scheduler_; - - DISALLOW_COPY_AND_ASSIGN(PauseHandle); }; std::unique_ptr<PauseHandle> Pause() WARN_UNUSED_RESULT; @@ -69,6 +69,8 @@ class PLATFORM_EXPORT WorkerScheduler : public FrameOrWorkerScheduler { // FrameOrWorkerScheduler implementation: void SetPreemptedForCooperativeScheduling(Preempted) override {} + std::unique_ptr<WebSchedulingTaskQueue> CreateWebSchedulingTaskQueue( + WebSchedulingPriority) override; protected: scoped_refptr<NonMainThreadTaskQueue> ThrottleableTaskQueue(); diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_metrics_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_metrics_helper.h index 5ebac2e537f..7acae9fb4b0 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_metrics_helper.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_metrics_helper.h @@ -14,14 +14,13 @@ namespace scheduler { class PLATFORM_EXPORT CompositorMetricsHelper : public MetricsHelper { public: explicit CompositorMetricsHelper(bool has_cpu_timing_for_each_task); + CompositorMetricsHelper(const CompositorMetricsHelper&) = delete; + CompositorMetricsHelper& operator=(const CompositorMetricsHelper&) = delete; ~CompositorMetricsHelper(); void RecordTaskMetrics( const base::sequence_manager::Task& task, const base::sequence_manager::TaskQueue::TaskTiming& task_timing); - - private: - DISALLOW_COPY_AND_ASSIGN(CompositorMetricsHelper); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread.h index 0c894171e91..a689ce9cedd 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread.h @@ -5,7 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_COMPOSITOR_THREAD_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_COMPOSITOR_THREAD_H_ -#include "base/macros.h" #include "third_party/blink/renderer/platform/scheduler/worker/worker_thread.h" namespace blink { @@ -14,13 +13,13 @@ namespace scheduler { class PLATFORM_EXPORT CompositorThread : public WorkerThread { public: explicit CompositorThread(const ThreadCreationParams& params); + CompositorThread(const CompositorThread&) = delete; + CompositorThread& operator=(const CompositorThread&) = delete; ~CompositorThread() override; private: std::unique_ptr<NonMainThreadSchedulerImpl> CreateNonMainThreadScheduler( base::sequence_manager::SequenceManager* sequence_manager) override; - - DISALLOW_COPY_AND_ASSIGN(CompositorThread); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc index 0779cb5c427..0c4c6c67e64 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc @@ -79,6 +79,11 @@ CompositorThreadScheduler::DefaultTaskRunner() { } scoped_refptr<base::SingleThreadTaskRunner> +CompositorThreadScheduler::InputTaskRunner() { + return helper()->InputTaskRunner(); +} + +scoped_refptr<base::SingleThreadTaskRunner> CompositorThreadScheduler::CompositorTaskRunner() { NOTREACHED(); return nullptr; diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h index 61c35b52d82..6302f70e93c 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h @@ -5,7 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_COMPOSITOR_THREAD_SCHEDULER_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_COMPOSITOR_THREAD_SCHEDULER_H_ -#include "base/macros.h" #include "base/single_thread_task_runner.h" #include "components/scheduling_metrics/task_duration_metric_reporter.h" #include "third_party/blink/renderer/platform/platform_export.h" @@ -27,6 +26,9 @@ class PLATFORM_EXPORT CompositorThreadScheduler public: explicit CompositorThreadScheduler( base::sequence_manager::SequenceManager* sequence_manager); + CompositorThreadScheduler(const CompositorThreadScheduler&) = delete; + CompositorThreadScheduler& operator=(const CompositorThreadScheduler&) = + delete; ~CompositorThreadScheduler() override; @@ -41,6 +43,7 @@ class PLATFORM_EXPORT CompositorThreadScheduler // WebThreadScheduler: scoped_refptr<base::SingleThreadTaskRunner> V8TaskRunner() override; scoped_refptr<base::SingleThreadTaskRunner> DefaultTaskRunner() override; + scoped_refptr<base::SingleThreadTaskRunner> InputTaskRunner() override; scoped_refptr<base::SingleThreadTaskRunner> CompositorTaskRunner() override; scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() override; bool ShouldYieldForHighPriorityWork() override; @@ -63,8 +66,6 @@ class PLATFORM_EXPORT CompositorThreadScheduler private: CompositorMetricsHelper compositor_metrics_helper_; - - DISALLOW_COPY_AND_ASSIGN(CompositorThreadScheduler); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.cc index de39768060c..468aebe1334 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.cc @@ -20,10 +20,12 @@ NonMainThreadSchedulerHelper::NonMainThreadSchedulerHelper( non_main_thread_scheduler_(non_main_thread_scheduler), default_task_queue_(NewTaskQueue(TaskQueue::Spec("subthread_default_tq") .SetShouldMonitorQuiescence(true))), + input_task_queue_(NewTaskQueue(TaskQueue::Spec("subthread_input_tq"))), control_task_queue_(NewTaskQueue(TaskQueue::Spec("subthread_control_tq") .SetShouldNotifyObservers(false))) { InitDefaultQueues(default_task_queue_, control_task_queue_, default_task_type); + input_task_queue_->SetQueuePriority(TaskQueue::kHighestPriority); } NonMainThreadSchedulerHelper::~NonMainThreadSchedulerHelper() { @@ -41,6 +43,11 @@ NonMainThreadSchedulerHelper::DefaultTaskRunner() { return default_task_queue_->GetTaskRunnerWithDefaultTaskType(); } +const scoped_refptr<base::SingleThreadTaskRunner>& +NonMainThreadSchedulerHelper::InputTaskRunner() { + return input_task_queue_->GetTaskRunnerWithDefaultTaskType(); +} + scoped_refptr<NonMainThreadTaskQueue> NonMainThreadSchedulerHelper::ControlNonMainThreadTaskQueue() { return control_task_queue_; @@ -52,9 +59,10 @@ NonMainThreadSchedulerHelper::ControlTaskRunner() { } scoped_refptr<NonMainThreadTaskQueue> -NonMainThreadSchedulerHelper::NewTaskQueue(const TaskQueue::Spec& spec) { +NonMainThreadSchedulerHelper::NewTaskQueue(const TaskQueue::Spec& spec, + bool can_be_throttled) { return sequence_manager_->CreateTaskQueueWithType<NonMainThreadTaskQueue>( - spec, non_main_thread_scheduler_); + spec, non_main_thread_scheduler_, can_be_throttled); } void NonMainThreadSchedulerHelper::ShutdownAllQueues() { diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.h index c0d7440a3da..8a18cd0e2c0 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.h @@ -25,10 +25,14 @@ class PLATFORM_EXPORT NonMainThreadSchedulerHelper : public SchedulerHelper { base::sequence_manager::SequenceManager* manager, NonMainThreadSchedulerImpl* non_main_thread_scheduler, TaskType default_task_type); + NonMainThreadSchedulerHelper(const NonMainThreadSchedulerHelper&) = delete; + NonMainThreadSchedulerHelper& operator=(const NonMainThreadSchedulerHelper&) = + delete; ~NonMainThreadSchedulerHelper() override; scoped_refptr<NonMainThreadTaskQueue> NewTaskQueue( - const base::sequence_manager::TaskQueue::Spec& spec); + const base::sequence_manager::TaskQueue::Spec& spec, + bool can_be_throttled = false); scoped_refptr<NonMainThreadTaskQueue> DefaultNonMainThreadTaskQueue(); scoped_refptr<NonMainThreadTaskQueue> ControlNonMainThreadTaskQueue(); @@ -38,15 +42,16 @@ class PLATFORM_EXPORT NonMainThreadSchedulerHelper : public SchedulerHelper { const scoped_refptr<base::SingleThreadTaskRunner>& ControlTaskRunner() override; + const scoped_refptr<base::SingleThreadTaskRunner>& InputTaskRunner(); + protected: void ShutdownAllQueues() override; private: NonMainThreadSchedulerImpl* non_main_thread_scheduler_; // NOT OWNED const scoped_refptr<NonMainThreadTaskQueue> default_task_queue_; + const scoped_refptr<NonMainThreadTaskQueue> input_task_queue_; const scoped_refptr<NonMainThreadTaskQueue> control_task_queue_; - - DISALLOW_COPY_AND_ASSIGN(NonMainThreadSchedulerHelper); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.cc index 1471095a229..3d1da66ddc3 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.cc @@ -30,11 +30,13 @@ std::unique_ptr<NonMainThreadSchedulerImpl> NonMainThreadSchedulerImpl::Create( } scoped_refptr<NonMainThreadTaskQueue> -NonMainThreadSchedulerImpl::CreateTaskQueue(const char* name) { +NonMainThreadSchedulerImpl::CreateTaskQueue(const char* name, + bool can_be_throttled) { helper_.CheckOnValidThread(); return helper_.NewTaskQueue(base::sequence_manager::TaskQueue::Spec(name) .SetShouldMonitorQuiescence(true) - .SetTimeDomain(nullptr)); + .SetTimeDomain(nullptr), + can_be_throttled); } void NonMainThreadSchedulerImpl::RunIdleTask(Thread::IdleTask task, diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h index 901003735df..5b32dcce581 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h @@ -7,7 +7,6 @@ #include <memory> -#include "base/macros.h" #include "base/task/sequence_manager/sequence_manager.h" #include "base/task/sequence_manager/task_queue.h" #include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h" @@ -28,6 +27,9 @@ class WorkerSchedulerProxy; class PLATFORM_EXPORT NonMainThreadSchedulerImpl : public ThreadSchedulerImpl { public: + NonMainThreadSchedulerImpl(const NonMainThreadSchedulerImpl&) = delete; + NonMainThreadSchedulerImpl& operator=(const NonMainThreadSchedulerImpl&) = + delete; ~NonMainThreadSchedulerImpl() override; // |sequence_manager| and |proxy| must remain valid for the entire lifetime of @@ -96,7 +98,9 @@ class PLATFORM_EXPORT NonMainThreadSchedulerImpl : public ThreadSchedulerImpl { // // virtual void Shutdown(); - scoped_refptr<NonMainThreadTaskQueue> CreateTaskQueue(const char* name); + scoped_refptr<NonMainThreadTaskQueue> CreateTaskQueue( + const char* name, + bool can_be_throttled = false); scoped_refptr<base::SingleThreadTaskRunner> DeprecatedDefaultTaskRunner() override; @@ -116,8 +120,6 @@ class PLATFORM_EXPORT NonMainThreadSchedulerImpl : public ThreadSchedulerImpl { private: NonMainThreadSchedulerHelper helper_; - - DISALLOW_COPY_AND_ASSIGN(NonMainThreadSchedulerImpl); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.cc index 065986002f2..d1396f59ddc 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.cc @@ -5,6 +5,7 @@ #include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h" #include "base/bind.h" +#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h" #include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h" namespace blink { @@ -15,10 +16,17 @@ using base::sequence_manager::TaskQueue; NonMainThreadTaskQueue::NonMainThreadTaskQueue( std::unique_ptr<base::sequence_manager::internal::TaskQueueImpl> impl, const TaskQueue::Spec& spec, - NonMainThreadSchedulerImpl* non_main_thread_scheduler) + NonMainThreadSchedulerImpl* non_main_thread_scheduler, + bool can_be_throttled) : TaskQueue(std::move(impl), spec), non_main_thread_scheduler_(non_main_thread_scheduler) { + // Throttling needs |should_notify_observers| to get task timing. + DCHECK(!can_be_throttled || spec.should_notify_observers) + << "Throttled queue is not supported with |!should_notify_observers|"; if (GetTaskQueueImpl() && spec.should_notify_observers) { + if (can_be_throttled) { + throttler_.emplace(this, non_main_thread_scheduler->GetTickClock()); + } // TaskQueueImpl may be null for tests. GetTaskQueueImpl()->SetOnTaskCompletedHandler(base::BindRepeating( &NonMainThreadTaskQueue::OnTaskCompleted, base::Unretained(this))); @@ -27,6 +35,12 @@ NonMainThreadTaskQueue::NonMainThreadTaskQueue( NonMainThreadTaskQueue::~NonMainThreadTaskQueue() = default; +void NonMainThreadTaskQueue::ShutdownTaskQueue() { + non_main_thread_scheduler_ = nullptr; + throttler_.reset(); + TaskQueue::ShutdownTaskQueue(); +} + void NonMainThreadTaskQueue::OnTaskCompleted( const base::sequence_manager::Task& task, TaskQueue::TaskTiming* task_timing, @@ -38,5 +52,54 @@ void NonMainThreadTaskQueue::OnTaskCompleted( } } +void NonMainThreadTaskQueue::AddToBudgetPool(base::TimeTicks now, + BudgetPool* pool) { + pool->AddThrottler(now, &throttler_.value()); +} + +void NonMainThreadTaskQueue::RemoveFromBudgetPool(base::TimeTicks now, + BudgetPool* pool) { + pool->RemoveThrottler(now, &throttler_.value()); +} + +void NonMainThreadTaskQueue::IncreaseThrottleRefCount() { + throttler_->IncreaseThrottleRefCount(); +} + +void NonMainThreadTaskQueue::DecreaseThrottleRefCount() { + throttler_->DecreaseThrottleRefCount(); +} + +void NonMainThreadTaskQueue::OnTaskRunTimeReported( + TaskQueue::TaskTiming* task_timing) { + if (throttler_.has_value()) { + throttler_->OnTaskRunTimeReported(task_timing->start_time(), + task_timing->end_time()); + } +} + +void NonMainThreadTaskQueue::SetWebSchedulingPriority( + WebSchedulingPriority priority) { + if (web_scheduling_priority_ == priority) + return; + web_scheduling_priority_ = priority; + OnWebSchedulingPriorityChanged(); +} + +void NonMainThreadTaskQueue::OnWebSchedulingPriorityChanged() { + DCHECK(web_scheduling_priority_); + switch (web_scheduling_priority_.value()) { + case WebSchedulingPriority::kUserBlockingPriority: + SetQueuePriority(TaskQueue::QueuePriority::kHighPriority); + return; + case WebSchedulingPriority::kUserVisiblePriority: + SetQueuePriority(TaskQueue::QueuePriority::kNormalPriority); + return; + case WebSchedulingPriority::kBackgroundPriority: + SetQueuePriority(TaskQueue::QueuePriority::kLowPriority); + return; + } +} + } // namespace scheduler } // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h index 12b25539d22..55063597b71 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h @@ -6,8 +6,11 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_NON_MAIN_THREAD_TASK_QUEUE_H_ #include "base/task/sequence_manager/task_queue_impl.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/platform/task_type.h" #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/public/web_scheduling_priority.h" namespace blink { namespace scheduler { @@ -21,7 +24,8 @@ class PLATFORM_EXPORT NonMainThreadTaskQueue NonMainThreadTaskQueue( std::unique_ptr<base::sequence_manager::internal::TaskQueueImpl> impl, const Spec& spec, - NonMainThreadSchedulerImpl* non_main_thread_scheduler); + NonMainThreadSchedulerImpl* non_main_thread_scheduler, + bool can_be_throttled); ~NonMainThreadTaskQueue() override; void OnTaskCompleted( @@ -34,6 +38,19 @@ class PLATFORM_EXPORT NonMainThreadTaskQueue return TaskQueue::CreateTaskRunner(static_cast<int>(task_type)); } + bool IsThrottled() const { return throttler_->IsThrottled(); } + + // Methods for setting and resetting budget pools for this task queue. + // Note that a task queue can be in multiple budget pools so a pool must + // be specified when removing. + void AddToBudgetPool(base::TimeTicks now, BudgetPool* pool); + void RemoveFromBudgetPool(base::TimeTicks now, BudgetPool* pool); + + void IncreaseThrottleRefCount(); + void DecreaseThrottleRefCount(); + + void ShutdownTaskQueue() override; + // This method returns the default task runner with task type kTaskTypeNone // and is mostly used for tests. For most use cases, you'll want a more // specific task runner and should use the 'CreateTaskRunner' method and pass @@ -43,9 +60,21 @@ class PLATFORM_EXPORT NonMainThreadTaskQueue return task_runner(); } + void SetWebSchedulingPriority(WebSchedulingPriority priority); + + void OnTaskRunTimeReported(TaskQueue::TaskTiming* task_timing); + private: + void OnWebSchedulingPriorityChanged(); + + absl::optional<TaskQueueThrottler> throttler_; + // Not owned. NonMainThreadSchedulerImpl* non_main_thread_scheduler_; + + // |web_scheduling_priority_| is the priority of the task queue within the web + // scheduling API. This priority is used to determine the task queue priority. + absl::optional<WebSchedulingPriority> web_scheduling_priority_; }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_web_scheduling_task_queue_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_web_scheduling_task_queue_impl.cc new file mode 100644 index 00000000000..cc6320b41ff --- /dev/null +++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_web_scheduling_task_queue_impl.cc @@ -0,0 +1,31 @@ +// Copyright 2021 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 "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_web_scheduling_task_queue_impl.h" + +#include "third_party/blink/public/platform/task_type.h" +#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h" + +namespace blink { +namespace scheduler { + +NonMainThreadWebSchedulingTaskQueueImpl:: + NonMainThreadWebSchedulingTaskQueueImpl( + scoped_refptr<NonMainThreadTaskQueue> task_queue) + : task_runner_( + task_queue->CreateTaskRunner(TaskType::kExperimentalWebScheduling)), + task_queue_(std::move(task_queue)) {} + +void NonMainThreadWebSchedulingTaskQueueImpl::SetPriority( + WebSchedulingPriority priority) { + task_queue_->SetWebSchedulingPriority(priority); +} + +scoped_refptr<base::SingleThreadTaskRunner> +NonMainThreadWebSchedulingTaskQueueImpl::GetTaskRunner() { + return task_runner_; +} + +} // namespace scheduler +} // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_web_scheduling_task_queue_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_web_scheduling_task_queue_impl.h new file mode 100644 index 00000000000..bd4e7050caa --- /dev/null +++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_web_scheduling_task_queue_impl.h @@ -0,0 +1,42 @@ +// Copyright 2021 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. + +#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_NON_MAIN_THREAD_WEB_SCHEDULING_TASK_QUEUE_IMPL_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_NON_MAIN_THREAD_WEB_SCHEDULING_TASK_QUEUE_IMPL_H_ + +#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_task_queue.h" + +#include "base/memory/scoped_refptr.h" +#include "base/single_thread_task_runner.h" +#include "third_party/blink/renderer/platform/platform_export.h" +#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h" + +namespace blink { +namespace scheduler { + +class NonMainThreadTaskQueue; + +class PLATFORM_EXPORT NonMainThreadWebSchedulingTaskQueueImpl + : public WebSchedulingTaskQueue { + public: + explicit NonMainThreadWebSchedulingTaskQueueImpl( + scoped_refptr<NonMainThreadTaskQueue>); + ~NonMainThreadWebSchedulingTaskQueueImpl() override = default; + + void SetPriority(WebSchedulingPriority) override; + + scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override; + + private: + const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + + // NonMainThreadWebSchedulingTaskQueueImpl owns this NonMainThreadTaskQueue + // and has the sole reference to it after its creation. + const scoped_refptr<NonMainThreadTaskQueue> task_queue_; +}; + +} // namespace scheduler +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_NON_MAIN_THREAD_WEB_SCHEDULING_TASK_QUEUE_IMPL_H_ diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_metrics_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_metrics_helper.h index d71aab7a391..7303bf95c41 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_metrics_helper.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_metrics_helper.h @@ -5,6 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_WORKER_METRICS_HELPER_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_WORKER_METRICS_HELPER_H_ +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/renderer/platform/scheduler/common/metrics_helper.h" #include "third_party/blink/renderer/platform/scheduler/common/thread_load_tracker.h" @@ -18,6 +19,8 @@ class PLATFORM_EXPORT WorkerMetricsHelper : public MetricsHelper { public: explicit WorkerMetricsHelper(ThreadType thread_type, bool has_cpu_timing_for_each_task); + WorkerMetricsHelper(const WorkerMetricsHelper&) = delete; + WorkerMetricsHelper& operator=(const WorkerMetricsHelper&) = delete; ~WorkerMetricsHelper(); void RecordTaskMetrics( @@ -37,8 +40,6 @@ class PLATFORM_EXPORT WorkerMetricsHelper : public MetricsHelper { background_dedicated_worker_per_parent_frame_status_duration_reporter_; absl::optional<FrameOriginType> parent_frame_type_; - - DISALLOW_COPY_AND_ASSIGN(WorkerMetricsHelper); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc index c55346e9190..91cd5b89f20 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc @@ -6,8 +6,10 @@ #include "third_party/blink/public/common/features.h" #include "third_party/blink/renderer/platform/back_forward_cache_utils.h" +#include "third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h" #include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h" #include "third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h" +#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_web_scheduling_task_queue_impl.h" #include "third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h" #include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h" @@ -28,7 +30,8 @@ WorkerScheduler::PauseHandle::~PauseHandle() { WorkerScheduler::WorkerScheduler(WorkerThreadScheduler* worker_thread_scheduler, WorkerSchedulerProxy* proxy) : throttleable_task_queue_( - worker_thread_scheduler->CreateTaskQueue("worker_throttleable_tq")), + worker_thread_scheduler->CreateTaskQueue("worker_throttleable_tq", + true)), pausable_task_queue_( worker_thread_scheduler->CreateTaskQueue("worker_pausable_tq")), unpausable_task_queue_( @@ -90,8 +93,10 @@ void WorkerScheduler::ResumeImpl() { } void WorkerScheduler::SetUpThrottling() { - if (!thread_scheduler_->task_queue_throttler()) + if (!thread_scheduler_->wake_up_budget_pool() && + !thread_scheduler_->cpu_time_budget_pool()) { return; + } base::TimeTicks now = thread_scheduler_->GetTickClock()->NowTicks(); WakeUpBudgetPool* wake_up_budget_pool = @@ -99,14 +104,11 @@ void WorkerScheduler::SetUpThrottling() { CPUTimeBudgetPool* cpu_time_budget_pool = thread_scheduler_->cpu_time_budget_pool(); - DCHECK(wake_up_budget_pool || cpu_time_budget_pool) - << "At least one budget pool should be present"; - if (wake_up_budget_pool) { - wake_up_budget_pool->AddQueue(now, throttleable_task_queue_.get()); + throttleable_task_queue_->AddToBudgetPool(now, wake_up_budget_pool); } if (cpu_time_budget_pool) { - cpu_time_budget_pool->AddQueue(now, throttleable_task_queue_.get()); + throttleable_task_queue_->AddToBudgetPool(now, cpu_time_budget_pool); } } @@ -116,11 +118,6 @@ SchedulingLifecycleState WorkerScheduler::CalculateLifecycleState( } void WorkerScheduler::Dispose() { - if (TaskQueueThrottler* throttler = - thread_scheduler_->task_queue_throttler()) { - throttler->ShutdownTaskQueue(throttleable_task_queue_.get()); - } - thread_scheduler_->UnregisterWorkerScheduler(this); for (const auto& pair : task_runners_) { @@ -220,7 +217,7 @@ scoped_refptr<base::SingleThreadTaskRunner> WorkerScheduler::GetTaskRunner( case TaskType::kInternalHighPriorityLocalFrame: case TaskType::kInternalInputBlocking: case TaskType::kMainThreadTaskQueueIPCTracking: - case TaskType::kCount: + case TaskType::kInternalPostMessageForwarding: NOTREACHED(); break; } @@ -235,12 +232,12 @@ void WorkerScheduler::OnLifecycleStateChanged( lifecycle_state_ = lifecycle_state; thread_scheduler_->OnLifecycleStateChanged(lifecycle_state); - if (TaskQueueThrottler* throttler = - thread_scheduler_->task_queue_throttler()) { + if (thread_scheduler_->cpu_time_budget_pool() || + thread_scheduler_->wake_up_budget_pool()) { if (lifecycle_state_ == SchedulingLifecycleState::kThrottled) { - throttler->IncreaseThrottleRefCount(throttleable_task_queue_.get()); + throttleable_task_queue_->IncreaseThrottleRefCount(); } else { - throttler->DecreaseThrottleRefCount(throttleable_task_queue_.get()); + throttleable_task_queue_->DecreaseThrottleRefCount(); } } NotifyLifecycleObservers(); @@ -264,5 +261,14 @@ void WorkerScheduler::OnStartedUsingFeature(SchedulingPolicy::Feature feature, void WorkerScheduler::OnStoppedUsingFeature(SchedulingPolicy::Feature feature, const SchedulingPolicy& policy) {} +std::unique_ptr<WebSchedulingTaskQueue> +WorkerScheduler::CreateWebSchedulingTaskQueue(WebSchedulingPriority priority) { + scoped_refptr<NonMainThreadTaskQueue> task_queue = + thread_scheduler_->CreateTaskQueue("worker_web_scheduling_tq"); + task_queue->SetWebSchedulingPriority(priority); + return std::make_unique<NonMainThreadWebSchedulingTaskQueueImpl>( + std::move(task_queue)); +} + } // namespace scheduler } // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h index 341d6116429..efe0b014eb0 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h @@ -5,7 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_WORKER_SCHEDULER_PROXY_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_WORKER_SCHEDULER_PROXY_H_ -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" @@ -34,6 +33,8 @@ class PLATFORM_EXPORT WorkerSchedulerProxy : public FrameOrWorkerScheduler::Observer { public: explicit WorkerSchedulerProxy(FrameOrWorkerScheduler* scheduler); + WorkerSchedulerProxy(const WorkerSchedulerProxy&) = delete; + WorkerSchedulerProxy& operator=(const WorkerSchedulerProxy&) = delete; ~WorkerSchedulerProxy() override; void OnWorkerSchedulerCreated( @@ -85,8 +86,6 @@ class PLATFORM_EXPORT WorkerSchedulerProxy ukm::SourceId ukm_source_id_ = ukm::kInvalidSourceId; THREAD_CHECKER(parent_thread_checker_); - - DISALLOW_COPY_AND_ASSIGN(WorkerSchedulerProxy); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc index 932a3418b26..6b6db450f24 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc @@ -6,13 +6,15 @@ #include <memory> #include "base/bind.h" -#include "base/macros.h" #include "base/task/sequence_manager/test/sequence_manager_for_test.h" #include "base/test/simple_test_tick_clock.h" #include "base/test/test_mock_time_task_runner.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h" #include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h" +#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h" +#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_task_queue.h" #include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h" #include "third_party/blink/renderer/platform/wtf/functional.h" @@ -71,7 +73,7 @@ class WorkerThreadSchedulerForTest : public WorkerThreadScheduler { return GetWorkerSchedulersForTesting(); } - using WorkerThreadScheduler::CreateTaskQueueThrottler; + using WorkerThreadScheduler::CreateBudgetPools; using WorkerThreadScheduler::SetCPUTimeBudgetPoolForTesting; }; @@ -99,8 +101,11 @@ class WorkerSchedulerTest : public testing::Test { nullptr /* proxy */)) { mock_task_runner_->AdvanceMockTickClock( base::TimeDelta::FromMicroseconds(5000)); + start_time_ = mock_task_runner_->NowTicks(); } + WorkerSchedulerTest(const WorkerSchedulerTest&) = delete; + WorkerSchedulerTest& operator=(const WorkerSchedulerTest&) = delete; ~WorkerSchedulerTest() override = default; void SetUp() override { @@ -138,8 +143,7 @@ class WorkerSchedulerTest : public testing::Test { sequence_manager_; std::unique_ptr<WorkerThreadSchedulerForTest> scheduler_; std::unique_ptr<WorkerSchedulerForTest> worker_scheduler_; - - DISALLOW_COPY_AND_ASSIGN(WorkerSchedulerTest); + base::TimeTicks start_time_; }; TEST_F(WorkerSchedulerTest, TestPostTasks) { @@ -185,28 +189,24 @@ TEST_F(WorkerSchedulerTest, RegisterWorkerSchedulers) { } TEST_F(WorkerSchedulerTest, ThrottleWorkerScheduler) { - scheduler_->CreateTaskQueueThrottler(); + scheduler_->CreateBudgetPools(); - EXPECT_FALSE(scheduler_->task_queue_throttler()->IsThrottled( - worker_scheduler_->ThrottleableTaskQueue().get())); + EXPECT_FALSE(worker_scheduler_->ThrottleableTaskQueue()->IsThrottled()); scheduler_->OnLifecycleStateChanged(SchedulingLifecycleState::kThrottled); - EXPECT_TRUE(scheduler_->task_queue_throttler()->IsThrottled( - worker_scheduler_->ThrottleableTaskQueue().get())); + EXPECT_TRUE(worker_scheduler_->ThrottleableTaskQueue()->IsThrottled()); scheduler_->OnLifecycleStateChanged(SchedulingLifecycleState::kThrottled); - EXPECT_TRUE(scheduler_->task_queue_throttler()->IsThrottled( - worker_scheduler_->ThrottleableTaskQueue().get())); + EXPECT_TRUE(worker_scheduler_->ThrottleableTaskQueue()->IsThrottled()); // Ensure that two calls with kThrottled do not mess with throttling // refcount. scheduler_->OnLifecycleStateChanged(SchedulingLifecycleState::kNotThrottled); - EXPECT_FALSE(scheduler_->task_queue_throttler()->IsThrottled( - worker_scheduler_->ThrottleableTaskQueue().get())); + EXPECT_FALSE(worker_scheduler_->ThrottleableTaskQueue()->IsThrottled()); } TEST_F(WorkerSchedulerTest, ThrottleWorkerScheduler_CreateThrottled) { - scheduler_->CreateTaskQueueThrottler(); + scheduler_->CreateBudgetPools(); scheduler_->OnLifecycleStateChanged(SchedulingLifecycleState::kThrottled); @@ -214,14 +214,13 @@ TEST_F(WorkerSchedulerTest, ThrottleWorkerScheduler_CreateThrottled) { std::make_unique<WorkerSchedulerForTest>(scheduler_.get()); // Ensure that newly created scheduler is throttled. - EXPECT_TRUE(scheduler_->task_queue_throttler()->IsThrottled( - worker_scheduler2->ThrottleableTaskQueue().get())); + EXPECT_TRUE(worker_scheduler2->ThrottleableTaskQueue()->IsThrottled()); worker_scheduler2->Dispose(); } TEST_F(WorkerSchedulerTest, ThrottleWorkerScheduler_RunThrottledTasks) { - scheduler_->CreateTaskQueueThrottler(); + scheduler_->CreateBudgetPools(); scheduler_->SetCPUTimeBudgetPoolForTesting(nullptr); // Create a new |worker_scheduler| to ensure that it's properly initialised. @@ -251,7 +250,7 @@ TEST_F(WorkerSchedulerTest, ThrottleWorkerScheduler_RunThrottledTasks) { TEST_F(WorkerSchedulerTest, ThrottleWorkerScheduler_RunThrottledTasks_CPUBudget) { - scheduler_->CreateTaskQueueThrottler(); + scheduler_->CreateBudgetPools(); scheduler_->cpu_time_budget_pool()->SetTimeBudgetRecoveryRate( GetClock()->NowTicks(), 0.01); @@ -273,12 +272,12 @@ TEST_F(WorkerSchedulerTest, RunUntilIdle(); - EXPECT_THAT( - tasks, ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1), - base::TimeTicks() + base::TimeDelta::FromSeconds(11), - base::TimeTicks() + base::TimeDelta::FromSeconds(21), - base::TimeTicks() + base::TimeDelta::FromSeconds(31), - base::TimeTicks() + base::TimeDelta::FromSeconds(41))); + EXPECT_THAT(tasks, + ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1), + start_time_ + base::TimeDelta::FromSeconds(10), + start_time_ + base::TimeDelta::FromSeconds(20), + start_time_ + base::TimeDelta::FromSeconds(30), + start_time_ + base::TimeDelta::FromSeconds(40))); } TEST_F(WorkerSchedulerTest, MAYBE_PausableTasks) { @@ -315,6 +314,83 @@ TEST_F(WorkerSchedulerTest, MAYBE_NestedPauseHandlesTasks) { EXPECT_THAT(run_order, testing::ElementsAre("T1", "T2")); } +class NonMainThreadWebSchedulingTaskQueueTest : public WorkerSchedulerTest { + public: + void SetUp() override { + WorkerSchedulerTest::SetUp(); + + for (int i = 0; i <= static_cast<int>(WebSchedulingPriority::kLastPriority); + i++) { + WebSchedulingPriority priority = static_cast<WebSchedulingPriority>(i); + std::unique_ptr<WebSchedulingTaskQueue> task_queue = + worker_scheduler_->CreateWebSchedulingTaskQueue(priority); + task_queues_.push_back(std::move(task_queue)); + } + } + + void TearDown() override { + WorkerSchedulerTest::TearDown(); + task_queues_.clear(); + } + + protected: + // Helper for posting tasks to a WebSchedulingTaskQueue. |task_descriptor| is + // a string with space delimited task identifiers. The first letter of each + // task identifier specifies the task queue priority: + // - 'U': UserBlocking + // - 'V': UserVisible + // - 'B': Background + void PostWebSchedulingTestTasks(Vector<String>* run_order, + const String& task_descriptor) { + std::istringstream stream(task_descriptor.Utf8()); + while (!stream.eof()) { + std::string task; + stream >> task; + WebSchedulingPriority priority; + switch (task[0]) { + case 'U': + priority = WebSchedulingPriority::kUserBlockingPriority; + break; + case 'V': + priority = WebSchedulingPriority::kUserVisiblePriority; + break; + case 'B': + priority = WebSchedulingPriority::kBackgroundPriority; + break; + default: + EXPECT_FALSE(true); + return; + } + task_queues_[static_cast<int>(priority)]->GetTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(&AppendToVectorTestTask, run_order, + String::FromUTF8(task))); + } + } + Vector<std::unique_ptr<WebSchedulingTaskQueue>> task_queues_; +}; + +TEST_F(NonMainThreadWebSchedulingTaskQueueTest, TasksRunInPriorityOrder) { + Vector<String> run_order; + + PostWebSchedulingTestTasks(&run_order, "B1 B2 V1 V2 U1 U2"); + + RunUntilIdle(); + EXPECT_THAT(run_order, + testing::ElementsAre("U1", "U2", "V1", "V2", "B1", "B2")); +} + +TEST_F(NonMainThreadWebSchedulingTaskQueueTest, DynamicTaskPriorityOrder) { + Vector<String> run_order; + + PostWebSchedulingTestTasks(&run_order, "B1 B2 V1 V2 U1 U2"); + task_queues_[static_cast<int>(WebSchedulingPriority::kUserBlockingPriority)] + ->SetPriority(WebSchedulingPriority::kBackgroundPriority); + + RunUntilIdle(); + EXPECT_THAT(run_order, + testing::ElementsAre("V1", "V2", "B1", "B2", "U1", "U2")); +} + } // namespace worker_scheduler_unittest } // namespace scheduler } // namespace blink diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc index 35284815699..519087970f5 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc @@ -23,7 +23,9 @@ #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/platform/scheduler/common/features.h" #include "third_party/blink/renderer/platform/scheduler/common/process_state.h" +#include "third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h" #include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h" +#include "third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h" #include "third_party/blink/renderer/platform/scheduler/public/event_loop.h" #include "third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h" #include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.h" @@ -117,7 +119,7 @@ WorkerThreadScheduler::WorkerThreadScheduler( if (thread_type == ThreadType::kDedicatedWorkerThread && base::FeatureList::IsEnabled(kDedicatedWorkerThrottling)) { - CreateTaskQueueThrottler(); + CreateBudgetPools(); } TRACE_EVENT_OBJECT_CREATED_WITH_ID( @@ -178,7 +180,6 @@ void WorkerThreadScheduler::RemoveTaskObserver( void WorkerThreadScheduler::Shutdown() { DCHECK(initialized_); - task_queue_throttler_.reset(); idle_helper_.Shutdown(); helper()->Shutdown(); } @@ -209,10 +210,8 @@ void WorkerThreadScheduler::OnTaskCompleted( task_timing->RecordTaskEnd(lazy_now); worker_metrics_helper_.RecordTaskMetrics(task, *task_timing); - if (task_queue_throttler_) { - task_queue_throttler_->OnTaskRunTimeReported( - task_queue, task_timing->start_time(), task_timing->end_time()); - } + if (task_queue != nullptr) + task_queue->OnTaskRunTimeReported(task_timing); RecordTaskUkm(task_queue, task, *task_timing); } @@ -258,17 +257,15 @@ WorkerThreadScheduler::ControlTaskQueue() { return helper()->ControlNonMainThreadTaskQueue(); } -void WorkerThreadScheduler::CreateTaskQueueThrottler() { - if (task_queue_throttler_) +void WorkerThreadScheduler::CreateBudgetPools() { + if (wake_up_budget_pool_ && cpu_time_budget_pool_) return; - task_queue_throttler_ = std::make_unique<TaskQueueThrottler>( - this, &traceable_variable_controller_); + base::TimeTicks now = GetTickClock()->NowTicks(); wake_up_budget_pool_ = - task_queue_throttler_->CreateWakeUpBudgetPool("worker_wake_up_pool"); - cpu_time_budget_pool_ = - task_queue_throttler_->CreateCPUTimeBudgetPool("worker_cpu_time_pool"); + std::make_unique<WakeUpBudgetPool>("worker_wake_up_pool"); + cpu_time_budget_pool_ = std::make_unique<CPUTimeBudgetPool>( + "worker_cpu_time_pool", &traceable_variable_controller_, now); - base::TimeTicks now = GetTickClock()->NowTicks(); cpu_time_budget_pool_->SetMaxBudgetLevel(now, GetMaxBudgetLevel()); cpu_time_budget_pool_->SetTimeBudgetRecoveryRate(now, GetBudgetRecoveryRate()); @@ -312,8 +309,8 @@ void WorkerThreadScheduler::SetUkmTaskSamplingRateForTest(double rate) { } void WorkerThreadScheduler::SetCPUTimeBudgetPoolForTesting( - CPUTimeBudgetPool* cpu_time_budget_pool) { - cpu_time_budget_pool_ = cpu_time_budget_pool; + std::unique_ptr<CPUTimeBudgetPool> cpu_time_budget_pool) { + cpu_time_budget_pool_ = std::move(cpu_time_budget_pool); } HashSet<WorkerScheduler*>& diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h index de6debae895..5d431c3ecfe 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h +++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h @@ -5,7 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_WORKER_THREAD_SCHEDULER_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_WORKER_THREAD_SCHEDULER_H_ -#include "base/macros.h" #include "base/single_thread_task_runner.h" #include "components/scheduling_metrics/task_duration_metric_reporter.h" #include "third_party/blink/renderer/platform/scheduler/common/idle_helper.h" @@ -31,7 +30,6 @@ namespace scheduler { class WorkerScheduler; class WorkerSchedulerProxy; -class TaskQueueThrottler; class WakeUpBudgetPool; class CPUTimeBudgetPool; @@ -44,6 +42,8 @@ class PLATFORM_EXPORT WorkerThreadScheduler : public NonMainThreadSchedulerImpl, ThreadType thread_type, base::sequence_manager::SequenceManager* sequence_manager, WorkerSchedulerProxy* proxy); + WorkerThreadScheduler(const WorkerThreadScheduler&) = delete; + WorkerThreadScheduler& operator=(const WorkerThreadScheduler&) = delete; ~WorkerThreadScheduler() override; // WebThreadScheduler implementation: @@ -89,14 +89,11 @@ class PLATFORM_EXPORT WorkerThreadScheduler : public NonMainThreadSchedulerImpl, // task queues. scoped_refptr<NonMainThreadTaskQueue> ControlTaskQueue(); - // TaskQueueThrottler might be null if throttling is not enabled or - // not supported. - TaskQueueThrottler* task_queue_throttler() const { - return task_queue_throttler_.get(); + WakeUpBudgetPool* wake_up_budget_pool() const { + return wake_up_budget_pool_.get(); } - WakeUpBudgetPool* wake_up_budget_pool() const { return wake_up_budget_pool_; } CPUTimeBudgetPool* cpu_time_budget_pool() const { - return cpu_time_budget_pool_; + return cpu_time_budget_pool_.get(); } protected: @@ -109,9 +106,10 @@ class PLATFORM_EXPORT WorkerThreadScheduler : public NonMainThreadSchedulerImpl, void OnIdlePeriodEnded() override {} void OnPendingTasksChanged(bool new_state) override {} - void CreateTaskQueueThrottler(); + void CreateBudgetPools(); - void SetCPUTimeBudgetPoolForTesting(CPUTimeBudgetPool* cpu_time_budget_pool); + void SetCPUTimeBudgetPoolForTesting( + std::unique_ptr<CPUTimeBudgetPool> cpu_time_budget_pool); HashSet<WorkerScheduler*>& GetWorkerSchedulersForTesting(); @@ -145,18 +143,14 @@ class PLATFORM_EXPORT WorkerThreadScheduler : public NonMainThreadSchedulerImpl, // Worker schedulers associated with this thread. HashSet<WorkerScheduler*> worker_schedulers_; - std::unique_ptr<TaskQueueThrottler> task_queue_throttler_; - // Owned by |task_queue_throttler_|. - WakeUpBudgetPool* wake_up_budget_pool_ = nullptr; - CPUTimeBudgetPool* cpu_time_budget_pool_ = nullptr; + std::unique_ptr<WakeUpBudgetPool> wake_up_budget_pool_; + std::unique_ptr<CPUTimeBudgetPool> cpu_time_budget_pool_; // The status of the parent frame when the worker was created. const FrameStatus initial_frame_status_; const ukm::SourceId ukm_source_id_; std::unique_ptr<ukm::UkmRecorder> ukm_recorder_; - - DISALLOW_COPY_AND_ASSIGN(WorkerThreadScheduler); }; } // namespace scheduler diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc index 2f9f37b427a..decca008b05 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc @@ -6,7 +6,6 @@ #include "base/bind.h" #include "base/callback.h" -#include "base/macros.h" #include "base/single_thread_task_runner.h" #include "base/task/sequence_manager/test/fake_task.h" #include "base/task/sequence_manager/test/sequence_manager_for_test.h" @@ -158,6 +157,9 @@ class WorkerThreadSchedulerTest : public testing::Test { idle_task_runner_ = scheduler_->IdleTaskRunner(); } + WorkerThreadSchedulerTest(const WorkerThreadSchedulerTest&) = delete; + WorkerThreadSchedulerTest& operator=(const WorkerThreadSchedulerTest&) = + delete; ~WorkerThreadSchedulerTest() override = default; void TearDown() override { @@ -219,8 +221,6 @@ class WorkerThreadSchedulerTest : public testing::Test { scoped_refptr<base::sequence_manager::TaskQueue> default_task_queue_; scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_; scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_; - - DISALLOW_COPY_AND_ASSIGN(WorkerThreadSchedulerTest); }; } // namespace @@ -509,6 +509,10 @@ class WorkerThreadSchedulerWithProxyTest : public testing::Test { scheduler_->AttachToCurrentThread(); } + WorkerThreadSchedulerWithProxyTest( + const WorkerThreadSchedulerWithProxyTest&) = delete; + WorkerThreadSchedulerWithProxyTest& operator=( + const WorkerThreadSchedulerWithProxyTest&) = delete; ~WorkerThreadSchedulerWithProxyTest() override = default; void TearDown() override { @@ -526,8 +530,6 @@ class WorkerThreadSchedulerWithProxyTest : public testing::Test { std::unique_ptr<WorkerThreadSchedulerForTest> scheduler_; scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_; scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_; - - DISALLOW_COPY_AND_ASSIGN(WorkerThreadSchedulerWithProxyTest); }; TEST_F(WorkerThreadSchedulerWithProxyTest, UkmTaskRecording) { diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_unittest.cc index af4e41dd2a1..a320a2f42d7 100644 --- a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_unittest.cc +++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_unittest.cc @@ -6,7 +6,6 @@ #include "base/bind.h" #include "base/location.h" -#include "base/macros.h" #include "base/synchronization/waitable_event.h" #include "base/task/task_executor.h" #include "testing/gmock/include/gmock/gmock.h" @@ -72,6 +71,8 @@ void ShutdownOnThread(Thread* thread) { class WorkerThreadTest : public testing::Test { public: WorkerThreadTest() = default; + WorkerThreadTest(const WorkerThreadTest&) = delete; + WorkerThreadTest& operator=(const WorkerThreadTest&) = delete; ~WorkerThreadTest() override = default; @@ -100,8 +101,6 @@ class WorkerThreadTest : public testing::Test { } std::unique_ptr<Thread> thread_; - - DISALLOW_COPY_AND_ASSIGN(WorkerThreadTest); }; TEST_F(WorkerThreadTest, TestDefaultTask) { |