| Index: components/scheduler/base/task_queue_selector.cc
|
| diff --git a/components/scheduler/base/task_queue_selector.cc b/components/scheduler/base/task_queue_selector.cc
|
| index c72c33a3629652e2702dc6286f19c96d9d305272..6f9f06159ee135c6038b214d3f8896bf85ce6368 100644
|
| --- a/components/scheduler/base/task_queue_selector.cc
|
| +++ b/components/scheduler/base/task_queue_selector.cc
|
| @@ -15,8 +15,8 @@ namespace internal {
|
| TaskQueueSelector::TaskQueueSelector()
|
| : delayed_work_queue_sets_(TaskQueue::QUEUE_PRIORITY_COUNT),
|
| immediate_work_queue_sets_(TaskQueue::QUEUE_PRIORITY_COUNT),
|
| - force_select_immediate_(true),
|
| - starvation_count_(0),
|
| + immediate_starvation_count_(0),
|
| + high_priority_starvation_count_(0),
|
| task_queue_selector_observer_(nullptr) {}
|
|
|
| TaskQueueSelector::~TaskQueueSelector() {}
|
| @@ -81,6 +81,7 @@ bool TaskQueueSelector::ChooseOldestDelayedTaskWithPriority(
|
|
|
| bool TaskQueueSelector::ChooseOldestImmediateOrDelayedTaskWithPriority(
|
| TaskQueue::QueuePriority priority,
|
| + bool* out_chose_delayed_over_immediate,
|
| WorkQueue** out_work_queue) const {
|
| WorkQueue* immediate_queue;
|
| if (immediate_work_queue_sets_.GetOldestQueueInSet(priority,
|
| @@ -99,6 +100,7 @@ bool TaskQueueSelector::ChooseOldestImmediateOrDelayedTaskWithPriority(
|
| if (immediate_enqueue_order < delayed_enqueue_order) {
|
| *out_work_queue = immediate_queue;
|
| } else {
|
| + *out_chose_delayed_over_immediate = true;
|
| *out_work_queue = delayed_queue;
|
| }
|
| } else {
|
| @@ -117,8 +119,10 @@ bool TaskQueueSelector::ChooseOldestImmediateOrDelayedTaskWithPriority(
|
|
|
| bool TaskQueueSelector::ChooseOldestWithPriority(
|
| TaskQueue::QueuePriority priority,
|
| + bool* out_chose_delayed_over_immediate,
|
| WorkQueue** out_work_queue) const {
|
| - if (force_select_immediate_) {
|
| + // Select an immediate work queue if we are starving immediate tasks.
|
| + if (immediate_starvation_count_ >= kMaxDelayedStarvationTasks) {
|
| if (ChooseOldestImmediateTaskWithPriority(priority, out_work_queue)) {
|
| return true;
|
| }
|
| @@ -127,31 +131,36 @@ bool TaskQueueSelector::ChooseOldestWithPriority(
|
| }
|
| return false;
|
| } else {
|
| - return ChooseOldestImmediateOrDelayedTaskWithPriority(priority,
|
| - out_work_queue);
|
| + return ChooseOldestImmediateOrDelayedTaskWithPriority(
|
| + priority, out_chose_delayed_over_immediate, out_work_queue);
|
| }
|
| }
|
|
|
| bool TaskQueueSelector::SelectWorkQueueToService(WorkQueue** out_work_queue) {
|
| DCHECK(main_thread_checker_.CalledOnValidThread());
|
| - force_select_immediate_ = !force_select_immediate_;
|
| + bool chose_delayed_over_immediate = false;
|
| // Always service the control queue if it has any work.
|
| - if (ChooseOldestWithPriority(TaskQueue::CONTROL_PRIORITY, out_work_queue)) {
|
| - DidSelectQueueWithPriority(TaskQueue::CONTROL_PRIORITY);
|
| + if (ChooseOldestWithPriority(TaskQueue::CONTROL_PRIORITY,
|
| + &chose_delayed_over_immediate, out_work_queue)) {
|
| + DidSelectQueueWithPriority(TaskQueue::CONTROL_PRIORITY,
|
| + chose_delayed_over_immediate);
|
| return true;
|
| }
|
| // Select from the normal priority queue if we are starving it.
|
| - if (starvation_count_ >= kMaxStarvationTasks &&
|
| - ChooseOldestWithPriority(TaskQueue::NORMAL_PRIORITY, out_work_queue)) {
|
| - DidSelectQueueWithPriority(TaskQueue::NORMAL_PRIORITY);
|
| + if (high_priority_starvation_count_ >= kMaxHighPriorityStarvationTasks &&
|
| + ChooseOldestWithPriority(TaskQueue::NORMAL_PRIORITY,
|
| + &chose_delayed_over_immediate, out_work_queue)) {
|
| + DidSelectQueueWithPriority(TaskQueue::NORMAL_PRIORITY,
|
| + chose_delayed_over_immediate);
|
| return true;
|
| }
|
| // Otherwise choose in priority order.
|
| for (TaskQueue::QueuePriority priority = TaskQueue::HIGH_PRIORITY;
|
| priority < TaskQueue::DISABLED_PRIORITY;
|
| priority = NextPriority(priority)) {
|
| - if (ChooseOldestWithPriority(priority, out_work_queue)) {
|
| - DidSelectQueueWithPriority(priority);
|
| + if (ChooseOldestWithPriority(priority, &chose_delayed_over_immediate,
|
| + out_work_queue)) {
|
| + DidSelectQueueWithPriority(priority, chose_delayed_over_immediate);
|
| return true;
|
| }
|
| }
|
| @@ -159,27 +168,34 @@ bool TaskQueueSelector::SelectWorkQueueToService(WorkQueue** out_work_queue) {
|
| }
|
|
|
| void TaskQueueSelector::DidSelectQueueWithPriority(
|
| - TaskQueue::QueuePriority priority) {
|
| + TaskQueue::QueuePriority priority,
|
| + bool chose_delayed_over_immediate) {
|
| switch (priority) {
|
| case TaskQueue::CONTROL_PRIORITY:
|
| break;
|
| case TaskQueue::HIGH_PRIORITY:
|
| - starvation_count_++;
|
| + high_priority_starvation_count_++;
|
| break;
|
| case TaskQueue::NORMAL_PRIORITY:
|
| case TaskQueue::BEST_EFFORT_PRIORITY:
|
| - starvation_count_ = 0;
|
| + high_priority_starvation_count_ = 0;
|
| break;
|
| default:
|
| NOTREACHED();
|
| }
|
| + if (chose_delayed_over_immediate) {
|
| + immediate_starvation_count_++;
|
| + } else {
|
| + immediate_starvation_count_ = 0;
|
| + }
|
| }
|
|
|
| void TaskQueueSelector::AsValueInto(
|
| base::trace_event::TracedValue* state) const {
|
| DCHECK(main_thread_checker_.CalledOnValidThread());
|
| - state->SetInteger("starvation_count", starvation_count_);
|
| - state->SetBoolean("try_delayed_first", force_select_immediate_);
|
| + state->SetInteger("high_priority_starvation_count",
|
| + high_priority_starvation_count_);
|
| + state->SetInteger("immediate_starvation_count", immediate_starvation_count_);
|
| }
|
|
|
| void TaskQueueSelector::SetTaskQueueSelectorObserver(Observer* observer) {
|
| @@ -198,9 +214,9 @@ bool TaskQueueSelector::EnabledWorkQueuesEmpty() const {
|
| return true;
|
| }
|
|
|
| -void TaskQueueSelector::SetForceSelectImmediateForTest(
|
| - bool force_select_immediate) {
|
| - force_select_immediate_ = force_select_immediate;
|
| +void TaskQueueSelector::SetImmediateStarvationCountForTest(
|
| + size_t immediate_starvation_count) {
|
| + immediate_starvation_count_ = immediate_starvation_count;
|
| }
|
|
|
| } // namespace internal
|
|
|