Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(296)

Side by Side Diff: components/scheduler/base/task_queue_selector.cc

Issue 1507093004: Adopt a less severe anti-starvation policy for immediate tasks (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix test flakes Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/scheduler/base/task_queue_selector.h" 5 #include "components/scheduler/base/task_queue_selector.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/trace_event/trace_event_argument.h" 8 #include "base/trace_event/trace_event_argument.h"
9 #include "components/scheduler/base/task_queue_impl.h" 9 #include "components/scheduler/base/task_queue_impl.h"
10 #include "components/scheduler/base/work_queue.h" 10 #include "components/scheduler/base/work_queue.h"
11 11
12 namespace scheduler { 12 namespace scheduler {
13 namespace internal { 13 namespace internal {
14 14
15 TaskQueueSelector::TaskQueueSelector() 15 TaskQueueSelector::TaskQueueSelector()
16 : delayed_work_queue_sets_(TaskQueue::QUEUE_PRIORITY_COUNT), 16 : delayed_work_queue_sets_(TaskQueue::QUEUE_PRIORITY_COUNT),
17 immediate_work_queue_sets_(TaskQueue::QUEUE_PRIORITY_COUNT), 17 immediate_work_queue_sets_(TaskQueue::QUEUE_PRIORITY_COUNT),
18 force_select_immediate_(true), 18 immediate_starvation_count_(0),
19 starvation_count_(0), 19 high_priority_starvation_count_(0),
20 task_queue_selector_observer_(nullptr) {} 20 task_queue_selector_observer_(nullptr) {}
21 21
22 TaskQueueSelector::~TaskQueueSelector() {} 22 TaskQueueSelector::~TaskQueueSelector() {}
23 23
24 void TaskQueueSelector::AddQueue(internal::TaskQueueImpl* queue) { 24 void TaskQueueSelector::AddQueue(internal::TaskQueueImpl* queue) {
25 DCHECK(main_thread_checker_.CalledOnValidThread()); 25 DCHECK(main_thread_checker_.CalledOnValidThread());
26 delayed_work_queue_sets_.AssignQueueToSet(queue->delayed_work_queue(), 26 delayed_work_queue_sets_.AssignQueueToSet(queue->delayed_work_queue(),
27 TaskQueue::NORMAL_PRIORITY); 27 TaskQueue::NORMAL_PRIORITY);
28 immediate_work_queue_sets_.AssignQueueToSet(queue->immediate_work_queue(), 28 immediate_work_queue_sets_.AssignQueueToSet(queue->immediate_work_queue(),
29 TaskQueue::NORMAL_PRIORITY); 29 TaskQueue::NORMAL_PRIORITY);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 } 74 }
75 75
76 bool TaskQueueSelector::ChooseOldestDelayedTaskWithPriority( 76 bool TaskQueueSelector::ChooseOldestDelayedTaskWithPriority(
77 TaskQueue::QueuePriority priority, 77 TaskQueue::QueuePriority priority,
78 WorkQueue** out_work_queue) const { 78 WorkQueue** out_work_queue) const {
79 return delayed_work_queue_sets_.GetOldestQueueInSet(priority, out_work_queue); 79 return delayed_work_queue_sets_.GetOldestQueueInSet(priority, out_work_queue);
80 } 80 }
81 81
82 bool TaskQueueSelector::ChooseOldestImmediateOrDelayedTaskWithPriority( 82 bool TaskQueueSelector::ChooseOldestImmediateOrDelayedTaskWithPriority(
83 TaskQueue::QueuePriority priority, 83 TaskQueue::QueuePriority priority,
84 bool* out_chose_delayed_over_immediate,
84 WorkQueue** out_work_queue) const { 85 WorkQueue** out_work_queue) const {
85 WorkQueue* immediate_queue; 86 WorkQueue* immediate_queue;
86 if (immediate_work_queue_sets_.GetOldestQueueInSet(priority, 87 if (immediate_work_queue_sets_.GetOldestQueueInSet(priority,
87 &immediate_queue)) { 88 &immediate_queue)) {
88 WorkQueue* delayed_queue; 89 WorkQueue* delayed_queue;
89 if (delayed_work_queue_sets_.GetOldestQueueInSet(priority, 90 if (delayed_work_queue_sets_.GetOldestQueueInSet(priority,
90 &delayed_queue)) { 91 &delayed_queue)) {
91 int immediate_enqueue_order; 92 int immediate_enqueue_order;
92 int delayed_enqueue_order; 93 int delayed_enqueue_order;
93 bool have_immediate_task = 94 bool have_immediate_task =
94 immediate_queue->GetFrontTaskEnqueueOrder(&immediate_enqueue_order); 95 immediate_queue->GetFrontTaskEnqueueOrder(&immediate_enqueue_order);
95 bool have_delayed_task = 96 bool have_delayed_task =
96 delayed_queue->GetFrontTaskEnqueueOrder(&delayed_enqueue_order); 97 delayed_queue->GetFrontTaskEnqueueOrder(&delayed_enqueue_order);
97 DCHECK(have_immediate_task); 98 DCHECK(have_immediate_task);
98 DCHECK(have_delayed_task); 99 DCHECK(have_delayed_task);
99 if (immediate_enqueue_order < delayed_enqueue_order) { 100 if (immediate_enqueue_order < delayed_enqueue_order) {
100 *out_work_queue = immediate_queue; 101 *out_work_queue = immediate_queue;
101 } else { 102 } else {
103 *out_chose_delayed_over_immediate = true;
102 *out_work_queue = delayed_queue; 104 *out_work_queue = delayed_queue;
103 } 105 }
104 } else { 106 } else {
105 *out_work_queue = immediate_queue; 107 *out_work_queue = immediate_queue;
106 } 108 }
107 return true; 109 return true;
108 } else { 110 } else {
109 if (delayed_work_queue_sets_.GetOldestQueueInSet(priority, 111 if (delayed_work_queue_sets_.GetOldestQueueInSet(priority,
110 out_work_queue)) { 112 out_work_queue)) {
111 return true; 113 return true;
112 } else { 114 } else {
113 return false; 115 return false;
114 } 116 }
115 } 117 }
116 } 118 }
117 119
118 bool TaskQueueSelector::ChooseOldestWithPriority( 120 bool TaskQueueSelector::ChooseOldestWithPriority(
119 TaskQueue::QueuePriority priority, 121 TaskQueue::QueuePriority priority,
122 bool* out_chose_delayed_over_immediate,
120 WorkQueue** out_work_queue) const { 123 WorkQueue** out_work_queue) const {
121 if (force_select_immediate_) { 124 // Select an immediate work queue if we are starving immediate tasks.
125 if (immediate_starvation_count_ >= kMaxDelayedStarvationTasks) {
122 if (ChooseOldestImmediateTaskWithPriority(priority, out_work_queue)) { 126 if (ChooseOldestImmediateTaskWithPriority(priority, out_work_queue)) {
123 return true; 127 return true;
124 } 128 }
125 if (ChooseOldestDelayedTaskWithPriority(priority, out_work_queue)) { 129 if (ChooseOldestDelayedTaskWithPriority(priority, out_work_queue)) {
126 return true; 130 return true;
127 } 131 }
128 return false; 132 return false;
129 } else { 133 } else {
130 return ChooseOldestImmediateOrDelayedTaskWithPriority(priority, 134 return ChooseOldestImmediateOrDelayedTaskWithPriority(
131 out_work_queue); 135 priority, out_chose_delayed_over_immediate, out_work_queue);
132 } 136 }
133 } 137 }
134 138
135 bool TaskQueueSelector::SelectWorkQueueToService(WorkQueue** out_work_queue) { 139 bool TaskQueueSelector::SelectWorkQueueToService(WorkQueue** out_work_queue) {
136 DCHECK(main_thread_checker_.CalledOnValidThread()); 140 DCHECK(main_thread_checker_.CalledOnValidThread());
137 force_select_immediate_ = !force_select_immediate_; 141 bool chose_delayed_over_immediate = false;
138 // Always service the control queue if it has any work. 142 // Always service the control queue if it has any work.
139 if (ChooseOldestWithPriority(TaskQueue::CONTROL_PRIORITY, out_work_queue)) { 143 if (ChooseOldestWithPriority(TaskQueue::CONTROL_PRIORITY,
140 DidSelectQueueWithPriority(TaskQueue::CONTROL_PRIORITY); 144 &chose_delayed_over_immediate, out_work_queue)) {
145 DidSelectQueueWithPriority(TaskQueue::CONTROL_PRIORITY,
146 chose_delayed_over_immediate);
141 return true; 147 return true;
142 } 148 }
143 // Select from the normal priority queue if we are starving it. 149 // Select from the normal priority queue if we are starving it.
144 if (starvation_count_ >= kMaxStarvationTasks && 150 if (high_priority_starvation_count_ >= kMaxHighPriorityStarvationTasks &&
145 ChooseOldestWithPriority(TaskQueue::NORMAL_PRIORITY, out_work_queue)) { 151 ChooseOldestWithPriority(TaskQueue::NORMAL_PRIORITY,
146 DidSelectQueueWithPriority(TaskQueue::NORMAL_PRIORITY); 152 &chose_delayed_over_immediate, out_work_queue)) {
153 DidSelectQueueWithPriority(TaskQueue::NORMAL_PRIORITY,
154 chose_delayed_over_immediate);
147 return true; 155 return true;
148 } 156 }
149 // Otherwise choose in priority order. 157 // Otherwise choose in priority order.
150 for (TaskQueue::QueuePriority priority = TaskQueue::HIGH_PRIORITY; 158 for (TaskQueue::QueuePriority priority = TaskQueue::HIGH_PRIORITY;
151 priority < TaskQueue::DISABLED_PRIORITY; 159 priority < TaskQueue::DISABLED_PRIORITY;
152 priority = NextPriority(priority)) { 160 priority = NextPriority(priority)) {
153 if (ChooseOldestWithPriority(priority, out_work_queue)) { 161 if (ChooseOldestWithPriority(priority, &chose_delayed_over_immediate,
154 DidSelectQueueWithPriority(priority); 162 out_work_queue)) {
163 DidSelectQueueWithPriority(priority, chose_delayed_over_immediate);
155 return true; 164 return true;
156 } 165 }
157 } 166 }
158 return false; 167 return false;
159 } 168 }
160 169
161 void TaskQueueSelector::DidSelectQueueWithPriority( 170 void TaskQueueSelector::DidSelectQueueWithPriority(
162 TaskQueue::QueuePriority priority) { 171 TaskQueue::QueuePriority priority,
172 bool chose_delayed_over_immediate) {
163 switch (priority) { 173 switch (priority) {
164 case TaskQueue::CONTROL_PRIORITY: 174 case TaskQueue::CONTROL_PRIORITY:
165 break; 175 break;
166 case TaskQueue::HIGH_PRIORITY: 176 case TaskQueue::HIGH_PRIORITY:
167 starvation_count_++; 177 high_priority_starvation_count_++;
168 break; 178 break;
169 case TaskQueue::NORMAL_PRIORITY: 179 case TaskQueue::NORMAL_PRIORITY:
170 case TaskQueue::BEST_EFFORT_PRIORITY: 180 case TaskQueue::BEST_EFFORT_PRIORITY:
171 starvation_count_ = 0; 181 high_priority_starvation_count_ = 0;
172 break; 182 break;
173 default: 183 default:
174 NOTREACHED(); 184 NOTREACHED();
175 } 185 }
186 if (chose_delayed_over_immediate) {
187 immediate_starvation_count_++;
188 } else {
189 immediate_starvation_count_ = 0;
190 }
176 } 191 }
177 192
178 void TaskQueueSelector::AsValueInto( 193 void TaskQueueSelector::AsValueInto(
179 base::trace_event::TracedValue* state) const { 194 base::trace_event::TracedValue* state) const {
180 DCHECK(main_thread_checker_.CalledOnValidThread()); 195 DCHECK(main_thread_checker_.CalledOnValidThread());
181 state->SetInteger("starvation_count", starvation_count_); 196 state->SetInteger("high_priority_starvation_count",
182 state->SetBoolean("try_delayed_first", force_select_immediate_); 197 high_priority_starvation_count_);
198 state->SetInteger("immediate_starvation_count", immediate_starvation_count_);
183 } 199 }
184 200
185 void TaskQueueSelector::SetTaskQueueSelectorObserver(Observer* observer) { 201 void TaskQueueSelector::SetTaskQueueSelectorObserver(Observer* observer) {
186 task_queue_selector_observer_ = observer; 202 task_queue_selector_observer_ = observer;
187 } 203 }
188 204
189 bool TaskQueueSelector::EnabledWorkQueuesEmpty() const { 205 bool TaskQueueSelector::EnabledWorkQueuesEmpty() const {
190 for (TaskQueue::QueuePriority priority = TaskQueue::HIGH_PRIORITY; 206 for (TaskQueue::QueuePriority priority = TaskQueue::HIGH_PRIORITY;
191 priority < TaskQueue::DISABLED_PRIORITY; 207 priority < TaskQueue::DISABLED_PRIORITY;
192 priority = NextPriority(priority)) { 208 priority = NextPriority(priority)) {
193 if (!delayed_work_queue_sets_.IsSetEmpty(priority) || 209 if (!delayed_work_queue_sets_.IsSetEmpty(priority) ||
194 !immediate_work_queue_sets_.IsSetEmpty(priority)) { 210 !immediate_work_queue_sets_.IsSetEmpty(priority)) {
195 return false; 211 return false;
196 } 212 }
197 } 213 }
198 return true; 214 return true;
199 } 215 }
200 216
201 void TaskQueueSelector::SetForceSelectImmediateForTest( 217 void TaskQueueSelector::SetImmediateStarvationCountForTest(
202 bool force_select_immediate) { 218 size_t immediate_starvation_count) {
203 force_select_immediate_ = force_select_immediate; 219 immediate_starvation_count_ = immediate_starvation_count;
204 } 220 }
205 221
206 } // namespace internal 222 } // namespace internal
207 } // namespace scheduler 223 } // namespace scheduler
OLDNEW
« no previous file with comments | « components/scheduler/base/task_queue_selector.h ('k') | components/scheduler/base/task_queue_selector_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698