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

Side by Side Diff: components/scheduler/renderer/renderer_scheduler_impl.cc

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

Powered by Google App Engine
This is Rietveld 408576698