OLD | NEW |
---|---|
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/renderer/renderer_scheduler_impl.h" | 5 #include "components/scheduler/renderer/renderer_scheduler_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/debug/stack_trace.h" | 8 #include "base/debug/stack_trace.h" |
9 #include "base/trace_event/trace_event.h" | 9 #include "base/trace_event/trace_event.h" |
10 #include "base/trace_event/trace_event_argument.h" | 10 #include "base/trace_event/trace_event_argument.h" |
11 #include "cc/output/begin_frame_args.h" | 11 #include "cc/output/begin_frame_args.h" |
12 #include "components/scheduler/child/scheduler_task_runner_delegate.h" | 12 #include "components/scheduler/child/scheduler_task_runner_delegate.h" |
13 #include "components/scheduler/child/task_queue_impl.h" | 13 #include "components/scheduler/child/task_queue_impl.h" |
14 #include "components/scheduler/child/task_queue_selector.h" | 14 #include "components/scheduler/child/task_queue_selector.h" |
15 | 15 |
16 namespace scheduler { | 16 namespace scheduler { |
17 namespace { | 17 namespace { |
18 const int kTimerTaskEstimationSampleCount = 4 * 60; | 18 const int kLoadingTaskEstimationSampleCount = 200; |
19 const double kTimerTaskEstimationPercentile = 80; | 19 const double kLoadingTaskEstimationPercentile = 90; |
20 const int kTimerTaskEstimationSampleCount = 200; | |
21 const double kTimerTaskEstimationPercentile = 90; | |
20 const int kShortIdlePeriodDurationSampleCount = 10; | 22 const int kShortIdlePeriodDurationSampleCount = 10; |
21 const double kShortIdlePeriodDurationPercentile = 20; | 23 const double kShortIdlePeriodDurationPercentile = 20; |
22 } | 24 } |
23 | 25 |
24 RendererSchedulerImpl::RendererSchedulerImpl( | 26 RendererSchedulerImpl::RendererSchedulerImpl( |
25 scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner) | 27 scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner) |
26 : helper_(main_task_runner, | 28 : helper_(main_task_runner, |
27 "renderer.scheduler", | 29 "renderer.scheduler", |
28 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 30 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
29 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler.debug")), | 31 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler.debug")), |
(...skipping 17 matching lines...) Expand all Loading... | |
47 base::Bind(&RendererSchedulerImpl::UpdatePolicy, | 49 base::Bind(&RendererSchedulerImpl::UpdatePolicy, |
48 base::Unretained(this)), | 50 base::Unretained(this)), |
49 helper_.ControlTaskRunner()), | 51 helper_.ControlTaskRunner()), |
50 policy_may_need_update_(&any_thread_lock_), | 52 policy_may_need_update_(&any_thread_lock_), |
51 weak_factory_(this) { | 53 weak_factory_(this) { |
52 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy, | 54 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy, |
53 weak_factory_.GetWeakPtr()); | 55 weak_factory_.GetWeakPtr()); |
54 end_renderer_hidden_idle_period_closure_.Reset(base::Bind( | 56 end_renderer_hidden_idle_period_closure_.Reset(base::Bind( |
55 &RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr())); | 57 &RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr())); |
56 | 58 |
59 loading_task_runner_->AddTaskObserver( | |
60 &MainThreadOnly().loading_task_cost_estimator); | |
61 | |
57 timer_task_runner_->AddTaskObserver( | 62 timer_task_runner_->AddTaskObserver( |
58 &MainThreadOnly().timer_task_cost_estimator_); | 63 &MainThreadOnly().timer_task_cost_estimator); |
59 | 64 |
60 TRACE_EVENT_OBJECT_CREATED_WITH_ID( | 65 TRACE_EVENT_OBJECT_CREATED_WITH_ID( |
61 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", | 66 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", |
62 this); | 67 this); |
68 | |
69 // Make sure that we don't initially assume there is no idle time. | |
70 MainThreadOnly().short_idle_period_duration.InsertSample( | |
71 cc::BeginFrameArgs::DefaultInterval()); | |
63 } | 72 } |
64 | 73 |
65 RendererSchedulerImpl::~RendererSchedulerImpl() { | 74 RendererSchedulerImpl::~RendererSchedulerImpl() { |
66 TRACE_EVENT_OBJECT_DELETED_WITH_ID( | 75 TRACE_EVENT_OBJECT_DELETED_WITH_ID( |
67 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", | 76 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", |
68 this); | 77 this); |
69 timer_task_runner_->RemoveTaskObserver( | 78 timer_task_runner_->RemoveTaskObserver( |
70 &MainThreadOnly().timer_task_cost_estimator_); | 79 &MainThreadOnly().timer_task_cost_estimator); |
71 // Ensure the renderer scheduler was shut down explicitly, because otherwise | 80 // Ensure the renderer scheduler was shut down explicitly, because otherwise |
72 // we could end up having stale pointers to the Blink heap which has been | 81 // we could end up having stale pointers to the Blink heap which has been |
73 // terminated by this point. | 82 // terminated by this point. |
74 DCHECK(MainThreadOnly().was_shutdown_); | 83 DCHECK(MainThreadOnly().was_shutdown); |
75 } | 84 } |
76 | 85 |
86 RendererSchedulerImpl::Policy::Policy() | |
87 : compositor_queue_priority(TaskQueue::NORMAL_PRIORITY), | |
88 loading_queue_priority(TaskQueue::NORMAL_PRIORITY), | |
89 timer_queue_priority(TaskQueue::NORMAL_PRIORITY) {} | |
90 | |
77 RendererSchedulerImpl::MainThreadOnly::MainThreadOnly() | 91 RendererSchedulerImpl::MainThreadOnly::MainThreadOnly() |
78 : timer_task_cost_estimator_(kTimerTaskEstimationSampleCount, | 92 : loading_task_cost_estimator(kLoadingTaskEstimationSampleCount, |
79 kTimerTaskEstimationPercentile), | 93 kLoadingTaskEstimationPercentile), |
80 short_idle_period_duration_(kShortIdlePeriodDurationSampleCount), | 94 timer_task_cost_estimator(kTimerTaskEstimationSampleCount, |
81 current_policy_(Policy::NORMAL), | 95 kTimerTaskEstimationPercentile), |
82 timer_queue_suspend_count_(0), | 96 short_idle_period_duration(kShortIdlePeriodDurationSampleCount), |
83 renderer_hidden_(false), | 97 current_use_case(UseCase::NONE), |
84 was_shutdown_(false) {} | 98 timer_queue_suspend_count(0), |
99 renderer_hidden(false), | |
100 was_shutdown(false), | |
101 loading_tasks_seem_expensive(false), | |
102 timer_tasks_seem_expensive(false), | |
103 touchstart_expected_soon(false) {} | |
85 | 104 |
86 RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {} | 105 RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {} |
87 | 106 |
88 RendererSchedulerImpl::AnyThread::AnyThread() | 107 RendererSchedulerImpl::AnyThread::AnyThread() |
89 : pending_main_thread_input_event_count_(0), | 108 : awaiting_touch_start_response(false), |
90 awaiting_touch_start_response_(false), | 109 in_idle_period(false), |
91 in_idle_period_(false), | 110 begin_main_frame_on_critical_path(false) {} |
92 begin_main_frame_on_critical_path_(false), | |
93 timer_tasks_seem_expensive_(false) {} | |
94 | 111 |
95 RendererSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly() | 112 RendererSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly() |
96 : last_input_type_(blink::WebInputEvent::Undefined) { | 113 : last_input_type(blink::WebInputEvent::Undefined) {} |
97 } | |
98 | 114 |
99 RendererSchedulerImpl::CompositorThreadOnly::~CompositorThreadOnly() { | 115 RendererSchedulerImpl::CompositorThreadOnly::~CompositorThreadOnly() { |
100 } | 116 } |
101 | 117 |
102 void RendererSchedulerImpl::Shutdown() { | 118 void RendererSchedulerImpl::Shutdown() { |
103 helper_.Shutdown(); | 119 helper_.Shutdown(); |
104 MainThreadOnly().was_shutdown_ = true; | 120 MainThreadOnly().was_shutdown = true; |
105 } | 121 } |
106 | 122 |
107 scoped_refptr<TaskQueue> RendererSchedulerImpl::DefaultTaskRunner() { | 123 scoped_refptr<TaskQueue> RendererSchedulerImpl::DefaultTaskRunner() { |
108 return helper_.DefaultTaskRunner(); | 124 return helper_.DefaultTaskRunner(); |
109 } | 125 } |
110 | 126 |
111 scoped_refptr<base::SingleThreadTaskRunner> | 127 scoped_refptr<base::SingleThreadTaskRunner> |
112 RendererSchedulerImpl::CompositorTaskRunner() { | 128 RendererSchedulerImpl::CompositorTaskRunner() { |
113 helper_.CheckOnValidThread(); | 129 helper_.CheckOnValidThread(); |
114 return compositor_task_runner_; | 130 return compositor_task_runner_; |
(...skipping 30 matching lines...) Expand all Loading... | |
145 } | 161 } |
146 | 162 |
147 void RendererSchedulerImpl::WillBeginFrame(const cc::BeginFrameArgs& args) { | 163 void RendererSchedulerImpl::WillBeginFrame(const cc::BeginFrameArgs& args) { |
148 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 164 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
149 "RendererSchedulerImpl::WillBeginFrame", "args", args.AsValue()); | 165 "RendererSchedulerImpl::WillBeginFrame", "args", args.AsValue()); |
150 helper_.CheckOnValidThread(); | 166 helper_.CheckOnValidThread(); |
151 if (helper_.IsShutdown()) | 167 if (helper_.IsShutdown()) |
152 return; | 168 return; |
153 | 169 |
154 EndIdlePeriod(); | 170 EndIdlePeriod(); |
155 MainThreadOnly().estimated_next_frame_begin_ = | 171 MainThreadOnly().estimated_next_frame_begin = args.frame_time + args.interval; |
156 args.frame_time + args.interval; | |
157 { | 172 { |
158 base::AutoLock lock(any_thread_lock_); | 173 base::AutoLock lock(any_thread_lock_); |
159 AnyThread().begin_main_frame_on_critical_path_ = args.on_critical_path; | 174 AnyThread().begin_main_frame_on_critical_path = args.on_critical_path; |
160 } | 175 } |
161 } | 176 } |
162 | 177 |
163 void RendererSchedulerImpl::DidCommitFrameToCompositor() { | 178 void RendererSchedulerImpl::DidCommitFrameToCompositor() { |
164 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 179 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
165 "RendererSchedulerImpl::DidCommitFrameToCompositor"); | 180 "RendererSchedulerImpl::DidCommitFrameToCompositor"); |
166 helper_.CheckOnValidThread(); | 181 helper_.CheckOnValidThread(); |
167 if (helper_.IsShutdown()) | 182 if (helper_.IsShutdown()) |
168 return; | 183 return; |
169 | 184 |
170 base::TimeTicks now(helper_.Now()); | 185 base::TimeTicks now(helper_.Now()); |
171 if (now < MainThreadOnly().estimated_next_frame_begin_) { | 186 if (now < MainThreadOnly().estimated_next_frame_begin) { |
172 // TODO(rmcilroy): Consider reducing the idle period based on the runtime of | 187 // TODO(rmcilroy): Consider reducing the idle period based on the runtime of |
173 // the next pending delayed tasks (as currently done in for long idle times) | 188 // the next pending delayed tasks (as currently done in for long idle times) |
174 idle_helper_.StartIdlePeriod( | 189 idle_helper_.StartIdlePeriod( |
175 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, now, | 190 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, now, |
176 MainThreadOnly().estimated_next_frame_begin_); | 191 MainThreadOnly().estimated_next_frame_begin); |
177 MainThreadOnly().short_idle_period_duration_.InsertSample( | 192 MainThreadOnly().short_idle_period_duration.InsertSample( |
178 MainThreadOnly().estimated_next_frame_begin_ - now); | 193 MainThreadOnly().estimated_next_frame_begin - now); |
179 MainThreadOnly().expected_short_idle_period_duration_ = | 194 } else { |
180 MainThreadOnly().short_idle_period_duration_.Percentile( | 195 // There was no idle time :( |
181 kShortIdlePeriodDurationPercentile); | 196 MainThreadOnly().short_idle_period_duration.InsertSample(base::TimeDelta()); |
182 } | 197 } |
198 | |
199 MainThreadOnly().expected_short_idle_period_duration = | |
200 MainThreadOnly().short_idle_period_duration.Percentile( | |
201 kShortIdlePeriodDurationPercentile); | |
183 } | 202 } |
184 | 203 |
185 void RendererSchedulerImpl::BeginFrameNotExpectedSoon() { | 204 void RendererSchedulerImpl::BeginFrameNotExpectedSoon() { |
186 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 205 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
187 "RendererSchedulerImpl::BeginFrameNotExpectedSoon"); | 206 "RendererSchedulerImpl::BeginFrameNotExpectedSoon"); |
188 helper_.CheckOnValidThread(); | 207 helper_.CheckOnValidThread(); |
189 if (helper_.IsShutdown()) | 208 if (helper_.IsShutdown()) |
190 return; | 209 return; |
191 | 210 |
192 idle_helper_.EnableLongIdlePeriod(); | 211 idle_helper_.EnableLongIdlePeriod(); |
193 } | 212 } |
194 | 213 |
195 void RendererSchedulerImpl::OnRendererHidden() { | 214 void RendererSchedulerImpl::OnRendererHidden() { |
196 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 215 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
197 "RendererSchedulerImpl::OnRendererHidden"); | 216 "RendererSchedulerImpl::OnRendererHidden"); |
198 helper_.CheckOnValidThread(); | 217 helper_.CheckOnValidThread(); |
199 if (helper_.IsShutdown() || MainThreadOnly().renderer_hidden_) | 218 if (helper_.IsShutdown() || MainThreadOnly().renderer_hidden) |
200 return; | 219 return; |
201 | 220 |
202 idle_helper_.EnableLongIdlePeriod(); | 221 idle_helper_.EnableLongIdlePeriod(); |
203 | 222 |
204 // Ensure that we stop running idle tasks after a few seconds of being hidden. | 223 // Ensure that we stop running idle tasks after a few seconds of being hidden. |
205 end_renderer_hidden_idle_period_closure_.Cancel(); | 224 end_renderer_hidden_idle_period_closure_.Cancel(); |
206 base::TimeDelta end_idle_when_hidden_delay = | 225 base::TimeDelta end_idle_when_hidden_delay = |
207 base::TimeDelta::FromMilliseconds(kEndIdleWhenHiddenDelayMillis); | 226 base::TimeDelta::FromMilliseconds(kEndIdleWhenHiddenDelayMillis); |
208 control_task_runner_->PostDelayedTask( | 227 control_task_runner_->PostDelayedTask( |
209 FROM_HERE, end_renderer_hidden_idle_period_closure_.callback(), | 228 FROM_HERE, end_renderer_hidden_idle_period_closure_.callback(), |
210 end_idle_when_hidden_delay); | 229 end_idle_when_hidden_delay); |
211 MainThreadOnly().renderer_hidden_ = true; | 230 MainThreadOnly().renderer_hidden = true; |
212 | 231 |
213 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( | 232 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
214 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", | 233 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", |
215 this, AsValue(helper_.Now())); | 234 this, AsValue(helper_.Now())); |
216 } | 235 } |
217 | 236 |
218 void RendererSchedulerImpl::OnRendererVisible() { | 237 void RendererSchedulerImpl::OnRendererVisible() { |
219 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 238 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
220 "RendererSchedulerImpl::OnRendererVisible"); | 239 "RendererSchedulerImpl::OnRendererVisible"); |
221 helper_.CheckOnValidThread(); | 240 helper_.CheckOnValidThread(); |
222 if (helper_.IsShutdown() || !MainThreadOnly().renderer_hidden_) | 241 if (helper_.IsShutdown() || !MainThreadOnly().renderer_hidden) |
223 return; | 242 return; |
224 | 243 |
225 end_renderer_hidden_idle_period_closure_.Cancel(); | 244 end_renderer_hidden_idle_period_closure_.Cancel(); |
226 MainThreadOnly().renderer_hidden_ = false; | 245 MainThreadOnly().renderer_hidden = false; |
227 EndIdlePeriod(); | 246 EndIdlePeriod(); |
228 | 247 |
229 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( | 248 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
230 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", | 249 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", |
231 this, AsValue(helper_.Now())); | 250 this, AsValue(helper_.Now())); |
232 } | 251 } |
233 | 252 |
234 void RendererSchedulerImpl::EndIdlePeriod() { | 253 void RendererSchedulerImpl::EndIdlePeriod() { |
235 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 254 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
236 "RendererSchedulerImpl::EndIdlePeriod"); | 255 "RendererSchedulerImpl::EndIdlePeriod"); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
276 UpdateForInputEventOnCompositorThread( | 295 UpdateForInputEventOnCompositorThread( |
277 blink::WebInputEvent::Undefined, | 296 blink::WebInputEvent::Undefined, |
278 InputEventState::EVENT_CONSUMED_BY_COMPOSITOR); | 297 InputEventState::EVENT_CONSUMED_BY_COMPOSITOR); |
279 } | 298 } |
280 | 299 |
281 void RendererSchedulerImpl::UpdateForInputEventOnCompositorThread( | 300 void RendererSchedulerImpl::UpdateForInputEventOnCompositorThread( |
282 blink::WebInputEvent::Type type, | 301 blink::WebInputEvent::Type type, |
283 InputEventState input_event_state) { | 302 InputEventState input_event_state) { |
284 base::AutoLock lock(any_thread_lock_); | 303 base::AutoLock lock(any_thread_lock_); |
285 base::TimeTicks now = helper_.Now(); | 304 base::TimeTicks now = helper_.Now(); |
286 bool was_in_compositor_priority = InputSignalsSuggestCompositorPriority(now); | 305 |
306 // TODO(alexclarke): Move WebInputEventTraits where we can access it from here | |
307 // and record the name rather than the integer representation. | |
308 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | |
309 "RendererSchedulerImpl::UpdateForInputEventOnCompositorThread", | |
310 "type", static_cast<int>(type), "input_event_state", | |
311 InputEventStateToString(input_event_state)); | |
312 | |
313 bool gesture_already_in_progress = InputSignalsSuggestGestureInProgress(now); | |
287 bool was_awaiting_touch_start_response = | 314 bool was_awaiting_touch_start_response = |
288 AnyThread().awaiting_touch_start_response_; | 315 AnyThread().awaiting_touch_start_response; |
316 | |
317 AnyThread().user_model.DidHandleInputEventOnCompositorThread( | |
318 type, input_event_state, now); | |
289 | 319 |
290 if (type) { | 320 if (type) { |
291 switch (type) { | 321 switch (type) { |
292 case blink::WebInputEvent::TouchStart: | 322 case blink::WebInputEvent::TouchStart: |
293 AnyThread().awaiting_touch_start_response_ = true; | 323 AnyThread().awaiting_touch_start_response = true; |
294 break; | 324 break; |
295 | 325 |
296 case blink::WebInputEvent::TouchMove: | 326 case blink::WebInputEvent::TouchMove: |
297 // Observation of consecutive touchmoves is a strong signal that the | 327 // Observation of consecutive touchmoves is a strong signal that the |
298 // page is consuming the touch sequence, in which case touchstart | 328 // page is consuming the touch sequence, in which case touchstart |
299 // response prioritization is no longer necessary. Otherwise, the | 329 // response prioritization is no longer necessary. Otherwise, the |
300 // initial touchmove should preserve the touchstart response pending | 330 // initial touchmove should preserve the touchstart response pending |
301 // state. | 331 // state. |
302 if (AnyThread().awaiting_touch_start_response_ && | 332 if (AnyThread().awaiting_touch_start_response && |
303 CompositorThreadOnly().last_input_type_ == | 333 CompositorThreadOnly().last_input_type == |
304 blink::WebInputEvent::TouchMove) { | 334 blink::WebInputEvent::TouchMove) { |
305 AnyThread().awaiting_touch_start_response_ = false; | 335 AnyThread().awaiting_touch_start_response = false; |
306 } | 336 } |
307 break; | 337 break; |
308 | 338 |
309 case blink::WebInputEvent::Undefined: | 339 case blink::WebInputEvent::Undefined: |
310 case blink::WebInputEvent::GestureTapDown: | 340 case blink::WebInputEvent::GestureTapDown: |
311 case blink::WebInputEvent::GestureShowPress: | 341 case blink::WebInputEvent::GestureShowPress: |
312 case blink::WebInputEvent::GestureFlingCancel: | 342 case blink::WebInputEvent::GestureFlingCancel: |
313 case blink::WebInputEvent::GestureScrollEnd: | 343 case blink::WebInputEvent::GestureScrollEnd: |
314 // With no observable effect, these meta events do not indicate a | 344 // With no observable effect, these meta events do not indicate a |
315 // meaningful touchstart response and should not impact task priority. | 345 // meaningful touchstart response and should not impact task priority. |
316 break; | 346 break; |
317 | 347 |
318 default: | 348 default: |
319 AnyThread().awaiting_touch_start_response_ = false; | 349 AnyThread().awaiting_touch_start_response = false; |
320 break; | 350 break; |
321 } | 351 } |
322 } | 352 } |
323 | 353 |
324 // Avoid unnecessary policy updates, while in compositor priority. | 354 // Avoid unnecessary policy updates, while a gesture is already in progress. |
325 if (!was_in_compositor_priority || | 355 if (!gesture_already_in_progress || |
326 was_awaiting_touch_start_response != | 356 was_awaiting_touch_start_response != |
327 AnyThread().awaiting_touch_start_response_) { | 357 AnyThread().awaiting_touch_start_response) { |
328 EnsureUrgentPolicyUpdatePostedOnMainThread(FROM_HERE); | 358 EnsureUrgentPolicyUpdatePostedOnMainThread(FROM_HERE); |
329 } | 359 } |
330 AnyThread().last_input_signal_time_ = now; | 360 CompositorThreadOnly().last_input_type = type; |
331 CompositorThreadOnly().last_input_type_ = type; | |
332 | |
333 if (input_event_state == InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD) | |
334 AnyThread().pending_main_thread_input_event_count_++; | |
335 } | 361 } |
336 | 362 |
337 void RendererSchedulerImpl::DidHandleInputEventOnMainThread( | 363 void RendererSchedulerImpl::DidHandleInputEventOnMainThread( |
338 const blink::WebInputEvent& web_input_event) { | 364 const blink::WebInputEvent& web_input_event) { |
339 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 365 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
340 "RendererSchedulerImpl::DidHandleInputEventOnMainThread"); | 366 "RendererSchedulerImpl::DidHandleInputEventOnMainThread"); |
341 helper_.CheckOnValidThread(); | 367 helper_.CheckOnValidThread(); |
342 if (ShouldPrioritizeInputEvent(web_input_event)) { | 368 if (ShouldPrioritizeInputEvent(web_input_event)) { |
343 base::AutoLock lock(any_thread_lock_); | 369 base::AutoLock lock(any_thread_lock_); |
344 AnyThread().last_input_signal_time_ = helper_.Now(); | 370 AnyThread().user_model.DidHandleInputEventOnMainThread(helper_.Now()); |
345 if (AnyThread().pending_main_thread_input_event_count_ > 0) | |
346 AnyThread().pending_main_thread_input_event_count_--; | |
347 } | 371 } |
348 } | 372 } |
349 | 373 |
350 bool RendererSchedulerImpl::IsHighPriorityWorkAnticipated() { | 374 bool RendererSchedulerImpl::IsHighPriorityWorkAnticipated() { |
351 helper_.CheckOnValidThread(); | 375 helper_.CheckOnValidThread(); |
352 if (helper_.IsShutdown()) | 376 if (helper_.IsShutdown()) |
353 return false; | 377 return false; |
354 | 378 |
355 MaybeUpdatePolicy(); | 379 MaybeUpdatePolicy(); |
356 // The touchstart and compositor policies indicate a strong likelihood of | 380 // The touchstart and main-thread scrolling states indicate a strong |
357 // high-priority work in the near future. | 381 // likelihood of high-priority work in the near future. |
358 return MainThreadOnly().current_policy_ == Policy::COMPOSITOR_PRIORITY || | 382 UseCase use_case = MainThreadOnly().current_use_case; |
359 MainThreadOnly().current_policy_ == | 383 return MainThreadOnly().touchstart_expected_soon || |
360 Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY || | 384 use_case == UseCase::TOUCHSTART || |
361 MainThreadOnly().current_policy_ == Policy::TOUCHSTART_PRIORITY; | 385 use_case == UseCase::MAIN_THREAD_GESTURE; |
362 } | 386 } |
363 | 387 |
364 bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() { | 388 bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() { |
365 helper_.CheckOnValidThread(); | 389 helper_.CheckOnValidThread(); |
366 if (helper_.IsShutdown()) | 390 if (helper_.IsShutdown()) |
367 return false; | 391 return false; |
368 | 392 |
369 MaybeUpdatePolicy(); | 393 MaybeUpdatePolicy(); |
370 // We only yield if we are in the compositor priority and there is compositor | 394 // We only yield if there's a urgent task to be run now, or we are expecting |
371 // work outstanding, or if we are in the touchstart response priority. | 395 // one soon (touch start). |
372 // Note: even though the control queue is higher priority we don't yield for | 396 // Note: even though the control queue has the highest priority we don't yield |
373 // it since these tasks are not user-provided work and they are only intended | 397 // for it since these tasks are not user-provided work and they are only |
374 // to run before the next task, not interrupt the tasks. | 398 // intended to run before the next task, not interrupt the tasks. |
375 switch (MainThreadOnly().current_policy_) { | 399 switch (MainThreadOnly().current_use_case) { |
376 case Policy::NORMAL: | 400 case UseCase::NONE: |
377 return false; | 401 return MainThreadOnly().touchstart_expected_soon; |
378 | 402 |
379 case Policy::COMPOSITOR_PRIORITY: | 403 case UseCase::COMPOSITOR_GESTURE: |
380 return !compositor_task_runner_->IsQueueEmpty(); | 404 return MainThreadOnly().touchstart_expected_soon; |
381 | 405 |
382 case Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY: | 406 case UseCase::MAIN_THREAD_GESTURE: |
383 return !compositor_task_runner_->IsQueueEmpty(); | 407 return !compositor_task_runner_->IsQueueEmpty() || |
408 MainThreadOnly().touchstart_expected_soon; | |
384 | 409 |
385 case Policy::TOUCHSTART_PRIORITY: | 410 case UseCase::TOUCHSTART: |
386 return true; | 411 return true; |
387 | 412 |
388 case Policy::LOADING_PRIORITY: | 413 case UseCase::LOADING: |
389 return false; | 414 return false; |
390 | 415 |
391 default: | 416 default: |
392 NOTREACHED(); | 417 NOTREACHED(); |
393 return false; | 418 return false; |
394 } | 419 } |
395 } | 420 } |
396 | 421 |
397 base::TimeTicks RendererSchedulerImpl::CurrentIdleTaskDeadlineForTesting() | 422 base::TimeTicks RendererSchedulerImpl::CurrentIdleTaskDeadlineForTesting() |
398 const { | 423 const { |
(...skipping 30 matching lines...) Expand all Loading... | |
429 | 454 |
430 void RendererSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) { | 455 void RendererSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) { |
431 helper_.CheckOnValidThread(); | 456 helper_.CheckOnValidThread(); |
432 any_thread_lock_.AssertAcquired(); | 457 any_thread_lock_.AssertAcquired(); |
433 if (helper_.IsShutdown()) | 458 if (helper_.IsShutdown()) |
434 return; | 459 return; |
435 | 460 |
436 base::TimeTicks now = helper_.Now(); | 461 base::TimeTicks now = helper_.Now(); |
437 policy_may_need_update_.SetWhileLocked(false); | 462 policy_may_need_update_.SetWhileLocked(false); |
438 | 463 |
439 AnyThread().timer_tasks_seem_expensive_ = | 464 base::TimeDelta expected_use_case_duration; |
440 MainThreadOnly().expected_short_idle_period_duration_ > | 465 UseCase use_case = ComputeCurrentUseCase(now, &expected_use_case_duration); |
441 base::TimeDelta() && | 466 MainThreadOnly().current_use_case = use_case; |
442 MainThreadOnly().timer_task_cost_estimator_.expected_task_duration() > | |
443 MainThreadOnly().expected_short_idle_period_duration_; | |
444 | 467 |
445 base::TimeDelta new_policy_duration; | 468 // TODO(alexclarke): We should wire up a signal from blink to let us know if |
446 Policy new_policy = ComputeNewPolicy(now, &new_policy_duration); | 469 // there are any touch handlers registerd or not, and only call |
470 // TouchStartExpectedSoon if there is at least one. | |
471 base::TimeDelta scroll_expected_flag_valid_for_duration; | |
472 bool touchstart_expected_soon = AnyThread().user_model.TouchStartExpectedSoon( | |
473 use_case, now, &scroll_expected_flag_valid_for_duration); | |
474 MainThreadOnly().touchstart_expected_soon = touchstart_expected_soon; | |
475 | |
476 bool loading_tasks_seem_expensive = | |
477 MainThreadOnly().loading_task_cost_estimator.expected_task_duration() > | |
478 MainThreadOnly().expected_short_idle_period_duration; | |
479 MainThreadOnly().loading_tasks_seem_expensive = loading_tasks_seem_expensive; | |
480 | |
481 bool timer_tasks_seem_expensive = | |
482 MainThreadOnly().timer_task_cost_estimator.expected_task_duration() > | |
483 MainThreadOnly().expected_short_idle_period_duration; | |
484 MainThreadOnly().timer_tasks_seem_expensive = timer_tasks_seem_expensive; | |
485 | |
486 // The |new_policy_duration| is the minimum of |expected_use_case_duration| | |
487 // and |scroll_expected_flag_valid_for_duration| unless one is zero in which | |
488 // case we choose the other. | |
489 base::TimeDelta new_policy_duration = expected_use_case_duration; | |
490 if (new_policy_duration == base::TimeDelta() || | |
491 (scroll_expected_flag_valid_for_duration > base::TimeDelta() && | |
492 new_policy_duration > scroll_expected_flag_valid_for_duration)) { | |
493 new_policy_duration = scroll_expected_flag_valid_for_duration; | |
494 } | |
495 | |
447 if (new_policy_duration > base::TimeDelta()) { | 496 if (new_policy_duration > base::TimeDelta()) { |
448 MainThreadOnly().current_policy_expiration_time_ = | 497 MainThreadOnly().current_policy_expiration_time = now + new_policy_duration; |
449 now + new_policy_duration; | |
450 delayed_update_policy_runner_.SetDeadline(FROM_HERE, new_policy_duration, | 498 delayed_update_policy_runner_.SetDeadline(FROM_HERE, new_policy_duration, |
451 now); | 499 now); |
452 } else { | 500 } else { |
453 MainThreadOnly().current_policy_expiration_time_ = base::TimeTicks(); | 501 MainThreadOnly().current_policy_expiration_time = base::TimeTicks(); |
454 } | 502 } |
455 | 503 |
456 if (update_type == UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED && | 504 Policy new_policy; |
457 new_policy == MainThreadOnly().current_policy_) | 505 bool block_expensive_tasks = false; |
458 return; | 506 switch (use_case) { |
507 case UseCase::COMPOSITOR_GESTURE: | |
508 if (touchstart_expected_soon) | |
509 block_expensive_tasks = true; | |
510 else | |
511 new_policy.loading_queue_priority = TaskQueue::HIGH_PRIORITY; | |
512 break; | |
459 | 513 |
460 TaskQueue::QueuePriority compositor_queue_priority = | 514 case UseCase::MAIN_THREAD_GESTURE: |
461 TaskQueue::NORMAL_PRIORITY; | 515 new_policy.compositor_queue_priority = TaskQueue::HIGH_PRIORITY; |
462 TaskQueue::QueuePriority loading_queue_priority = TaskQueue::NORMAL_PRIORITY; | 516 block_expensive_tasks = true; |
463 TaskQueue::QueuePriority timer_queue_priority = | 517 break; |
464 MainThreadOnly().timer_queue_suspend_count_ != 0 | |
465 ? TaskQueue::DISABLED_PRIORITY | |
466 : TaskQueue::NORMAL_PRIORITY; | |
467 | 518 |
468 switch (new_policy) { | 519 case UseCase::TOUCHSTART: |
469 case Policy::COMPOSITOR_PRIORITY: | 520 new_policy.compositor_queue_priority = TaskQueue::HIGH_PRIORITY; |
470 compositor_queue_priority = TaskQueue::HIGH_PRIORITY; | 521 new_policy.loading_queue_priority = TaskQueue::DISABLED_PRIORITY; |
522 new_policy.timer_queue_priority = TaskQueue::DISABLED_PRIORITY; | |
471 break; | 523 break; |
472 case Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY: | 524 |
473 compositor_queue_priority = TaskQueue::HIGH_PRIORITY; | 525 case UseCase::NONE: |
474 loading_queue_priority = TaskQueue::DISABLED_PRIORITY; | 526 if (touchstart_expected_soon) |
475 timer_queue_priority = TaskQueue::DISABLED_PRIORITY; | 527 block_expensive_tasks = true; |
528 else | |
529 new_policy.loading_queue_priority = TaskQueue::HIGH_PRIORITY; | |
476 break; | 530 break; |
477 case Policy::TOUCHSTART_PRIORITY: | 531 |
478 compositor_queue_priority = TaskQueue::HIGH_PRIORITY; | 532 case UseCase::LOADING: |
479 loading_queue_priority = TaskQueue::DISABLED_PRIORITY; | 533 new_policy.loading_queue_priority = TaskQueue::HIGH_PRIORITY; |
480 timer_queue_priority = TaskQueue::DISABLED_PRIORITY; | |
481 break; | |
482 case Policy::NORMAL: | |
483 break; | |
484 case Policy::LOADING_PRIORITY: | |
485 // We prioritize loading tasks by deprioritizing compositing and timers. | |
486 compositor_queue_priority = TaskQueue::BEST_EFFORT_PRIORITY; | |
487 timer_queue_priority = TaskQueue::BEST_EFFORT_PRIORITY; | |
488 // TODO(alexclarke): See if we can safely mark the loading task queue as | |
489 // high priority. | |
490 break; | 534 break; |
491 default: | 535 default: |
492 NOTREACHED(); | 536 NOTREACHED(); |
493 } | 537 } |
494 | 538 |
495 compositor_task_runner_->SetQueuePriority(compositor_queue_priority); | 539 if (block_expensive_tasks && loading_tasks_seem_expensive) |
496 loading_task_runner_->SetQueuePriority(loading_queue_priority); | 540 new_policy.loading_queue_priority = TaskQueue::DISABLED_PRIORITY; |
497 timer_task_runner_->SetQueuePriority(timer_queue_priority); | |
498 | 541 |
499 DCHECK(compositor_task_runner_->IsQueueEnabled()); | 542 if ((block_expensive_tasks && timer_tasks_seem_expensive) || |
500 if (new_policy != Policy::TOUCHSTART_PRIORITY && | 543 MainThreadOnly().timer_queue_suspend_count != 0) |
501 new_policy != Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY) { | 544 new_policy.timer_queue_priority = TaskQueue::DISABLED_PRIORITY; |
502 DCHECK(loading_task_runner_->IsQueueEnabled()); | |
503 } | |
504 MainThreadOnly().current_policy_ = new_policy; | |
505 | 545 |
546 // Tracing is done before the early out check, because it's quite possible we | |
Sami
2015/08/27 15:15:59
Should we only do this if the use case or the poli
alex clarke (OOO till 29th)
2015/09/03 10:34:25
I actually think it was way too hard to figure out
| |
547 // will otherwise miss this information in traces. | |
506 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( | 548 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
507 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", | 549 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", |
508 this, AsValueLocked(now)); | 550 this, AsValueLocked(now)); |
551 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "use_case", | |
552 use_case); | |
509 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 553 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
510 "RendererScheduler.policy", MainThreadOnly().current_policy_); | 554 "RendererScheduler.loading_tasks_seem_expensive", |
555 MainThreadOnly().loading_tasks_seem_expensive); | |
511 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 556 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
512 "RendererScheduler.timer_tasks_seem_expensive", | 557 "RendererScheduler.timer_tasks_seem_expensive", |
513 AnyThread().timer_tasks_seem_expensive_); | 558 MainThreadOnly().timer_tasks_seem_expensive); |
559 | |
560 if (update_type == UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED && | |
561 new_policy == MainThreadOnly().current_policy) { | |
562 return; | |
563 } | |
564 | |
565 compositor_task_runner_->SetQueuePriority( | |
566 new_policy.compositor_queue_priority); | |
567 loading_task_runner_->SetQueuePriority(new_policy.loading_queue_priority); | |
568 timer_task_runner_->SetQueuePriority(new_policy.timer_queue_priority); | |
569 | |
570 DCHECK(compositor_task_runner_->IsQueueEnabled()); | |
571 MainThreadOnly().current_policy = new_policy; | |
514 } | 572 } |
515 | 573 |
516 bool RendererSchedulerImpl::InputSignalsSuggestCompositorPriority( | 574 bool RendererSchedulerImpl::InputSignalsSuggestGestureInProgress( |
517 base::TimeTicks now) const { | 575 base::TimeTicks now) const { |
518 base::TimeDelta unused_policy_duration; | 576 base::TimeDelta unused_policy_duration; |
519 switch (ComputeNewPolicy(now, &unused_policy_duration)) { | 577 switch (ComputeCurrentUseCase(now, &unused_policy_duration)) { |
520 case Policy::TOUCHSTART_PRIORITY: | 578 case UseCase::COMPOSITOR_GESTURE: |
521 case Policy::COMPOSITOR_PRIORITY: | 579 case UseCase::MAIN_THREAD_GESTURE: |
522 case Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY: | 580 case UseCase::TOUCHSTART: |
523 return true; | 581 return true; |
524 | 582 |
525 default: | 583 default: |
526 break; | 584 break; |
527 } | 585 } |
528 return false; | 586 return false; |
529 } | 587 } |
530 | 588 |
531 RendererSchedulerImpl::Policy RendererSchedulerImpl::ComputeNewPolicy( | 589 RendererSchedulerImpl::UseCase RendererSchedulerImpl::ComputeCurrentUseCase( |
532 base::TimeTicks now, | 590 base::TimeTicks now, |
533 base::TimeDelta* new_policy_duration) const { | 591 base::TimeDelta* expected_use_case_duration) const { |
534 any_thread_lock_.AssertAcquired(); | 592 any_thread_lock_.AssertAcquired(); |
535 // Above all else we want to be responsive to user input. | 593 // Above all else we want to be responsive to user input. |
536 *new_policy_duration = TimeLeftInInputEscalatedPolicy(now); | 594 *expected_use_case_duration = |
537 if (*new_policy_duration > base::TimeDelta()) { | 595 AnyThread().user_model.TimeLeftInInputEscalatedPolicy(now); |
538 if (AnyThread().awaiting_touch_start_response_) | 596 if (*expected_use_case_duration > base::TimeDelta()) { |
539 return Policy::TOUCHSTART_PRIORITY; | 597 // Has scrolling been fully established? |
540 // If BeginMainFrame is on the critical path, we want to try and prevent | 598 if (AnyThread().awaiting_touch_start_response) { |
541 // timers and loading tasks from running if we think they might be | 599 // No, so arrange for compositor tasks to be run at the highest priority. |
542 // expensive. | 600 return UseCase::TOUCHSTART; |
601 } | |
602 // Yes scrolling has been established. If BeginMainFrame is on the critical | |
603 // path, compositor tasks need to be prioritized, otherwise now might be a | |
604 // good time to run potentially expensive work. | |
543 // TODO(skyostil): Consider removing in_idle_period_ and | 605 // TODO(skyostil): Consider removing in_idle_period_ and |
544 // HadAnIdlePeriodRecently() unless we need them here. | 606 // HadAnIdlePeriodRecently() unless we need them here. |
545 if (AnyThread().timer_tasks_seem_expensive_ && | 607 if (AnyThread().begin_main_frame_on_critical_path) { |
546 AnyThread().begin_main_frame_on_critical_path_) { | 608 return UseCase::MAIN_THREAD_GESTURE; |
547 return Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY; | 609 } else { |
610 return UseCase::COMPOSITOR_GESTURE; | |
548 } | 611 } |
549 return Policy::COMPOSITOR_PRIORITY; | |
550 } | 612 } |
551 | 613 |
552 if (AnyThread().rails_loading_priority_deadline_ > now) { | 614 if (AnyThread().rails_loading_priority_deadline > now) { |
553 *new_policy_duration = AnyThread().rails_loading_priority_deadline_ - now; | 615 *expected_use_case_duration = |
554 return Policy::LOADING_PRIORITY; | 616 AnyThread().rails_loading_priority_deadline - now; |
617 return UseCase::LOADING; | |
555 } | 618 } |
556 | 619 |
557 return Policy::NORMAL; | 620 return UseCase::NONE; |
558 } | |
559 | |
560 base::TimeDelta RendererSchedulerImpl::TimeLeftInInputEscalatedPolicy( | |
561 base::TimeTicks now) const { | |
562 any_thread_lock_.AssertAcquired(); | |
563 | |
564 base::TimeDelta escalated_priority_duration = | |
565 base::TimeDelta::FromMilliseconds(kPriorityEscalationAfterInputMillis); | |
566 | |
567 // If the input event is still pending, go into input prioritized policy | |
568 // and check again later. | |
569 if (AnyThread().pending_main_thread_input_event_count_ > 0) | |
570 return escalated_priority_duration; | |
571 if (AnyThread().last_input_signal_time_.is_null() || | |
572 AnyThread().last_input_signal_time_ + escalated_priority_duration < now) { | |
573 return base::TimeDelta(); | |
574 } | |
575 return AnyThread().last_input_signal_time_ + escalated_priority_duration - | |
576 now; | |
577 } | 621 } |
578 | 622 |
579 bool RendererSchedulerImpl::CanEnterLongIdlePeriod( | 623 bool RendererSchedulerImpl::CanEnterLongIdlePeriod( |
580 base::TimeTicks now, | 624 base::TimeTicks now, |
581 base::TimeDelta* next_long_idle_period_delay_out) { | 625 base::TimeDelta* next_long_idle_period_delay_out) { |
582 helper_.CheckOnValidThread(); | 626 helper_.CheckOnValidThread(); |
583 | 627 |
584 MaybeUpdatePolicy(); | 628 MaybeUpdatePolicy(); |
585 if (MainThreadOnly().current_policy_ == Policy::TOUCHSTART_PRIORITY) { | 629 if (MainThreadOnly().current_use_case == UseCase::TOUCHSTART) { |
586 // Don't start a long idle task in touch start priority, try again when | 630 // Don't start a long idle task in touch start priority, try again when |
587 // the policy is scheduled to end. | 631 // the policy is scheduled to end. |
588 *next_long_idle_period_delay_out = | 632 *next_long_idle_period_delay_out = |
589 MainThreadOnly().current_policy_expiration_time_ - now; | 633 MainThreadOnly().current_policy_expiration_time - now; |
590 return false; | 634 return false; |
591 } | 635 } |
592 return true; | 636 return true; |
593 } | 637 } |
594 | 638 |
595 SchedulerHelper* RendererSchedulerImpl::GetSchedulerHelperForTesting() { | 639 SchedulerHelper* RendererSchedulerImpl::GetSchedulerHelperForTesting() { |
596 return &helper_; | 640 return &helper_; |
597 } | 641 } |
598 | 642 |
599 void RendererSchedulerImpl::SuspendTimerQueue() { | 643 void RendererSchedulerImpl::SuspendTimerQueue() { |
600 MainThreadOnly().timer_queue_suspend_count_++; | 644 MainThreadOnly().timer_queue_suspend_count++; |
601 ForceUpdatePolicy(); | 645 ForceUpdatePolicy(); |
602 DCHECK(!timer_task_runner_->IsQueueEnabled()); | 646 DCHECK(!timer_task_runner_->IsQueueEnabled()); |
603 } | 647 } |
604 | 648 |
605 void RendererSchedulerImpl::ResumeTimerQueue() { | 649 void RendererSchedulerImpl::ResumeTimerQueue() { |
606 MainThreadOnly().timer_queue_suspend_count_--; | 650 MainThreadOnly().timer_queue_suspend_count--; |
607 DCHECK_GE(MainThreadOnly().timer_queue_suspend_count_, 0); | 651 DCHECK_GE(MainThreadOnly().timer_queue_suspend_count, 0); |
608 ForceUpdatePolicy(); | 652 ForceUpdatePolicy(); |
609 } | 653 } |
610 | 654 |
611 // static | |
612 const char* RendererSchedulerImpl::PolicyToString(Policy policy) { | |
613 switch (policy) { | |
614 case Policy::NORMAL: | |
615 return "normal"; | |
616 case Policy::COMPOSITOR_PRIORITY: | |
617 return "compositor"; | |
618 case Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY: | |
619 return "compositor_critical_path"; | |
620 case Policy::TOUCHSTART_PRIORITY: | |
621 return "touchstart"; | |
622 case Policy::LOADING_PRIORITY: | |
623 return "loading"; | |
624 default: | |
625 NOTREACHED(); | |
626 return nullptr; | |
627 } | |
628 } | |
629 | |
630 scoped_refptr<base::trace_event::ConvertableToTraceFormat> | 655 scoped_refptr<base::trace_event::ConvertableToTraceFormat> |
631 RendererSchedulerImpl::AsValue(base::TimeTicks optional_now) const { | 656 RendererSchedulerImpl::AsValue(base::TimeTicks optional_now) const { |
632 base::AutoLock lock(any_thread_lock_); | 657 base::AutoLock lock(any_thread_lock_); |
633 return AsValueLocked(optional_now); | 658 return AsValueLocked(optional_now); |
634 } | 659 } |
635 | 660 |
636 scoped_refptr<base::trace_event::ConvertableToTraceFormat> | 661 scoped_refptr<base::trace_event::ConvertableToTraceFormat> |
637 RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const { | 662 RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const { |
638 helper_.CheckOnValidThread(); | 663 helper_.CheckOnValidThread(); |
639 any_thread_lock_.AssertAcquired(); | 664 any_thread_lock_.AssertAcquired(); |
640 | 665 |
641 if (optional_now.is_null()) | 666 if (optional_now.is_null()) |
642 optional_now = helper_.Now(); | 667 optional_now = helper_.Now(); |
643 scoped_refptr<base::trace_event::TracedValue> state = | 668 scoped_refptr<base::trace_event::TracedValue> state = |
644 new base::trace_event::TracedValue(); | 669 new base::trace_event::TracedValue(); |
645 | 670 |
646 state->SetString("current_policy", | 671 state->SetString("current_use_case", |
647 PolicyToString(MainThreadOnly().current_policy_)); | 672 UseCaseToString(MainThreadOnly().current_use_case)); |
673 state->SetBoolean("loading_tasks_seem_expensive", | |
674 MainThreadOnly().loading_tasks_seem_expensive); | |
675 state->SetBoolean("timer_tasks_seem_expensive", | |
676 MainThreadOnly().timer_tasks_seem_expensive); | |
677 state->SetBoolean("touchstart_expected_soon", | |
678 MainThreadOnly().touchstart_expected_soon); | |
648 state->SetString("idle_period_state", | 679 state->SetString("idle_period_state", |
649 IdleHelper::IdlePeriodStateToString( | 680 IdleHelper::IdlePeriodStateToString( |
650 idle_helper_.SchedulerIdlePeriodState())); | 681 idle_helper_.SchedulerIdlePeriodState())); |
651 state->SetBoolean("renderer_hidden", MainThreadOnly().renderer_hidden_); | 682 state->SetBoolean("renderer_hidden", MainThreadOnly().renderer_hidden); |
652 state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF()); | 683 state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF()); |
653 state->SetDouble("last_input_signal_time", | 684 state->SetDouble( |
654 (AnyThread().last_input_signal_time_ - base::TimeTicks()) | 685 "rails_loading_priority_deadline", |
686 (AnyThread().rails_loading_priority_deadline - base::TimeTicks()) | |
687 .InMillisecondsF()); | |
688 state->SetDouble("last_idle_period_end_time", | |
689 (AnyThread().last_idle_period_end_time - base::TimeTicks()) | |
655 .InMillisecondsF()); | 690 .InMillisecondsF()); |
656 state->SetDouble("rails_loading_priority_deadline", | 691 state->SetBoolean("awaiting_touch_start_response", |
657 (AnyThread().rails_loading_priority_deadline_ - | 692 AnyThread().awaiting_touch_start_response); |
658 base::TimeTicks()).InMillisecondsF()); | 693 state->SetBoolean("begin_main_frame_on_critical_path", |
659 state->SetDouble("last_idle_period_end_time", | 694 AnyThread().begin_main_frame_on_critical_path); |
660 (AnyThread().last_idle_period_end_time_ - base::TimeTicks()) | 695 state->SetDouble("expected_loading_task_duration", |
696 MainThreadOnly() | |
697 .loading_task_cost_estimator.expected_task_duration() | |
661 .InMillisecondsF()); | 698 .InMillisecondsF()); |
662 state->SetInteger("pending_main_thread_input_event_count", | |
663 AnyThread().pending_main_thread_input_event_count_); | |
664 state->SetBoolean("awaiting_touch_start_response", | |
665 AnyThread().awaiting_touch_start_response_); | |
666 state->SetBoolean("begin_main_frame_on_critical_path", | |
667 AnyThread().begin_main_frame_on_critical_path_); | |
668 state->SetDouble("expected_timer_task_duration", | 699 state->SetDouble("expected_timer_task_duration", |
669 MainThreadOnly() | 700 MainThreadOnly() |
670 .timer_task_cost_estimator_.expected_task_duration() | 701 .timer_task_cost_estimator.expected_task_duration() |
671 .InMillisecondsF()); | 702 .InMillisecondsF()); |
672 // TODO(skyostil): Can we somehow trace how accurate these estimates were? | 703 // TODO(skyostil): Can we somehow trace how accurate these estimates were? |
673 state->SetDouble( | 704 state->SetDouble( |
674 "expected_short_idle_period_duration", | 705 "expected_short_idle_period_duration", |
675 MainThreadOnly().expected_short_idle_period_duration_.InMillisecondsF()); | 706 MainThreadOnly().expected_short_idle_period_duration.InMillisecondsF()); |
676 state->SetBoolean("timer_tasks_seem_expensive", | 707 state->SetDouble( |
677 AnyThread().timer_tasks_seem_expensive_); | 708 "estimated_next_frame_begin", |
678 state->SetDouble("estimated_next_frame_begin", | 709 (MainThreadOnly().estimated_next_frame_begin - base::TimeTicks()) |
679 (MainThreadOnly().estimated_next_frame_begin_ - | 710 .InMillisecondsF()); |
680 base::TimeTicks()).InMillisecondsF()); | 711 state->SetBoolean("in_idle_period", AnyThread().in_idle_period); |
681 state->SetBoolean("in_idle_period", AnyThread().in_idle_period_); | 712 AnyThread().user_model.AsValueInto(state.get()); |
682 | 713 |
683 return state; | 714 return state; |
684 } | 715 } |
685 | 716 |
686 void RendererSchedulerImpl::OnIdlePeriodStarted() { | 717 void RendererSchedulerImpl::OnIdlePeriodStarted() { |
687 base::AutoLock lock(any_thread_lock_); | 718 base::AutoLock lock(any_thread_lock_); |
688 AnyThread().in_idle_period_ = true; | 719 AnyThread().in_idle_period = true; |
689 UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED); | 720 UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED); |
690 } | 721 } |
691 | 722 |
692 void RendererSchedulerImpl::OnIdlePeriodEnded() { | 723 void RendererSchedulerImpl::OnIdlePeriodEnded() { |
693 base::AutoLock lock(any_thread_lock_); | 724 base::AutoLock lock(any_thread_lock_); |
694 AnyThread().last_idle_period_end_time_ = helper_.Now(); | 725 AnyThread().last_idle_period_end_time = helper_.Now(); |
695 AnyThread().in_idle_period_ = false; | 726 AnyThread().in_idle_period = false; |
696 UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED); | 727 UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED); |
697 } | 728 } |
698 | 729 |
699 void RendererSchedulerImpl::OnPageLoadStarted() { | 730 void RendererSchedulerImpl::OnPageLoadStarted() { |
700 base::AutoLock lock(any_thread_lock_); | 731 base::AutoLock lock(any_thread_lock_); |
701 AnyThread().rails_loading_priority_deadline_ = | 732 AnyThread().rails_loading_priority_deadline = |
702 helper_.Now() + base::TimeDelta::FromMilliseconds( | 733 helper_.Now() + base::TimeDelta::FromMilliseconds( |
703 kRailsInitialLoadingPrioritizationMillis); | 734 kRailsInitialLoadingPrioritizationMillis); |
704 UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED); | 735 UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED); |
705 } | 736 } |
706 | 737 |
707 bool RendererSchedulerImpl::HadAnIdlePeriodRecently(base::TimeTicks now) const { | 738 bool RendererSchedulerImpl::HadAnIdlePeriodRecently(base::TimeTicks now) const { |
708 return (now - AnyThread().last_idle_period_end_time_) <= | 739 return (now - AnyThread().last_idle_period_end_time) <= |
709 base::TimeDelta::FromMilliseconds( | 740 base::TimeDelta::FromMilliseconds( |
710 kIdlePeriodStarvationThresholdMillis); | 741 kIdlePeriodStarvationThresholdMillis); |
711 } | 742 } |
712 | 743 |
713 } // namespace scheduler | 744 } // namespace scheduler |
OLD | NEW |