Commit f160a626 authored by kdillon's avatar kdillon Committed by Commit Bot

[scheduling] Removing QueueClass.

QueueClass is currently used for high-level policy decisions in the
main thread. For the most part, the policies applied to each queue
class are largely the same. This change removes QueueClass entirely
and adds bits on the policy for pausing and deferring task queues as
well as whether or not virtual time is enabled.


Change-Id: Iae28c5d7d2ad4c9deb7dad2e1c3294e7ac6b9470
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2365315
Commit-Queue: Katie Dillon <kdillon@chromium.org>
Reviewed-by: default avatarScott Haseley <shaseley@chromium.org>
Reviewed-by: default avatarAlexander Timin <altimin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#801591}
parent 8d8c65e7
......@@ -695,12 +695,10 @@ scoped_refptr<MainThreadTaskQueue> MainThreadSchedulerImpl::NewTaskQueue(
}
auto insert_result = task_runners_.emplace(task_queue, std::move(voter));
auto queue_class = task_queue->queue_class();
UpdateTaskQueueState(
task_queue.get(), insert_result.first->second.get(), TaskQueuePolicy(),
main_thread_only().current_policy.GetQueuePolicy(queue_class),
/*should_update_priority=*/true);
UpdateTaskQueueState(task_queue.get(), insert_result.first->second.get(),
Policy(), main_thread_only().current_policy,
/*should_update_priority=*/true);
// If this is a timer queue, and virtual time is enabled and paused, it should
// be suspended by adding a fence to prevent immediate tasks from running when
......@@ -718,8 +716,8 @@ scoped_refptr<MainThreadTaskQueue> MainThreadSchedulerImpl::NewTaskQueue(
scoped_refptr<MainThreadTaskQueue> MainThreadSchedulerImpl::NewLoadingTaskQueue(
MainThreadTaskQueue::QueueType queue_type,
FrameSchedulerImpl* frame_scheduler) {
DCHECK_EQ(MainThreadTaskQueue::QueueClassForQueueType(queue_type),
MainThreadTaskQueue::QueueClass::kLoading);
DCHECK(queue_type == MainThreadTaskQueue::QueueType::kFrameLoading ||
queue_type == MainThreadTaskQueue::QueueType::kFrameLoadingControl);
return NewTaskQueue(MainThreadTaskQueue::QueueCreationParams(queue_type)
.SetCanBePaused(true)
.SetCanBeFrozen(true)
......@@ -1454,8 +1452,7 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
case UseCase::kTouchstart:
new_policy.rail_mode() = RAILMode::kResponse;
new_policy.loading_queue_policy().is_deferred = true;
new_policy.default_queue_policy().is_deferred = true;
new_policy.should_defer_task_queues() = true;
break;
case UseCase::kNone:
......@@ -1484,18 +1481,13 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
if (main_thread_only().renderer_hidden)
new_policy.rail_mode() = RAILMode::kIdle;
if (main_thread_only().renderer_pause_count != 0) {
new_policy.loading_queue_policy().is_paused = true;
new_policy.default_queue_policy().is_paused = true;
}
if (main_thread_only().pause_timers_for_webview) {
new_policy.default_queue_policy().is_paused = true;
if (main_thread_only().renderer_pause_count != 0 ||
main_thread_only().pause_timers_for_webview) {
new_policy.should_pause_task_queues() = true;
}
if (main_thread_only().use_virtual_time) {
new_policy.compositor_queue_policy().use_virtual_time = true;
new_policy.default_queue_policy().use_virtual_time = true;
new_policy.loading_queue_policy().use_virtual_time = true;
new_policy.use_virtual_time() = true;
}
if (scheduling_settings_
......@@ -1566,12 +1558,8 @@ void MainThreadSchedulerImpl::UpdateStateForAllTaskQueues(
!previous_policy.has_value() ||
ShouldUpdateTaskQueuePriorities(previous_policy.value());
for (const auto& pair : task_runners_) {
MainThreadTaskQueue::QueueClass queue_class = pair.first->queue_class();
UpdateTaskQueueState(pair.first.get(), pair.second.get(),
old_policy.GetQueuePolicy(queue_class),
current_policy.GetQueuePolicy(queue_class),
should_update_priorities);
UpdateTaskQueueState(pair.first.get(), pair.second.get(), old_policy,
current_policy, should_update_priorities);
}
compositor_task_queue_enabled_voter_->SetVoteToEnable(
!current_policy.should_freeze_compositor_task_queue());
......@@ -1580,31 +1568,25 @@ void MainThreadSchedulerImpl::UpdateStateForAllTaskQueues(
void MainThreadSchedulerImpl::UpdateTaskQueueState(
MainThreadTaskQueue* task_queue,
TaskQueue::QueueEnabledVoter* task_queue_enabled_voter,
const TaskQueuePolicy& old_task_queue_policy,
const TaskQueuePolicy& new_task_queue_policy,
const Policy& old_policy,
const Policy& new_policy,
bool should_update_priority) const {
if (should_update_priority)
task_queue->SetQueuePriority(ComputePriority(task_queue));
DCHECK(old_task_queue_policy.IsQueueEnabled(task_queue) ||
task_queue_enabled_voter);
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_task_queue_policy.IsQueueEnabled(task_queue));
is_enabled_for_agent && new_policy.IsQueueEnabled(task_queue));
}
// Make sure if there's no voter that the task queue is enabled.
DCHECK(task_queue_enabled_voter ||
old_task_queue_policy.IsQueueEnabled(task_queue));
DCHECK(task_queue_enabled_voter || old_policy.IsQueueEnabled(task_queue));
TimeDomainType old_time_domain_type =
old_task_queue_policy.GetTimeDomainType(task_queue);
TimeDomainType new_time_domain_type =
new_task_queue_policy.GetTimeDomainType(task_queue);
TimeDomainType old_time_domain_type = old_policy.GetTimeDomainType();
TimeDomainType new_time_domain_type = new_policy.GetTimeDomainType();
if (old_time_domain_type != new_time_domain_type) {
if (new_time_domain_type == TimeDomainType::kVirtual) {
......@@ -2046,33 +2028,22 @@ void MainThreadSchedulerImpl::AsValueIntoLocked(
state->EndDictionary();
}
bool MainThreadSchedulerImpl::TaskQueuePolicy::IsQueueEnabled(
bool MainThreadSchedulerImpl::Policy::IsQueueEnabled(
MainThreadTaskQueue* task_queue) const {
if (!is_enabled)
if (should_pause_task_queues() && task_queue->CanBePaused())
return false;
if (is_paused && task_queue->CanBePaused())
return false;
if (is_deferred && task_queue->CanBeDeferred())
if (should_defer_task_queues() && task_queue->CanBeDeferred())
return false;
return true;
}
MainThreadSchedulerImpl::TimeDomainType
MainThreadSchedulerImpl::TaskQueuePolicy::GetTimeDomainType(
MainThreadTaskQueue* task_queue) const {
if (use_virtual_time)
MainThreadSchedulerImpl::Policy::GetTimeDomainType() const {
if (use_virtual_time())
return TimeDomainType::kVirtual;
return TimeDomainType::kReal;
}
void MainThreadSchedulerImpl::TaskQueuePolicy::AsValueInto(
base::trace_event::TracedValue* state) const {
state->SetBoolean("is_enabled", is_enabled);
state->SetBoolean("is_paused", is_paused);
state->SetBoolean("is_deferred", is_deferred);
state->SetBoolean("use_virtual_time", use_virtual_time);
}
MainThreadSchedulerImpl::Policy::Policy()
: rail_mode_(RAILMode::kAnimation),
should_disable_throttling_(false),
......@@ -2086,24 +2057,14 @@ MainThreadSchedulerImpl::Policy::Policy()
void MainThreadSchedulerImpl::Policy::AsValueInto(
base::trace_event::TracedValue* state) const {
state->BeginDictionary("compositor_queue_policy");
compositor_queue_policy().AsValueInto(state);
state->EndDictionary();
state->BeginDictionary("loading_queue_policy");
loading_queue_policy().AsValueInto(state);
state->EndDictionary();
state->BeginDictionary("default_queue_policy");
default_queue_policy().AsValueInto(state);
state->EndDictionary();
state->SetString("rail_mode", RAILModeToString(rail_mode()));
state->SetString("compositor_priority",
TaskQueue::PriorityToString(compositor_priority()));
state->SetString("use_case", UseCaseToString(use_case()));
state->SetBoolean("should_disable_throttling", should_disable_throttling());
state->SetBoolean("should_defer_task_queues", should_defer_task_queues());
state->SetBoolean("should_pause_task_queues", should_pause_task_queues());
state->SetBoolean("use_virtual_time", use_virtual_time());
}
void MainThreadSchedulerImpl::OnIdlePeriodStarted() {
......
......@@ -474,33 +474,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
bool IsAnyMainFrameWaitingForFirstContentfulPaint() const;
bool IsAnyMainFrameWaitingForFirstMeaningfulPaint() const;
struct TaskQueuePolicy {
// Default constructor of TaskQueuePolicy should match behaviour of a
// newly-created task queue.
TaskQueuePolicy()
: is_enabled(true),
is_paused(false),
is_deferred(false),
use_virtual_time(false) {}
bool is_enabled;
bool is_paused;
bool is_deferred;
bool use_virtual_time;
bool IsQueueEnabled(MainThreadTaskQueue* task_queue) const;
TimeDomainType GetTimeDomainType(MainThreadTaskQueue* task_queue) const;
bool operator==(const TaskQueuePolicy& other) const {
return is_enabled == other.is_enabled && is_paused == other.is_paused &&
is_deferred == other.is_deferred &&
use_virtual_time == other.use_virtual_time;
}
void AsValueInto(base::trace_event::TracedValue* state) const;
};
class Policy {
DISALLOW_NEW();
......@@ -508,38 +481,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
Policy();
~Policy() = default;
TaskQueuePolicy& compositor_queue_policy() {
return policies_[static_cast<size_t>(
MainThreadTaskQueue::QueueClass::kCompositor)];
}
const TaskQueuePolicy& compositor_queue_policy() const {
return policies_[static_cast<size_t>(
MainThreadTaskQueue::QueueClass::kCompositor)];
}
TaskQueuePolicy& loading_queue_policy() {
return policies_[static_cast<size_t>(
MainThreadTaskQueue::QueueClass::kLoading)];
}
const TaskQueuePolicy& loading_queue_policy() const {
return policies_[static_cast<size_t>(
MainThreadTaskQueue::QueueClass::kLoading)];
}
TaskQueuePolicy& default_queue_policy() {
return policies_[static_cast<size_t>(
MainThreadTaskQueue::QueueClass::kNone)];
}
const TaskQueuePolicy& default_queue_policy() const {
return policies_[static_cast<size_t>(
MainThreadTaskQueue::QueueClass::kNone)];
}
const TaskQueuePolicy& GetQueuePolicy(
MainThreadTaskQueue::QueueClass queue_class) const {
return policies_[static_cast<size_t>(queue_class)];
}
RAILMode& rail_mode() { return rail_mode_; }
RAILMode rail_mode() const { return rail_mode_; }
......@@ -565,6 +506,15 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
return should_freeze_compositor_task_queue_;
}
bool& should_defer_task_queues() { return should_defer_task_queues_; }
bool should_defer_task_queues() const { return should_defer_task_queues_; }
bool& should_pause_task_queues() { return should_pause_task_queues_; }
bool should_pause_task_queues() const { return should_pause_task_queues_; }
bool& use_virtual_time() { return use_virtual_time_; }
bool use_virtual_time() const { return use_virtual_time_; }
base::sequence_manager::TaskQueue::QueuePriority& compositor_priority() {
return compositor_priority_;
}
......@@ -585,13 +535,16 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
UseCase use_case() const { return use_case_; }
bool operator==(const Policy& other) const {
return policies_ == other.policies_ && rail_mode_ == other.rail_mode_ &&
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_ &&
should_freeze_compositor_task_queue_ ==
other.should_freeze_compositor_task_queue_ &&
should_defer_task_queues_ == other.should_defer_task_queues_ &&
should_pause_task_queues_ == other.should_pause_task_queues_ &&
use_virtual_time_ == other.use_virtual_time_ &&
compositor_priority_ == other.compositor_priority_ &&
find_in_page_priority_ == other.find_in_page_priority_ &&
use_case_ == other.use_case_;
......@@ -599,12 +552,19 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
void AsValueInto(base::trace_event::TracedValue* state) const;
bool IsQueueEnabled(MainThreadTaskQueue* task_queue) const;
TimeDomainType GetTimeDomainType() const;
private:
RAILMode rail_mode_;
bool should_disable_throttling_;
bool frozen_when_backgrounded_;
bool should_prioritize_loading_with_compositing_;
bool should_freeze_compositor_task_queue_{false};
bool should_defer_task_queues_{false};
bool should_pause_task_queues_{false};
bool use_virtual_time_{false};
// Priority of task queues belonging to the compositor class (Check
// MainThread::QueueClass).
......@@ -613,10 +573,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
base::sequence_manager::TaskQueue::QueuePriority find_in_page_priority_;
UseCase use_case_;
std::array<TaskQueuePolicy,
static_cast<size_t>(MainThreadTaskQueue::QueueClass::kCount)>
policies_;
};
class TaskDurationMetricTracker;
......@@ -741,8 +697,8 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
MainThreadTaskQueue* task_queue,
base::sequence_manager::TaskQueue::QueueEnabledVoter*
task_queue_enabled_voter,
const TaskQueuePolicy& old_task_queue_policy,
const TaskQueuePolicy& new_task_queue_policy,
const Policy& old_policy,
const Policy& new_policy,
bool should_update_priority) const;
void PauseRendererImpl();
......
......@@ -3379,12 +3379,12 @@ TEST_F(MainThreadSchedulerImplTest, PauseTimersForAndroidWebView) {
scheduler_->PauseTimersForAndroidWebView();
EnableIdleTasks();
test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_THAT(run_order, testing::ElementsAre("D1", "C1", "L1", "I1"));
EXPECT_THAT(run_order, testing::ElementsAre("D1", "C1", "I1"));
// The rest queued tasks fire when the throttleable queues are resumed.
run_order.clear();
scheduler_->ResumeTimersForAndroidWebView();
test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_THAT(run_order, testing::ElementsAre("T1"));
EXPECT_THAT(run_order, testing::ElementsAre("L1", "T1"));
}
#endif // defined(OS_ANDROID)
......
......@@ -100,37 +100,6 @@ bool MainThreadTaskQueue::IsPerFrameTaskQueue(
return false;
}
MainThreadTaskQueue::QueueClass MainThreadTaskQueue::QueueClassForQueueType(
QueueType type) {
switch (type) {
case QueueType::kControl:
case QueueType::kDefault:
case QueueType::kIdle:
case QueueType::kTest:
case QueueType::kV8:
case QueueType::kNonWaking:
case QueueType::kFrameThrottleable:
case QueueType::kFrameDeferrable:
case QueueType::kFramePausable:
case QueueType::kFrameUnpausable:
case QueueType::kWebScheduling:
return QueueClass::kNone;
case QueueType::kFrameLoading:
case QueueType::kFrameLoadingControl:
return QueueClass::kLoading;
case QueueType::kCompositor:
case QueueType::kInput:
return QueueClass::kCompositor;
case QueueType::kDetached:
case QueueType::kOther:
case QueueType::kCount:
DCHECK(false);
return QueueClass::kCount;
}
NOTREACHED();
return QueueClass::kNone;
}
MainThreadTaskQueue::MainThreadTaskQueue(
std::unique_ptr<internal::TaskQueueImpl> impl,
const TaskQueue::Spec& spec,
......@@ -138,7 +107,6 @@ MainThreadTaskQueue::MainThreadTaskQueue(
MainThreadSchedulerImpl* main_thread_scheduler)
: TaskQueue(std::move(impl), spec),
queue_type_(params.queue_type),
queue_class_(QueueClassForQueueType(params.queue_type)),
fixed_priority_(params.fixed_priority),
queue_traits_(params.queue_traits),
freeze_when_keep_active_(params.freeze_when_keep_active),
......
......@@ -92,18 +92,6 @@ class PLATFORM_EXPORT MainThreadTaskQueue
// the entire main thread.
static bool IsPerFrameTaskQueue(QueueType);
// High-level category used by MainThreadScheduler to make scheduling
// decisions.
enum class QueueClass {
kNone = 0,
kLoading = 1,
kCompositor = 4,
kCount = 5,
};
static QueueClass QueueClassForQueueType(QueueType type);
using QueueTraitsKeyType = int;
// QueueTraits represent the deferrable, throttleable, pausable, and freezable
......@@ -338,8 +326,6 @@ class PLATFORM_EXPORT MainThreadTaskQueue
QueueType queue_type() const { return queue_type_; }
QueueClass queue_class() const { return queue_class_; }
base::Optional<base::sequence_manager::TaskQueue::QueuePriority>
FixedPriority() const {
return fixed_priority_;
......@@ -431,7 +417,6 @@ class PLATFORM_EXPORT MainThreadTaskQueue
void ClearReferencesToSchedulers();
const QueueType queue_type_;
const QueueClass queue_class_;
const base::Optional<base::sequence_manager::TaskQueue::QueuePriority>
fixed_priority_;
const QueueTraits queue_traits_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment