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

Side by Side Diff: components/scheduler/child/idle_helper.cc

Issue 1151353003: [scheduler]: Avoid waking up the scheduler to end long idle periods. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@end_idle_sync_2
Patch Set: Fix Win for realz hopefully... Created 5 years, 6 months 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/child/idle_helper.h" 5 #include "components/scheduler/child/idle_helper.h"
6 6
7 #include "base/time/time.h"
7 #include "base/trace_event/trace_event.h" 8 #include "base/trace_event/trace_event.h"
8 #include "base/trace_event/trace_event_argument.h" 9 #include "base/trace_event/trace_event_argument.h"
9 #include "components/scheduler/child/scheduler_helper.h" 10 #include "components/scheduler/child/scheduler_helper.h"
10 11
11 namespace scheduler { 12 namespace scheduler {
12 13
13 IdleHelper::IdleHelper( 14 IdleHelper::IdleHelper(
14 SchedulerHelper* helper, 15 SchedulerHelper* helper,
15 Delegate* delegate, 16 Delegate* delegate,
16 size_t idle_queue_index, 17 size_t idle_queue_index,
17 const char* tracing_category, 18 const char* tracing_category,
18 const char* disabled_by_default_tracing_category, 19 const char* disabled_by_default_tracing_category,
19 const char* idle_period_tracing_name, 20 const char* idle_period_tracing_name,
20 base::TimeDelta required_quiescence_duration_before_long_idle_period) 21 base::TimeDelta required_quiescence_duration_before_long_idle_period)
21 : helper_(helper), 22 : helper_(helper),
22 delegate_(delegate), 23 delegate_(delegate),
23 idle_queue_index_(idle_queue_index), 24 idle_queue_index_(idle_queue_index),
24 idle_period_state_(IdlePeriodState::NOT_IN_IDLE_PERIOD), 25 state_(helper,
26 tracing_category,
27 disabled_by_default_tracing_category,
28 idle_period_tracing_name),
25 quiescence_monitored_task_queue_mask_( 29 quiescence_monitored_task_queue_mask_(
26 helper_->GetQuiescenceMonitoredTaskQueueMask() & 30 helper_->GetQuiescenceMonitoredTaskQueueMask() &
27 ~(1ull << idle_queue_index_)), 31 ~(1ull << idle_queue_index_)),
28 required_quiescence_duration_before_long_idle_period_( 32 required_quiescence_duration_before_long_idle_period_(
29 required_quiescence_duration_before_long_idle_period), 33 required_quiescence_duration_before_long_idle_period),
30 tracing_category_(tracing_category),
31 disabled_by_default_tracing_category_( 34 disabled_by_default_tracing_category_(
32 disabled_by_default_tracing_category), 35 disabled_by_default_tracing_category),
33 idle_period_tracing_name_(idle_period_tracing_name),
34 weak_factory_(this) { 36 weak_factory_(this) {
35 weak_idle_helper_ptr_ = weak_factory_.GetWeakPtr(); 37 weak_idle_helper_ptr_ = weak_factory_.GetWeakPtr();
36 end_idle_period_closure_.Reset(
37 base::Bind(&IdleHelper::EndIdlePeriod, weak_idle_helper_ptr_));
38 enable_next_long_idle_period_closure_.Reset( 38 enable_next_long_idle_period_closure_.Reset(
39 base::Bind(&IdleHelper::EnableLongIdlePeriod, weak_idle_helper_ptr_)); 39 base::Bind(&IdleHelper::EnableLongIdlePeriod, weak_idle_helper_ptr_));
40 enable_next_long_idle_period_after_wakeup_closure_.Reset(base::Bind( 40 on_idle_task_posted_closure_.Reset(base::Bind(
41 &IdleHelper::EnableLongIdlePeriodAfterWakeup, weak_idle_helper_ptr_)); 41 &IdleHelper::OnIdleTaskPostedOnMainThread, weak_idle_helper_ptr_));
42 42
43 idle_task_runner_ = make_scoped_refptr(new SingleThreadIdleTaskRunner( 43 idle_task_runner_ = make_scoped_refptr(new SingleThreadIdleTaskRunner(
44 helper_->TaskRunnerForQueue(idle_queue_index_), 44 helper_->TaskRunnerForQueue(idle_queue_index_),
45 helper_->ControlAfterWakeUpTaskRunner(), 45 helper_->ControlAfterWakeUpTaskRunner(), this, tracing_category));
46 base::Bind(&IdleHelper::CurrentIdleTaskDeadlineCallback,
47 weak_idle_helper_ptr_),
48 tracing_category));
49 46
50 helper_->DisableQueue(idle_queue_index_); 47 helper_->DisableQueue(idle_queue_index_);
51 helper_->SetPumpPolicy(idle_queue_index_, 48 helper_->SetPumpPolicy(idle_queue_index_,
52 TaskQueueManager::PumpPolicy::MANUAL); 49 TaskQueueManager::PumpPolicy::MANUAL);
50
51 helper_->AddTaskObserver(this);
53 } 52 }
54 53
55 IdleHelper::~IdleHelper() { 54 IdleHelper::~IdleHelper() {
55 helper_->RemoveTaskObserver(this);
56 } 56 }
57 57
58 IdleHelper::Delegate::Delegate() { 58 IdleHelper::Delegate::Delegate() {
59 } 59 }
60 60
61 IdleHelper::Delegate::~Delegate() { 61 IdleHelper::Delegate::~Delegate() {
62 } 62 }
63 63
64 scoped_refptr<SingleThreadIdleTaskRunner> IdleHelper::IdleTaskRunner() { 64 scoped_refptr<SingleThreadIdleTaskRunner> IdleHelper::IdleTaskRunner() {
65 helper_->CheckOnValidThread(); 65 helper_->CheckOnValidThread();
66 return idle_task_runner_; 66 return idle_task_runner_;
67 } 67 }
68 68
69 void IdleHelper::CurrentIdleTaskDeadlineCallback(
70 base::TimeTicks* deadline_out) const {
71 helper_->CheckOnValidThread();
72 *deadline_out = idle_period_deadline_;
73 }
74
75 IdleHelper::IdlePeriodState IdleHelper::ComputeNewLongIdlePeriodState( 69 IdleHelper::IdlePeriodState IdleHelper::ComputeNewLongIdlePeriodState(
76 const base::TimeTicks now, 70 const base::TimeTicks now,
77 base::TimeDelta* next_long_idle_period_delay_out) { 71 base::TimeDelta* next_long_idle_period_delay_out) {
78 helper_->CheckOnValidThread(); 72 helper_->CheckOnValidThread();
79 73
80 if (!delegate_->CanEnterLongIdlePeriod(now, 74 if (!delegate_->CanEnterLongIdlePeriod(now,
81 next_long_idle_period_delay_out)) { 75 next_long_idle_period_delay_out)) {
82 return IdlePeriodState::NOT_IN_IDLE_PERIOD; 76 return IdlePeriodState::NOT_IN_IDLE_PERIOD;
83 } 77 }
84 78
85 base::TimeTicks next_pending_delayed_task = 79 base::TimeTicks next_pending_delayed_task =
86 helper_->NextPendingDelayedTaskRunTime(); 80 helper_->NextPendingDelayedTaskRunTime();
87 base::TimeDelta max_long_idle_period_duration = 81 base::TimeDelta max_long_idle_period_duration =
88 base::TimeDelta::FromMilliseconds(kMaximumIdlePeriodMillis); 82 base::TimeDelta::FromMilliseconds(kMaximumIdlePeriodMillis);
89 base::TimeDelta long_idle_period_duration; 83 base::TimeDelta long_idle_period_duration;
90 if (next_pending_delayed_task.is_null()) { 84 if (next_pending_delayed_task.is_null()) {
91 long_idle_period_duration = max_long_idle_period_duration; 85 long_idle_period_duration = max_long_idle_period_duration;
92 } else { 86 } else {
93 // Limit the idle period duration to be before the next pending task. 87 // Limit the idle period duration to be before the next pending task.
94 long_idle_period_duration = std::min(next_pending_delayed_task - now, 88 long_idle_period_duration = std::min(next_pending_delayed_task - now,
95 max_long_idle_period_duration); 89 max_long_idle_period_duration);
96 } 90 }
97 91
98 if (long_idle_period_duration > base::TimeDelta()) { 92 if (long_idle_period_duration > base::TimeDelta()) {
99 *next_long_idle_period_delay_out = long_idle_period_duration; 93 *next_long_idle_period_delay_out = long_idle_period_duration;
100 return long_idle_period_duration == max_long_idle_period_duration 94 if (helper_->IsQueueEmpty(idle_queue_index_)) {
101 ? IdlePeriodState::IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE 95 return IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED;
102 : IdlePeriodState::IN_LONG_IDLE_PERIOD; 96 } else if (long_idle_period_duration == max_long_idle_period_duration) {
97 return IdlePeriodState::IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE;
98 } else {
99 return IdlePeriodState::IN_LONG_IDLE_PERIOD;
100 }
103 } else { 101 } else {
104 // If we can't start the idle period yet then try again after wakeup. 102 // If we can't start the idle period yet then try again after wakeup.
105 *next_long_idle_period_delay_out = base::TimeDelta::FromMilliseconds( 103 *next_long_idle_period_delay_out = base::TimeDelta::FromMilliseconds(
106 kRetryEnableLongIdlePeriodDelayMillis); 104 kRetryEnableLongIdlePeriodDelayMillis);
107 return IdlePeriodState::NOT_IN_IDLE_PERIOD; 105 return IdlePeriodState::NOT_IN_IDLE_PERIOD;
108 } 106 }
109 } 107 }
110 108
111 bool IdleHelper::ShouldWaitForQuiescence() { 109 bool IdleHelper::ShouldWaitForQuiescence() {
112 helper_->CheckOnValidThread(); 110 helper_->CheckOnValidThread();
(...skipping 14 matching lines...) Expand all
127 task_queues_run_since_last_check_bitmap); 125 task_queues_run_since_last_check_bitmap);
128 126
129 // If anything was run on the queues we care about, then we're not quiescent 127 // If anything was run on the queues we care about, then we're not quiescent
130 // and we should wait. 128 // and we should wait.
131 return task_queues_run_since_last_check_bitmap != 0; 129 return task_queues_run_since_last_check_bitmap != 0;
132 } 130 }
133 131
134 void IdleHelper::EnableLongIdlePeriod() { 132 void IdleHelper::EnableLongIdlePeriod() {
135 TRACE_EVENT0(disabled_by_default_tracing_category_, "EnableLongIdlePeriod"); 133 TRACE_EVENT0(disabled_by_default_tracing_category_, "EnableLongIdlePeriod");
136 helper_->CheckOnValidThread(); 134 helper_->CheckOnValidThread();
135 if (helper_->IsShutdown())
136 return;
137 137
138 // End any previous idle period. 138 // End any previous idle period.
139 EndIdlePeriod(); 139 EndIdlePeriod();
140 140
141 if (ShouldWaitForQuiescence()) { 141 if (ShouldWaitForQuiescence()) {
142 helper_->ControlTaskRunner()->PostDelayedTask( 142 helper_->ControlTaskRunner()->PostDelayedTask(
143 FROM_HERE, enable_next_long_idle_period_closure_.callback(), 143 FROM_HERE, enable_next_long_idle_period_closure_.callback(),
144 required_quiescence_duration_before_long_idle_period_); 144 required_quiescence_duration_before_long_idle_period_);
145 delegate_->IsNotQuiescent(); 145 delegate_->IsNotQuiescent();
146 return; 146 return;
147 } 147 }
148 148
149 base::TimeTicks now(helper_->Now()); 149 base::TimeTicks now(helper_->Now());
150 base::TimeDelta next_long_idle_period_delay; 150 base::TimeDelta next_long_idle_period_delay;
151 IdlePeriodState new_idle_period_state = 151 IdlePeriodState new_idle_period_state =
152 ComputeNewLongIdlePeriodState(now, &next_long_idle_period_delay); 152 ComputeNewLongIdlePeriodState(now, &next_long_idle_period_delay);
153 if (IsInIdlePeriod(new_idle_period_state)) { 153 if (IsInIdlePeriod(new_idle_period_state)) {
154 StartIdlePeriod(new_idle_period_state, now, 154 StartIdlePeriod(new_idle_period_state, now,
155 now + next_long_idle_period_delay, false); 155 now + next_long_idle_period_delay);
156 }
157
158 if (helper_->IsQueueEmpty(idle_queue_index_)) {
159 // If there are no current idle tasks then post the call to initiate the
160 // next idle for execution after wakeup (at which point after-wakeup idle
161 // tasks might be eligible to run or more idle tasks posted).
162 helper_->ControlAfterWakeUpTaskRunner()->PostDelayedTask(
163 FROM_HERE,
164 enable_next_long_idle_period_after_wakeup_closure_.callback(),
165 next_long_idle_period_delay);
166 } else { 156 } else {
167 // Otherwise post on the normal control task queue. 157 // Otherwise wait for the next long idle period delay before trying again.
168 helper_->ControlTaskRunner()->PostDelayedTask( 158 helper_->ControlTaskRunner()->PostDelayedTask(
169 FROM_HERE, enable_next_long_idle_period_closure_.callback(), 159 FROM_HERE, enable_next_long_idle_period_closure_.callback(),
170 next_long_idle_period_delay); 160 next_long_idle_period_delay);
171 } 161 }
172 } 162 }
173 163
174 void IdleHelper::EnableLongIdlePeriodAfterWakeup() {
175 TRACE_EVENT0(disabled_by_default_tracing_category_,
176 "EnableLongIdlePeriodAfterWakeup");
177 helper_->CheckOnValidThread();
178
179 if (IsInIdlePeriod(idle_period_state_)) {
180 // Since we were asleep until now, end the async idle period trace event at
181 // the time when it would have ended were we awake.
182 TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0(
183 tracing_category_, idle_period_tracing_name_, this,
184 std::min(idle_period_deadline_, helper_->Now()).ToInternalValue());
185 idle_period_state_ = IdlePeriodState::ENDING_LONG_IDLE_PERIOD;
186 EndIdlePeriod();
187 }
188
189 // Post a task to initiate the next long idle period rather than calling it
190 // directly to allow all pending PostIdleTaskAfterWakeup tasks to get enqueued
191 // on the idle task queue before the next idle period starts so they are
192 // eligible to be run during the new idle period.
193 helper_->ControlTaskRunner()->PostTask(
194 FROM_HERE, enable_next_long_idle_period_closure_.callback());
195 }
196
197 void IdleHelper::StartIdlePeriod(IdlePeriodState new_state, 164 void IdleHelper::StartIdlePeriod(IdlePeriodState new_state,
198 base::TimeTicks now, 165 base::TimeTicks now,
199 base::TimeTicks idle_period_deadline, 166 base::TimeTicks idle_period_deadline) {
200 bool post_end_idle_period) {
201 DCHECK_GT(idle_period_deadline, now); 167 DCHECK_GT(idle_period_deadline, now);
202 TRACE_EVENT_ASYNC_BEGIN0(tracing_category_, idle_period_tracing_name_, this);
203 helper_->CheckOnValidThread(); 168 helper_->CheckOnValidThread();
204 DCHECK(IsInIdlePeriod(new_state)); 169 DCHECK(IsInIdlePeriod(new_state));
170 TRACE_EVENT0(disabled_by_default_tracing_category_, "StartIdlePeriod");
205 171
206 helper_->EnableQueue(idle_queue_index_, 172 helper_->EnableQueue(idle_queue_index_,
207 PrioritizingTaskQueueSelector::BEST_EFFORT_PRIORITY); 173 PrioritizingTaskQueueSelector::BEST_EFFORT_PRIORITY);
208 helper_->PumpQueue(idle_queue_index_); 174 helper_->PumpQueue(idle_queue_index_);
209 idle_period_state_ = new_state;
210 175
211 idle_period_deadline_ = idle_period_deadline; 176 state_.UpdateState(new_state, idle_period_deadline, now);
212 if (post_end_idle_period) {
213 helper_->ControlTaskRunner()->PostDelayedTask(
214 FROM_HERE, end_idle_period_closure_.callback(),
215 idle_period_deadline_ - now);
216 }
217 } 177 }
218 178
219 void IdleHelper::EndIdlePeriod() { 179 void IdleHelper::EndIdlePeriod() {
220 helper_->CheckOnValidThread(); 180 helper_->CheckOnValidThread();
181 TRACE_EVENT0(disabled_by_default_tracing_category_, "EndIdlePeriod");
221 182
222 end_idle_period_closure_.Cancel();
223 enable_next_long_idle_period_closure_.Cancel(); 183 enable_next_long_idle_period_closure_.Cancel();
224 enable_next_long_idle_period_after_wakeup_closure_.Cancel(); 184 on_idle_task_posted_closure_.Cancel();
225 185
226 // If we weren't already within an idle period then early-out. 186 // If we weren't already within an idle period then early-out.
227 if (!IsInIdlePeriod(idle_period_state_)) 187 if (!IsInIdlePeriod(state_.idle_period_state()))
228 return; 188 return;
229 189
230 // If we are in the ENDING_LONG_IDLE_PERIOD state we have already logged the 190 helper_->DisableQueue(idle_queue_index_);
231 // trace event. 191 state_.UpdateState(IdlePeriodState::NOT_IN_IDLE_PERIOD, base::TimeTicks(),
232 if (idle_period_state_ != IdlePeriodState::ENDING_LONG_IDLE_PERIOD) { 192 base::TimeTicks());
233 bool is_tracing; 193 }
234 TRACE_EVENT_CATEGORY_GROUP_ENABLED(tracing_category_, &is_tracing); 194
235 if (is_tracing && !idle_period_deadline_.is_null() && 195 void IdleHelper::WillProcessTask(const base::PendingTask& pending_task) {
236 helper_->Now() > idle_period_deadline_) { 196 }
237 TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0( 197
238 tracing_category_, idle_period_tracing_name_, this, "DeadlineOverrun", 198 void IdleHelper::DidProcessTask(const base::PendingTask& pending_task) {
239 idle_period_deadline_.ToInternalValue()); 199 helper_->CheckOnValidThread();
200 TRACE_EVENT0(disabled_by_default_tracing_category_, "DidProcessTask");
201 if (IsInIdlePeriod(state_.idle_period_state()) &&
202 state_.idle_period_state() !=
203 IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED &&
204 helper_->Now() >= state_.idle_period_deadline()) {
205 // If the idle period deadline has now been reached, either end the idle
206 // period or trigger a new long-idle period.
207 if (IsInLongIdlePeriod(state_.idle_period_state())) {
208 EnableLongIdlePeriod();
209 } else {
210 DCHECK(IdlePeriodState::IN_SHORT_IDLE_PERIOD ==
211 state_.idle_period_state());
212 EndIdlePeriod();
240 } 213 }
241 TRACE_EVENT_ASYNC_END0(tracing_category_, idle_period_tracing_name_, this);
242 } 214 }
215 }
243 216
244 helper_->DisableQueue(idle_queue_index_); 217 void IdleHelper::UpdateLongIdlePeriodStateAfterIdleTask() {
245 idle_period_state_ = IdlePeriodState::NOT_IN_IDLE_PERIOD; 218 helper_->CheckOnValidThread();
246 idle_period_deadline_ = base::TimeTicks(); 219 DCHECK(IsInLongIdlePeriod(state_.idle_period_state()));
220 TRACE_EVENT0(disabled_by_default_tracing_category_,
221 "UpdateLongIdlePeriodStateAfterIdleTask");
222 TaskQueueManager::QueueState queue_state =
223 helper_->GetQueueState(idle_queue_index_);
224 if (queue_state == TaskQueueManager::QueueState::EMPTY) {
225 // If there are no more idle tasks then pause long idle period ticks until a
226 // new idle task is posted.
227 state_.UpdateState(IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED,
228 state_.idle_period_deadline(), base::TimeTicks());
229 } else if (queue_state == TaskQueueManager::QueueState::NEEDS_PUMPING) {
230 // If there is still idle work to do then just start the next idle period.
231 base::TimeDelta next_long_idle_period_delay;
232 if (state_.idle_period_state() ==
233 IdlePeriodState::IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE) {
234 // If we are in a max deadline long idle period then start the next
235 // idle period immediately.
236 next_long_idle_period_delay = base::TimeDelta();
237 } else {
238 // Otherwise ensure that we kick the scheduler at the right time to
239 // initiate the next idle period.
240 next_long_idle_period_delay = std::max(
241 base::TimeDelta(), state_.idle_period_deadline() - helper_->Now());
242 }
243 helper_->ControlTaskRunner()->PostDelayedTask(
244 FROM_HERE, enable_next_long_idle_period_closure_.callback(),
245 next_long_idle_period_delay);
246 }
247 }
248
249 base::TimeTicks IdleHelper::CurrentIdleTaskDeadline() const {
250 helper_->CheckOnValidThread();
251 return state_.idle_period_deadline();
252 }
253
254 void IdleHelper::OnIdleTaskPosted() {
255 TRACE_EVENT0(disabled_by_default_tracing_category_, "OnIdleTaskPosted");
256 if (idle_task_runner_->RunsTasksOnCurrentThread()) {
257 OnIdleTaskPostedOnMainThread();
258 } else {
259 helper_->ControlTaskRunner()->PostTask(
260 FROM_HERE, on_idle_task_posted_closure_.callback());
261 }
262 }
263
264 void IdleHelper::OnIdleTaskPostedOnMainThread() {
265 TRACE_EVENT0(disabled_by_default_tracing_category_,
266 "OnIdleTaskPostedOnMainThread");
267 if (state_.idle_period_state() ==
268 IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED) {
269 // Restart long idle period ticks.
270 helper_->ControlTaskRunner()->PostTask(
271 FROM_HERE, enable_next_long_idle_period_closure_.callback());
272 }
273 }
274
275 base::TimeTicks IdleHelper::WillProcessIdleTask() {
276 helper_->CheckOnValidThread();
277 DCHECK(IsInIdlePeriod(state_.idle_period_state()));
278
279 state_.TraceIdleIdleTaskStart();
280 return CurrentIdleTaskDeadline();
281 }
282
283 void IdleHelper::DidProcessIdleTask() {
284 helper_->CheckOnValidThread();
285 state_.TraceIdleIdleTaskEnd();
286 if (IsInLongIdlePeriod(state_.idle_period_state())) {
287 UpdateLongIdlePeriodStateAfterIdleTask();
288 }
247 } 289 }
248 290
249 // static 291 // static
250 bool IdleHelper::IsInIdlePeriod(IdlePeriodState state) { 292 bool IdleHelper::IsInIdlePeriod(IdlePeriodState state) {
251 return state != IdlePeriodState::NOT_IN_IDLE_PERIOD; 293 return state != IdlePeriodState::NOT_IN_IDLE_PERIOD;
252 } 294 }
253 295
296 // static
297 bool IdleHelper::IsInLongIdlePeriod(IdlePeriodState state) {
298 return state == IdlePeriodState::IN_LONG_IDLE_PERIOD ||
299 state == IdlePeriodState::IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE ||
300 state == IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED;
301 }
302
254 bool IdleHelper::CanExceedIdleDeadlineIfRequired() const { 303 bool IdleHelper::CanExceedIdleDeadlineIfRequired() const {
255 TRACE_EVENT0(tracing_category_, "CanExceedIdleDeadlineIfRequired"); 304 TRACE_EVENT0(disabled_by_default_tracing_category_,
305 "CanExceedIdleDeadlineIfRequired");
256 helper_->CheckOnValidThread(); 306 helper_->CheckOnValidThread();
257 return idle_period_state_ == 307 return state_.idle_period_state() ==
258 IdlePeriodState::IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE; 308 IdlePeriodState::IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE;
259 } 309 }
260 310
261 IdleHelper::IdlePeriodState IdleHelper::SchedulerIdlePeriodState() const { 311 IdleHelper::IdlePeriodState IdleHelper::SchedulerIdlePeriodState() const {
312 return state_.idle_period_state();
313 }
314
315 IdleHelper::State::State(SchedulerHelper* helper,
316 const char* tracing_category,
317 const char* disabled_by_default_tracing_category,
318 const char* idle_period_tracing_name)
319 : helper_(helper),
320 idle_period_state_(IdlePeriodState::NOT_IN_IDLE_PERIOD),
321 nestable_events_started_(false),
322 tracing_category_(tracing_category),
323 disabled_by_default_tracing_category_(
324 disabled_by_default_tracing_category),
325 idle_period_tracing_name_(idle_period_tracing_name) {
326 }
327
328 IdleHelper::State::~State() {
329 }
330
331 IdleHelper::IdlePeriodState IdleHelper::State::idle_period_state() const {
332 helper_->CheckOnValidThread();
262 return idle_period_state_; 333 return idle_period_state_;
263 } 334 }
264 335
336 base::TimeTicks IdleHelper::State::idle_period_deadline() const {
337 helper_->CheckOnValidThread();
338 return idle_period_deadline_;
339 }
340
341 void IdleHelper::State::UpdateState(IdlePeriodState new_state,
342 base::TimeTicks new_deadline,
343 base::TimeTicks optional_now) {
344 helper_->CheckOnValidThread();
345 if (new_state == idle_period_state_) {
346 DCHECK_EQ(new_deadline, idle_period_deadline_);
347 return;
348 }
349
350 bool is_tracing;
351 TRACE_EVENT_CATEGORY_GROUP_ENABLED(tracing_category_, &is_tracing);
352 if (is_tracing) {
353 base::TimeTicks now(optional_now.is_null() ? helper_->Now() : optional_now);
354 TraceEventIdlePeriodStateChange(new_state, new_deadline, now);
355 idle_period_deadline_for_tracing_ =
356 base::TraceTicks::Now() + (new_deadline - now);
357 }
358
359 idle_period_state_ = new_state;
360 idle_period_deadline_ = new_deadline;
361 }
362
363 void IdleHelper::State::TraceIdleIdleTaskStart() {
364 helper_->CheckOnValidThread();
365
366 bool is_tracing;
367 TRACE_EVENT_CATEGORY_GROUP_ENABLED(tracing_category_, &is_tracing);
368 if (is_tracing && nestable_events_started_) {
369 last_idle_task_trace_time_ = base::TraceTicks::Now();
370 TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
371 tracing_category_, "RunningIdleTask", this,
372 last_idle_task_trace_time_.ToInternalValue());
373 }
374 }
375
376 void IdleHelper::State::TraceIdleIdleTaskEnd() {
377 helper_->CheckOnValidThread();
378
379 bool is_tracing;
380 TRACE_EVENT_CATEGORY_GROUP_ENABLED(tracing_category_, &is_tracing);
381 if (is_tracing && nestable_events_started_) {
382 if (!idle_period_deadline_for_tracing_.is_null() &&
383 base::TraceTicks::Now() > idle_period_deadline_for_tracing_) {
384 TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
385 tracing_category_, "DeadlineOverrun", this,
386 std::max(idle_period_deadline_for_tracing_,
387 last_idle_task_trace_time_).ToInternalValue());
388 TRACE_EVENT_NESTABLE_ASYNC_END0(tracing_category_, "DeadlineOverrun",
389 this);
390 }
391 TRACE_EVENT_NESTABLE_ASYNC_END0(tracing_category_, "RunningIdleTask", this);
392 }
393 }
394
395 void IdleHelper::State::TraceEventIdlePeriodStateChange(
396 IdlePeriodState new_state,
397 base::TimeTicks new_deadline,
398 base::TimeTicks now) {
399 TRACE_EVENT2(disabled_by_default_tracing_category_, "SetIdlePeriodState",
400 "old_state",
401 IdleHelper::IdlePeriodStateToString(idle_period_state_),
402 "new_state", IdleHelper::IdlePeriodStateToString(new_state));
403 if (nestable_events_started_) {
404 // End async tracing events for the state we are leaving.
405 if (idle_period_state_ == IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED) {
406 TRACE_EVENT_NESTABLE_ASYNC_END0(tracing_category_, "LongIdlePeriodPaused",
407 this);
408 }
409 if (IsInLongIdlePeriod(idle_period_state_) &&
410 !IsInLongIdlePeriod(new_state)) {
411 TRACE_EVENT_NESTABLE_ASYNC_END0(tracing_category_, "LongIdlePeriod",
412 this);
413 }
414 if (idle_period_state_ == IdlePeriodState::IN_SHORT_IDLE_PERIOD) {
415 TRACE_EVENT_NESTABLE_ASYNC_END0(tracing_category_, "ShortIdlePeriod",
416 this);
417 }
418 if (IsInIdlePeriod(idle_period_state_) && !IsInIdlePeriod(new_state)) {
419 TRACE_EVENT_NESTABLE_ASYNC_END0(tracing_category_,
420 idle_period_tracing_name_, this);
421 nestable_events_started_ = false;
422 }
423 }
424
425 // Start async tracing events for the state we are entering.
426 if (IsInIdlePeriod(new_state) && !IsInIdlePeriod(idle_period_state_)) {
427 nestable_events_started_ = true;
428 TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
429 tracing_category_, idle_period_tracing_name_, this,
430 "idle_period_length_ms", (new_deadline - now).ToInternalValue());
431 }
432 if (new_state == IdlePeriodState::IN_SHORT_IDLE_PERIOD) {
433 TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(tracing_category_, "ShortIdlePeriod",
434 this);
435 }
436 if (IsInLongIdlePeriod(new_state) &&
437 !IsInLongIdlePeriod(idle_period_state_)) {
438 TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(tracing_category_, "LongIdlePeriod",
439 this);
440 }
441 if (new_state == IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED) {
442 TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(tracing_category_, "LongIdlePeriodPaused",
443 this);
444 }
445 }
446
265 // static 447 // static
266 const char* IdleHelper::IdlePeriodStateToString( 448 const char* IdleHelper::IdlePeriodStateToString(
267 IdlePeriodState idle_period_state) { 449 IdlePeriodState idle_period_state) {
268 switch (idle_period_state) { 450 switch (idle_period_state) {
269 case IdlePeriodState::NOT_IN_IDLE_PERIOD: 451 case IdlePeriodState::NOT_IN_IDLE_PERIOD:
270 return "not_in_idle_period"; 452 return "not_in_idle_period";
271 case IdlePeriodState::IN_SHORT_IDLE_PERIOD: 453 case IdlePeriodState::IN_SHORT_IDLE_PERIOD:
272 return "in_short_idle_period"; 454 return "in_short_idle_period";
273 case IdlePeriodState::IN_LONG_IDLE_PERIOD: 455 case IdlePeriodState::IN_LONG_IDLE_PERIOD:
274 return "in_long_idle_period"; 456 return "in_long_idle_period";
275 case IdlePeriodState::IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE: 457 case IdlePeriodState::IN_LONG_IDLE_PERIOD_WITH_MAX_DEADLINE:
276 return "in_long_idle_period_with_max_deadline"; 458 return "in_long_idle_period_with_max_deadline";
277 case IdlePeriodState::ENDING_LONG_IDLE_PERIOD: 459 case IdlePeriodState::IN_LONG_IDLE_PERIOD_PAUSED:
278 return "ending_long_idle_period"; 460 return "in_long_idle_period_paused";
279 default: 461 default:
280 NOTREACHED(); 462 NOTREACHED();
281 return nullptr; 463 return nullptr;
282 } 464 }
283 } 465 }
284 466
285 } // namespace scheduler 467 } // namespace scheduler
OLDNEW
« no previous file with comments | « components/scheduler/child/idle_helper.h ('k') | components/scheduler/child/idle_helper_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698