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

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: Rebase + remove some unwanted changes 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;
Sami 2015/08/26 13:38:01 Any reason for tweaking these in this way?
alex clarke (OOO till 29th) 2015/08/27 12:02:51 Yes, I was hoping for a more pessimistic result th
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
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 base::TimeDelta::FromMilliseconds(16));
Sami 2015/08/26 13:38:01 BeginFrameArgs::DefaultInterval()?
alex clarke (OOO till 29th) 2015/08/27 12:02:51 Done.
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,
93 kLoadingTaskEstimationPercentile),
94 timer_task_cost_estimator_(kTimerTaskEstimationSampleCount,
79 kTimerTaskEstimationPercentile), 95 kTimerTaskEstimationPercentile),
80 short_idle_period_duration_(kShortIdlePeriodDurationSampleCount), 96 short_idle_period_duration_(kShortIdlePeriodDurationSampleCount),
81 current_policy_(Policy::NORMAL), 97 current_use_case_(UseCase::NOT_SCROLLING),
82 timer_queue_suspend_count_(0), 98 timer_queue_suspend_count_(0),
83 renderer_hidden_(false), 99 renderer_hidden_(false),
84 was_shutdown_(false) {} 100 was_shutdown_(false),
101 loading_tasks_seem_expensive_(false),
102 timer_tasks_seem_expensive_(false) {}
85 103
86 RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {} 104 RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {}
87 105
88 RendererSchedulerImpl::AnyThread::AnyThread() 106 RendererSchedulerImpl::AnyThread::AnyThread()
89 : pending_main_thread_input_event_count_(0), 107 : pending_main_thread_input_event_count_(0),
90 awaiting_touch_start_response_(false), 108 awaiting_touch_start_response_(false),
91 in_idle_period_(false), 109 in_idle_period_(false),
92 begin_main_frame_on_critical_path_(false), 110 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 } 114 }
98 115
99 RendererSchedulerImpl::CompositorThreadOnly::~CompositorThreadOnly() { 116 RendererSchedulerImpl::CompositorThreadOnly::~CompositorThreadOnly() {
100 } 117 }
101 118
102 void RendererSchedulerImpl::Shutdown() { 119 void RendererSchedulerImpl::Shutdown() {
103 helper_.Shutdown(); 120 helper_.Shutdown();
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 186
170 base::TimeTicks now(helper_.Now()); 187 base::TimeTicks now(helper_.Now());
171 if (now < MainThreadOnly().estimated_next_frame_begin_) { 188 if (now < MainThreadOnly().estimated_next_frame_begin_) {
172 // TODO(rmcilroy): Consider reducing the idle period based on the runtime of 189 // 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) 190 // the next pending delayed tasks (as currently done in for long idle times)
174 idle_helper_.StartIdlePeriod( 191 idle_helper_.StartIdlePeriod(
175 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, now, 192 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, now,
176 MainThreadOnly().estimated_next_frame_begin_); 193 MainThreadOnly().estimated_next_frame_begin_);
177 MainThreadOnly().short_idle_period_duration_.InsertSample( 194 MainThreadOnly().short_idle_period_duration_.InsertSample(
178 MainThreadOnly().estimated_next_frame_begin_ - now); 195 MainThreadOnly().estimated_next_frame_begin_ - now);
179 MainThreadOnly().expected_short_idle_period_duration_ = 196 } else {
180 MainThreadOnly().short_idle_period_duration_.Percentile( 197 // There was no idle time :(
181 kShortIdlePeriodDurationPercentile); 198 MainThreadOnly().short_idle_period_duration_.InsertSample(
199 base::TimeDelta());
182 } 200 }
201
202 MainThreadOnly().expected_short_idle_period_duration_ =
203 MainThreadOnly().short_idle_period_duration_.Percentile(
204 kShortIdlePeriodDurationPercentile);
183 } 205 }
184 206
185 void RendererSchedulerImpl::BeginFrameNotExpectedSoon() { 207 void RendererSchedulerImpl::BeginFrameNotExpectedSoon() {
186 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), 208 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
187 "RendererSchedulerImpl::BeginFrameNotExpectedSoon"); 209 "RendererSchedulerImpl::BeginFrameNotExpectedSoon");
188 helper_.CheckOnValidThread(); 210 helper_.CheckOnValidThread();
189 if (helper_.IsShutdown()) 211 if (helper_.IsShutdown())
190 return; 212 return;
191 213
192 idle_helper_.EnableLongIdlePeriod(); 214 idle_helper_.EnableLongIdlePeriod();
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 } 293 }
272 294
273 void RendererSchedulerImpl::DidAnimateForInputOnCompositorThread() { 295 void RendererSchedulerImpl::DidAnimateForInputOnCompositorThread() {
274 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), 296 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
275 "RendererSchedulerImpl::DidAnimateForInputOnCompositorThread"); 297 "RendererSchedulerImpl::DidAnimateForInputOnCompositorThread");
276 UpdateForInputEventOnCompositorThread( 298 UpdateForInputEventOnCompositorThread(
277 blink::WebInputEvent::Undefined, 299 blink::WebInputEvent::Undefined,
278 InputEventState::EVENT_CONSUMED_BY_COMPOSITOR); 300 InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
279 } 301 }
280 302
303 const char* WebInputEventToString(blink::WebInputEvent::Type type) {
304 #define CASE_TYPE(t) \
305 case blink::WebInputEvent::t: \
306 return #t
307 switch (type) {
308 CASE_TYPE(Undefined);
Sami 2015/08/26 13:38:01 Instead of duplicating this from RenderWidget, cou
alex clarke (OOO till 29th) 2015/08/27 12:02:51 Acknowledged.
309 CASE_TYPE(MouseDown);
310 CASE_TYPE(MouseUp);
311 CASE_TYPE(MouseMove);
312 CASE_TYPE(MouseEnter);
313 CASE_TYPE(MouseLeave);
314 CASE_TYPE(ContextMenu);
315 CASE_TYPE(MouseWheel);
316 CASE_TYPE(RawKeyDown);
317 CASE_TYPE(KeyDown);
318 CASE_TYPE(KeyUp);
319 CASE_TYPE(Char);
320 CASE_TYPE(GestureScrollBegin);
321 CASE_TYPE(GestureScrollEnd);
322 CASE_TYPE(GestureScrollUpdate);
323 CASE_TYPE(GestureFlingStart);
324 CASE_TYPE(GestureFlingCancel);
325 CASE_TYPE(GestureShowPress);
326 CASE_TYPE(GestureTap);
327 CASE_TYPE(GestureTapUnconfirmed);
328 CASE_TYPE(GestureTapDown);
329 CASE_TYPE(GestureTapCancel);
330 CASE_TYPE(GestureDoubleTap);
331 CASE_TYPE(GestureTwoFingerTap);
332 CASE_TYPE(GestureLongPress);
333 CASE_TYPE(GestureLongTap);
334 CASE_TYPE(GesturePinchBegin);
335 CASE_TYPE(GesturePinchEnd);
336 CASE_TYPE(GesturePinchUpdate);
337 CASE_TYPE(TouchStart);
338 CASE_TYPE(TouchMove);
339 CASE_TYPE(TouchEnd);
340 CASE_TYPE(TouchCancel);
341 }
342 return "";
343 }
344
281 void RendererSchedulerImpl::UpdateForInputEventOnCompositorThread( 345 void RendererSchedulerImpl::UpdateForInputEventOnCompositorThread(
282 blink::WebInputEvent::Type type, 346 blink::WebInputEvent::Type type,
283 InputEventState input_event_state) { 347 InputEventState input_event_state) {
284 base::AutoLock lock(any_thread_lock_); 348 base::AutoLock lock(any_thread_lock_);
285 base::TimeTicks now = helper_.Now(); 349 base::TimeTicks now = helper_.Now();
286 bool was_in_compositor_priority = InputSignalsSuggestCompositorPriority(now); 350 bool already_scrolling = InputSignalsSuggestScrolling(now);
287 bool was_awaiting_touch_start_response = 351 bool was_awaiting_touch_start_response =
288 AnyThread().awaiting_touch_start_response_; 352 AnyThread().awaiting_touch_start_response_;
289 353
290 if (type) { 354 if (type) {
291 switch (type) { 355 switch (type) {
292 case blink::WebInputEvent::TouchStart: 356 case blink::WebInputEvent::TouchStart:
293 AnyThread().awaiting_touch_start_response_ = true; 357 AnyThread().awaiting_touch_start_response_ = true;
358 AnyThread().last_touchstart_time_ = now;
294 break; 359 break;
295 360
296 case blink::WebInputEvent::TouchMove: 361 case blink::WebInputEvent::TouchMove:
297 // Observation of consecutive touchmoves is a strong signal that the 362 // Observation of consecutive touchmoves is a strong signal that the
298 // page is consuming the touch sequence, in which case touchstart 363 // page is consuming the touch sequence, in which case touchstart
299 // response prioritization is no longer necessary. Otherwise, the 364 // response prioritization is no longer necessary. Otherwise, the
300 // initial touchmove should preserve the touchstart response pending 365 // initial touchmove should preserve the touchstart response pending
301 // state. 366 // state.
302 if (AnyThread().awaiting_touch_start_response_ && 367 if (AnyThread().awaiting_touch_start_response_ &&
303 CompositorThreadOnly().last_input_type_ == 368 CompositorThreadOnly().last_input_type_ ==
(...skipping 11 matching lines...) Expand all
315 // meaningful touchstart response and should not impact task priority. 380 // meaningful touchstart response and should not impact task priority.
316 break; 381 break;
317 382
318 default: 383 default:
319 AnyThread().awaiting_touch_start_response_ = false; 384 AnyThread().awaiting_touch_start_response_ = false;
320 break; 385 break;
321 } 386 }
322 } 387 }
323 388
324 // Avoid unnecessary policy updates, while in compositor priority. 389 // Avoid unnecessary policy updates, while in compositor priority.
325 if (!was_in_compositor_priority || 390 if (!already_scrolling ||
326 was_awaiting_touch_start_response != 391 was_awaiting_touch_start_response !=
327 AnyThread().awaiting_touch_start_response_) { 392 AnyThread().awaiting_touch_start_response_) {
328 EnsureUrgentPolicyUpdatePostedOnMainThread(FROM_HERE); 393 EnsureUrgentPolicyUpdatePostedOnMainThread(FROM_HERE);
329 } 394 }
330 AnyThread().last_input_signal_time_ = now; 395 AnyThread().last_input_signal_time_ = now;
331 CompositorThreadOnly().last_input_type_ = type; 396 CompositorThreadOnly().last_input_type_ = type;
332 397
333 if (input_event_state == InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD) 398 if (input_event_state == InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD) {
399 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
400 "InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD", "type",
401 WebInputEventToString(type));
334 AnyThread().pending_main_thread_input_event_count_++; 402 AnyThread().pending_main_thread_input_event_count_++;
403 }
335 } 404 }
336 405
337 void RendererSchedulerImpl::DidHandleInputEventOnMainThread( 406 void RendererSchedulerImpl::DidHandleInputEventOnMainThread(
338 const blink::WebInputEvent& web_input_event) { 407 const blink::WebInputEvent& web_input_event) {
339 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), 408 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
340 "RendererSchedulerImpl::DidHandleInputEventOnMainThread"); 409 "RendererSchedulerImpl::DidHandleInputEventOnMainThread");
341 helper_.CheckOnValidThread(); 410 helper_.CheckOnValidThread();
342 if (ShouldPrioritizeInputEvent(web_input_event)) { 411 if (ShouldPrioritizeInputEvent(web_input_event)) {
343 base::AutoLock lock(any_thread_lock_); 412 base::AutoLock lock(any_thread_lock_);
344 AnyThread().last_input_signal_time_ = helper_.Now(); 413 AnyThread().last_input_signal_time_ = helper_.Now();
345 if (AnyThread().pending_main_thread_input_event_count_ > 0) 414 if (AnyThread().pending_main_thread_input_event_count_ > 0)
346 AnyThread().pending_main_thread_input_event_count_--; 415 AnyThread().pending_main_thread_input_event_count_--;
347 } 416 }
348 } 417 }
349 418
350 bool RendererSchedulerImpl::IsHighPriorityWorkAnticipated() { 419 bool RendererSchedulerImpl::IsHighPriorityWorkAnticipated() {
351 helper_.CheckOnValidThread(); 420 helper_.CheckOnValidThread();
352 if (helper_.IsShutdown()) 421 if (helper_.IsShutdown())
353 return false; 422 return false;
354 423
355 MaybeUpdatePolicy(); 424 MaybeUpdatePolicy();
356 // The touchstart and compositor policies indicate a strong likelihood of 425 // The touchstart and main-thread scrolling states indicate a strong
357 // high-priority work in the near future. 426 // likelihood of high-priority work in the near future.
358 return MainThreadOnly().current_policy_ == Policy::COMPOSITOR_PRIORITY || 427 UseCase use_case = MainThreadOnly().current_use_case_;
359 MainThreadOnly().current_policy_ == 428 return MainThreadOnly().scroll_expected_soon_ ||
360 Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY || 429 use_case == UseCase::MAINTHREAD_SCROLLING ||
361 MainThreadOnly().current_policy_ == Policy::TOUCHSTART_PRIORITY; 430 use_case == UseCase::TOUCHSTART;
362 } 431 }
363 432
364 bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() { 433 bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() {
365 helper_.CheckOnValidThread(); 434 helper_.CheckOnValidThread();
366 if (helper_.IsShutdown()) 435 if (helper_.IsShutdown())
367 return false; 436 return false;
368 437
369 MaybeUpdatePolicy(); 438 MaybeUpdatePolicy();
370 // We only yield if we are in the compositor priority and there is compositor 439 // 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. 440 // one soon (touch start).
372 // Note: even though the control queue is higher priority we don't yield for 441 // 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 442 // 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. 443 // intended to run before the next task, not interrupt the tasks.
375 switch (MainThreadOnly().current_policy_) { 444 switch (MainThreadOnly().current_use_case_) {
376 case Policy::NORMAL: 445 case UseCase::NOT_SCROLLING:
Sami 2015/08/26 13:38:01 Could we not be expecting a scroll in this state?
alex clarke (OOO till 29th) 2015/08/27 12:02:51 Yeah we could. Maybe we should yeild in that situ
377 return false; 446 return false;
378 447
379 case Policy::COMPOSITOR_PRIORITY: 448 case UseCase::COMPOSITOR_SCROLLING:
449 return MainThreadOnly().scroll_expected_soon_;
450
451 case UseCase::MAINTHREAD_SCROLLING:
380 return !compositor_task_runner_->IsQueueEmpty(); 452 return !compositor_task_runner_->IsQueueEmpty();
381 453
382 case Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY: 454 case UseCase::TOUCHSTART:
383 return !compositor_task_runner_->IsQueueEmpty();
384
385 case Policy::TOUCHSTART_PRIORITY:
386 return true; 455 return true;
387 456
388 case Policy::LOADING_PRIORITY: 457 case UseCase::LOADING:
389 return false; 458 return false;
390 459
391 default: 460 default:
392 NOTREACHED(); 461 NOTREACHED();
393 return false; 462 return false;
394 } 463 }
395 } 464 }
396 465
397 base::TimeTicks RendererSchedulerImpl::CurrentIdleTaskDeadlineForTesting() 466 base::TimeTicks RendererSchedulerImpl::CurrentIdleTaskDeadlineForTesting()
398 const { 467 const {
(...skipping 21 matching lines...) Expand all
420 void RendererSchedulerImpl::UpdatePolicy() { 489 void RendererSchedulerImpl::UpdatePolicy() {
421 base::AutoLock lock(any_thread_lock_); 490 base::AutoLock lock(any_thread_lock_);
422 UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED); 491 UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED);
423 } 492 }
424 493
425 void RendererSchedulerImpl::ForceUpdatePolicy() { 494 void RendererSchedulerImpl::ForceUpdatePolicy() {
426 base::AutoLock lock(any_thread_lock_); 495 base::AutoLock lock(any_thread_lock_);
427 UpdatePolicyLocked(UpdateType::FORCE_UPDATE); 496 UpdatePolicyLocked(UpdateType::FORCE_UPDATE);
428 } 497 }
429 498
499 bool RendererSchedulerImpl::ScrollExpectedSoon(
500 UseCase use_case,
501 const base::TimeTicks now,
502 base::TimeDelta* new_policy_duration) const {
503 if (use_case == UseCase::NOT_SCROLLING) {
504 // If we've scrolled recently then future scrolling is likely.
505 base::TimeDelta expect_subsequent_input_for =
506 base::TimeDelta::FromMilliseconds(kExpectSubsequentInputMillis);
507 if (AnyThread().last_input_signal_time_.is_null() ||
508 AnyThread().last_input_signal_time_ + expect_subsequent_input_for <=
509 now) {
510 return false;
511 }
512 *new_policy_duration =
513 AnyThread().last_input_signal_time_ + expect_subsequent_input_for - now;
514 return true;
515 }
516
517 if (use_case == UseCase::COMPOSITOR_SCROLLING) {
518 // If we've only just started scrolling then, then future scrolling is
519 // unlikely.
520 base::TimeDelta minimum_typical_scroll_duration =
521 base::TimeDelta::FromMilliseconds(kMinimumTypicalScrollDurationMillis);
522 if (AnyThread().last_touchstart_time_.is_null() ||
Sami 2015/08/26 13:38:01 Touchstart doesn't get sent if there are no touch
alex clarke (OOO till 29th) 2015/08/27 12:02:51 Maybe this function is badly named then (see comme
523 AnyThread().last_touchstart_time_ + minimum_typical_scroll_duration <=
524 now) {
525 return true;
526 }
527 *new_policy_duration = AnyThread().last_touchstart_time_ +
528 minimum_typical_scroll_duration - now;
529 return false;
530 }
531 return false;
Sami 2015/08/26 13:38:01 Should we always return true for main thread scrol
alex clarke (OOO till 29th) 2015/08/27 12:02:51 Good question. I think that depends on what we wa
532 }
533
430 void RendererSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) { 534 void RendererSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
431 helper_.CheckOnValidThread(); 535 helper_.CheckOnValidThread();
432 any_thread_lock_.AssertAcquired(); 536 any_thread_lock_.AssertAcquired();
433 if (helper_.IsShutdown()) 537 if (helper_.IsShutdown())
434 return; 538 return;
435 539
436 base::TimeTicks now = helper_.Now(); 540 base::TimeTicks now = helper_.Now();
437 policy_may_need_update_.SetWhileLocked(false); 541 policy_may_need_update_.SetWhileLocked(false);
438 542
439 AnyThread().timer_tasks_seem_expensive_ = 543 base::TimeDelta new_policy_duration;
440 MainThreadOnly().expected_short_idle_period_duration_ > 544 UseCase use_case = ComputeCurrentUseCase(now, &new_policy_duration);
441 base::TimeDelta() && 545
546 // Adjust the policy duration if |scroll_expected_soon| is likely to change.
547 bool scroll_expected_soon = ScrollExpectedSoon(use_case,
548 now,
549 &new_policy_duration);
550 bool loading_tasks_seem_expensive =
551 MainThreadOnly().loading_task_cost_estimator_.expected_task_duration() >
552 MainThreadOnly().expected_short_idle_period_duration_;
553 bool timer_tasks_seem_expensive =
442 MainThreadOnly().timer_task_cost_estimator_.expected_task_duration() > 554 MainThreadOnly().timer_task_cost_estimator_.expected_task_duration() >
443 MainThreadOnly().expected_short_idle_period_duration_; 555 MainThreadOnly().expected_short_idle_period_duration_;
556 MainThreadOnly().scroll_expected_soon_ = scroll_expected_soon;
557 MainThreadOnly().loading_tasks_seem_expensive_ = loading_tasks_seem_expensive;
558 MainThreadOnly().timer_tasks_seem_expensive_ = timer_tasks_seem_expensive;
444 559
445 base::TimeDelta new_policy_duration;
446 Policy new_policy = ComputeNewPolicy(now, &new_policy_duration);
447 if (new_policy_duration > base::TimeDelta()) { 560 if (new_policy_duration > base::TimeDelta()) {
448 MainThreadOnly().current_policy_expiration_time_ = 561 MainThreadOnly().current_policy_expiration_time_ =
449 now + new_policy_duration; 562 now + new_policy_duration;
450 delayed_update_policy_runner_.SetDeadline(FROM_HERE, new_policy_duration, 563 delayed_update_policy_runner_.SetDeadline(FROM_HERE, new_policy_duration,
451 now); 564 now);
452 } else { 565 } else {
453 MainThreadOnly().current_policy_expiration_time_ = base::TimeTicks(); 566 MainThreadOnly().current_policy_expiration_time_ = base::TimeTicks();
454 } 567 }
455 568
456 if (update_type == UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED && 569 Policy new_policy;
457 new_policy == MainThreadOnly().current_policy_) 570 bool block_expensive_tasks = false;
458 return; 571 switch (use_case) {
572 case UseCase::COMPOSITOR_SCROLLING:
573 if (scroll_expected_soon)
574 block_expensive_tasks = true;
575 else
576 new_policy.loading_queue_priority_ = TaskQueue::HIGH_PRIORITY;
577 break;
459 578
460 TaskQueue::QueuePriority compositor_queue_priority = 579 case UseCase::MAINTHREAD_SCROLLING:
461 TaskQueue::NORMAL_PRIORITY; 580 new_policy.compositor_queue_priority_ = TaskQueue::HIGH_PRIORITY;
462 TaskQueue::QueuePriority loading_queue_priority = TaskQueue::NORMAL_PRIORITY; 581 block_expensive_tasks = true;
463 TaskQueue::QueuePriority timer_queue_priority = 582 break;
464 MainThreadOnly().timer_queue_suspend_count_ != 0
465 ? TaskQueue::DISABLED_PRIORITY
466 : TaskQueue::NORMAL_PRIORITY;
467 583
468 switch (new_policy) { 584 case UseCase::TOUCHSTART:
469 case Policy::COMPOSITOR_PRIORITY: 585 new_policy.compositor_queue_priority_ = TaskQueue::HIGH_PRIORITY;
470 compositor_queue_priority = TaskQueue::HIGH_PRIORITY; 586 new_policy.loading_queue_priority_ = TaskQueue::DISABLED_PRIORITY;
587 new_policy.timer_queue_priority_ = TaskQueue::DISABLED_PRIORITY;
Sami 2015/08/26 13:38:01 block_expensive_tasks = true?
alex clarke (OOO till 29th) 2015/08/27 12:02:51 We could do that, but it would be a nop. Do you st
Sami 2015/08/27 15:15:58 Yeah, I was thinking it would be better to have it
alex clarke (OOO till 29th) 2015/09/03 10:34:25 Done.
471 break; 588 break;
472 case Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY: 589
473 compositor_queue_priority = TaskQueue::HIGH_PRIORITY; 590 case UseCase::NOT_SCROLLING:
474 loading_queue_priority = TaskQueue::DISABLED_PRIORITY; 591 if (scroll_expected_soon)
475 timer_queue_priority = TaskQueue::DISABLED_PRIORITY; 592 block_expensive_tasks = true;
593 else
594 new_policy.loading_queue_priority_ = TaskQueue::HIGH_PRIORITY;
476 break; 595 break;
477 case Policy::TOUCHSTART_PRIORITY: 596
478 compositor_queue_priority = TaskQueue::HIGH_PRIORITY; 597 case UseCase::LOADING:
479 loading_queue_priority = TaskQueue::DISABLED_PRIORITY; 598 new_policy.loading_queue_priority_ = TaskQueue::HIGH_PRIORITY;
480 timer_queue_priority = TaskQueue::DISABLED_PRIORITY; 599 new_policy.timer_queue_priority_ = TaskQueue::HIGH_PRIORITY;
Sami 2015/08/26 13:38:01 Why are timers now high priority? They used to be
alex clarke (OOO till 29th) 2015/08/27 12:02:51 They don't need to be :)
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; 600 break;
491 default: 601 default:
492 NOTREACHED(); 602 NOTREACHED();
493 } 603 }
494 604
495 compositor_task_runner_->SetQueuePriority(compositor_queue_priority); 605 if (block_expensive_tasks && loading_tasks_seem_expensive)
496 loading_task_runner_->SetQueuePriority(loading_queue_priority); 606 new_policy.loading_queue_priority_ = TaskQueue::DISABLED_PRIORITY;
497 timer_task_runner_->SetQueuePriority(timer_queue_priority);
498 607
499 DCHECK(compositor_task_runner_->IsQueueEnabled()); 608 if ((block_expensive_tasks && timer_tasks_seem_expensive) ||
500 if (new_policy != Policy::TOUCHSTART_PRIORITY && 609 MainThreadOnly().timer_queue_suspend_count_ != 0)
501 new_policy != Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY) { 610 new_policy.timer_queue_priority_ = TaskQueue::DISABLED_PRIORITY;
502 DCHECK(loading_task_runner_->IsQueueEnabled());
503 }
504 MainThreadOnly().current_policy_ = new_policy;
505 611
612 // Tracing is done before the early out check, because it's quite possible we
613 // will otherwise miss this information in traces.
506 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( 614 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
507 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", 615 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler",
508 this, AsValueLocked(now)); 616 this, AsValueLocked(now));
617 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "use_case",
618 use_case);
509 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), 619 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
510 "RendererScheduler.policy", MainThreadOnly().current_policy_); 620 "RendererScheduler.loading_tasks_seem_expensive",
621 MainThreadOnly().loading_tasks_seem_expensive_);
511 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), 622 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
512 "RendererScheduler.timer_tasks_seem_expensive", 623 "RendererScheduler.timer_tasks_seem_expensive",
513 AnyThread().timer_tasks_seem_expensive_); 624 MainThreadOnly().timer_tasks_seem_expensive_);
625
626 if (update_type == UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED &&
627 use_case == MainThreadOnly().current_use_case_ &&
Sami 2015/08/26 13:38:01 Do we need to check if the use case changed? Could
alex clarke (OOO till 29th) 2015/08/27 12:02:51 Yeah I think we could do that.
628 new_policy == MainThreadOnly().current_policy_) {
629 return;
630 }
631
632 compositor_task_runner_->SetQueuePriority(
633 new_policy.compositor_queue_priority_);
634 loading_task_runner_->SetQueuePriority(new_policy.loading_queue_priority_);
635 timer_task_runner_->SetQueuePriority(new_policy.timer_queue_priority_);
636
637 DCHECK(compositor_task_runner_->IsQueueEnabled());
638 MainThreadOnly().current_use_case_ = use_case;
639 MainThreadOnly().current_policy_ = new_policy;
514 } 640 }
515 641
516 bool RendererSchedulerImpl::InputSignalsSuggestCompositorPriority( 642 bool RendererSchedulerImpl::InputSignalsSuggestScrolling(
517 base::TimeTicks now) const { 643 base::TimeTicks now) const {
518 base::TimeDelta unused_policy_duration; 644 base::TimeDelta unused_policy_duration;
519 switch (ComputeNewPolicy(now, &unused_policy_duration)) { 645 switch (ComputeCurrentUseCase(now, &unused_policy_duration)) {
520 case Policy::TOUCHSTART_PRIORITY: 646 case UseCase::COMPOSITOR_SCROLLING:
521 case Policy::COMPOSITOR_PRIORITY: 647 case UseCase::MAINTHREAD_SCROLLING:
522 case Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY: 648 case UseCase::TOUCHSTART:
523 return true; 649 return true;
524 650
525 default: 651 default:
526 break; 652 break;
527 } 653 }
528 return false; 654 return false;
529 } 655 }
530 656
531 RendererSchedulerImpl::Policy RendererSchedulerImpl::ComputeNewPolicy( 657 RendererSchedulerImpl::UseCase RendererSchedulerImpl::ComputeCurrentUseCase(
532 base::TimeTicks now, 658 base::TimeTicks now,
533 base::TimeDelta* new_policy_duration) const { 659 base::TimeDelta* new_policy_duration) const {
534 any_thread_lock_.AssertAcquired(); 660 any_thread_lock_.AssertAcquired();
535 // Above all else we want to be responsive to user input. 661 // Above all else we want to be responsive to user input.
536 *new_policy_duration = TimeLeftInInputEscalatedPolicy(now); 662 *new_policy_duration = TimeLeftInInputEscalatedPolicy(now);
537 if (*new_policy_duration > base::TimeDelta()) { 663 if (*new_policy_duration > base::TimeDelta()) {
538 if (AnyThread().awaiting_touch_start_response_) 664 // Has scrolling been fully established?
539 return Policy::TOUCHSTART_PRIORITY; 665 if (AnyThread().awaiting_touch_start_response_) {
540 // If BeginMainFrame is on the critical path, we want to try and prevent 666 // No., so arrange for compositor tasks to be run at the highest priority.
Sami 2015/08/26 13:38:01 typo: .
alex clarke (OOO till 29th) 2015/08/27 12:02:51 Done.
541 // timers and loading tasks from running if we think they might be 667 return UseCase::TOUCHSTART;
542 // expensive.
543 // TODO(skyostil): Consider removing in_idle_period_ and
Sami 2015/08/26 13:38:01 Wanna keep this todo since the code is still here?
alex clarke (OOO till 29th) 2015/08/27 12:02:51 Done.
544 // HadAnIdlePeriodRecently() unless we need them here.
545 if (AnyThread().timer_tasks_seem_expensive_ &&
546 AnyThread().begin_main_frame_on_critical_path_) {
547 return Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY;
548 } 668 }
549 return Policy::COMPOSITOR_PRIORITY; 669 // Yes scrolling has been established. If BeginMainFrame is on the critical
670 // path, compositor tasks need to be prioritized, otherwise now might be a
671 // good time to run potentially expensive work.
672 if (AnyThread().begin_main_frame_on_critical_path_) {
673 return UseCase::MAINTHREAD_SCROLLING;
674 } else {
675 return UseCase::COMPOSITOR_SCROLLING;
676 }
550 } 677 }
551 678
552 if (AnyThread().rails_loading_priority_deadline_ > now) { 679 if (AnyThread().rails_loading_priority_deadline_ > now) {
553 *new_policy_duration = AnyThread().rails_loading_priority_deadline_ - now; 680 *new_policy_duration = AnyThread().rails_loading_priority_deadline_ - now;
554 return Policy::LOADING_PRIORITY; 681 return UseCase::LOADING;
555 } 682 }
556 683
557 return Policy::NORMAL; 684 return UseCase::NOT_SCROLLING;
558 } 685 }
559 686
560 base::TimeDelta RendererSchedulerImpl::TimeLeftInInputEscalatedPolicy( 687 base::TimeDelta RendererSchedulerImpl::TimeLeftInInputEscalatedPolicy(
561 base::TimeTicks now) const { 688 base::TimeTicks now) const {
562 any_thread_lock_.AssertAcquired(); 689 any_thread_lock_.AssertAcquired();
563 690
564 base::TimeDelta escalated_priority_duration = 691 base::TimeDelta escalated_priority_duration =
565 base::TimeDelta::FromMilliseconds(kPriorityEscalationAfterInputMillis); 692 base::TimeDelta::FromMilliseconds(kPriorityEscalationAfterInputMillis);
566 693
567 // If the input event is still pending, go into input prioritized policy 694 // If the input event is still pending, go into input prioritized policy
568 // and check again later. 695 // and check again later.
569 if (AnyThread().pending_main_thread_input_event_count_ > 0) 696 if (AnyThread().pending_main_thread_input_event_count_ > 0)
570 return escalated_priority_duration; 697 return escalated_priority_duration;
571 if (AnyThread().last_input_signal_time_.is_null() || 698 if (AnyThread().last_input_signal_time_.is_null() ||
572 AnyThread().last_input_signal_time_ + escalated_priority_duration < now) { 699 AnyThread().last_input_signal_time_ + escalated_priority_duration < now) {
573 return base::TimeDelta(); 700 return base::TimeDelta();
574 } 701 }
575 return AnyThread().last_input_signal_time_ + escalated_priority_duration - 702 return AnyThread().last_input_signal_time_ + escalated_priority_duration -
576 now; 703 now;
577 } 704 }
578 705
579 bool RendererSchedulerImpl::CanEnterLongIdlePeriod( 706 bool RendererSchedulerImpl::CanEnterLongIdlePeriod(
580 base::TimeTicks now, 707 base::TimeTicks now,
581 base::TimeDelta* next_long_idle_period_delay_out) { 708 base::TimeDelta* next_long_idle_period_delay_out) {
582 helper_.CheckOnValidThread(); 709 helper_.CheckOnValidThread();
583 710
584 MaybeUpdatePolicy(); 711 MaybeUpdatePolicy();
585 if (MainThreadOnly().current_policy_ == Policy::TOUCHSTART_PRIORITY) { 712 if (MainThreadOnly().current_use_case_ == UseCase::TOUCHSTART) {
586 // Don't start a long idle task in touch start priority, try again when 713 // Don't start a long idle task in touch start priority, try again when
587 // the policy is scheduled to end. 714 // the policy is scheduled to end.
588 *next_long_idle_period_delay_out = 715 *next_long_idle_period_delay_out =
589 MainThreadOnly().current_policy_expiration_time_ - now; 716 MainThreadOnly().current_policy_expiration_time_ - now;
590 return false; 717 return false;
591 } 718 }
592 return true; 719 return true;
593 } 720 }
594 721
595 SchedulerHelper* RendererSchedulerImpl::GetSchedulerHelperForTesting() { 722 SchedulerHelper* RendererSchedulerImpl::GetSchedulerHelperForTesting() {
596 return &helper_; 723 return &helper_;
597 } 724 }
598 725
599 void RendererSchedulerImpl::SuspendTimerQueue() { 726 void RendererSchedulerImpl::SuspendTimerQueue() {
600 MainThreadOnly().timer_queue_suspend_count_++; 727 MainThreadOnly().timer_queue_suspend_count_++;
601 ForceUpdatePolicy(); 728 ForceUpdatePolicy();
602 DCHECK(!timer_task_runner_->IsQueueEnabled()); 729 DCHECK(!timer_task_runner_->IsQueueEnabled());
603 } 730 }
604 731
605 void RendererSchedulerImpl::ResumeTimerQueue() { 732 void RendererSchedulerImpl::ResumeTimerQueue() {
606 MainThreadOnly().timer_queue_suspend_count_--; 733 MainThreadOnly().timer_queue_suspend_count_--;
607 DCHECK_GE(MainThreadOnly().timer_queue_suspend_count_, 0); 734 DCHECK_GE(MainThreadOnly().timer_queue_suspend_count_, 0);
608 ForceUpdatePolicy(); 735 ForceUpdatePolicy();
609 } 736 }
610 737
611 // static 738 // static
612 const char* RendererSchedulerImpl::PolicyToString(Policy policy) { 739 const char* RendererSchedulerImpl::UseCaseToString(UseCase use_case) {
613 switch (policy) { 740 switch (use_case) {
614 case Policy::NORMAL: 741 case UseCase::NOT_SCROLLING:
615 return "normal"; 742 return "not_scrolling";
616 case Policy::COMPOSITOR_PRIORITY: 743 case UseCase::COMPOSITOR_SCROLLING:
617 return "compositor"; 744 return "compositor_scrolling";
618 case Policy::COMPOSITOR_CRITICAL_PATH_PRIORITY: 745 case UseCase::MAINTHREAD_SCROLLING:
619 return "compositor_critical_path"; 746 return "mainthread_scrolling";
620 case Policy::TOUCHSTART_PRIORITY: 747 case UseCase::TOUCHSTART:
621 return "touchstart"; 748 return "touchstart";
622 case Policy::LOADING_PRIORITY: 749 case UseCase::LOADING:
623 return "loading"; 750 return "loading";
624 default: 751 default:
625 NOTREACHED(); 752 NOTREACHED();
626 return nullptr; 753 return nullptr;
627 } 754 }
628 } 755 }
629 756
630 scoped_refptr<base::trace_event::ConvertableToTraceFormat> 757 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
631 RendererSchedulerImpl::AsValue(base::TimeTicks optional_now) const { 758 RendererSchedulerImpl::AsValue(base::TimeTicks optional_now) const {
632 base::AutoLock lock(any_thread_lock_); 759 base::AutoLock lock(any_thread_lock_);
633 return AsValueLocked(optional_now); 760 return AsValueLocked(optional_now);
634 } 761 }
635 762
636 scoped_refptr<base::trace_event::ConvertableToTraceFormat> 763 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
637 RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const { 764 RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const {
638 helper_.CheckOnValidThread(); 765 helper_.CheckOnValidThread();
639 any_thread_lock_.AssertAcquired(); 766 any_thread_lock_.AssertAcquired();
640 767
641 if (optional_now.is_null()) 768 if (optional_now.is_null())
642 optional_now = helper_.Now(); 769 optional_now = helper_.Now();
643 scoped_refptr<base::trace_event::TracedValue> state = 770 scoped_refptr<base::trace_event::TracedValue> state =
644 new base::trace_event::TracedValue(); 771 new base::trace_event::TracedValue();
645 772
646 state->SetString("current_policy", 773 state->SetString("current_use_case",
Sami 2015/08/26 13:38:01 Do we want to trace the policy too? One way would
alex clarke (OOO till 29th) 2015/08/27 12:02:51 We could do that, mind you it's already logged in
Sami 2015/08/27 15:15:58 Right, let's add it once it actually adds new info
alex clarke (OOO till 29th) 2015/09/03 10:34:25 Acknowledged.
647 PolicyToString(MainThreadOnly().current_policy_)); 774 UseCaseToString(MainThreadOnly().current_use_case_));
775 state->SetBoolean("loading_tasks_seem_expensive",
776 MainThreadOnly().loading_tasks_seem_expensive_);
777 state->SetBoolean("timer_tasks_seem_expensive",
778 MainThreadOnly().timer_tasks_seem_expensive_);
779 state->SetBoolean("scroll_expected_soon",
780 MainThreadOnly().scroll_expected_soon_);
648 state->SetString("idle_period_state", 781 state->SetString("idle_period_state",
649 IdleHelper::IdlePeriodStateToString( 782 IdleHelper::IdlePeriodStateToString(
650 idle_helper_.SchedulerIdlePeriodState())); 783 idle_helper_.SchedulerIdlePeriodState()));
651 state->SetBoolean("renderer_hidden", MainThreadOnly().renderer_hidden_); 784 state->SetBoolean("renderer_hidden", MainThreadOnly().renderer_hidden_);
652 state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF()); 785 state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF());
653 state->SetDouble("last_input_signal_time", 786 state->SetDouble("last_input_signal_time",
654 (AnyThread().last_input_signal_time_ - base::TimeTicks()) 787 (AnyThread().last_input_signal_time_ - base::TimeTicks())
655 .InMillisecondsF()); 788 .InMillisecondsF());
656 state->SetDouble("rails_loading_priority_deadline", 789 state->SetDouble("rails_loading_priority_deadline",
657 (AnyThread().rails_loading_priority_deadline_ - 790 (AnyThread().rails_loading_priority_deadline_ -
658 base::TimeTicks()).InMillisecondsF()); 791 base::TimeTicks()).InMillisecondsF());
659 state->SetDouble("last_idle_period_end_time", 792 state->SetDouble("last_idle_period_end_time",
660 (AnyThread().last_idle_period_end_time_ - base::TimeTicks()) 793 (AnyThread().last_idle_period_end_time_ - base::TimeTicks())
661 .InMillisecondsF()); 794 .InMillisecondsF());
662 state->SetInteger("pending_main_thread_input_event_count", 795 state->SetInteger("pending_main_thread_input_event_count",
663 AnyThread().pending_main_thread_input_event_count_); 796 AnyThread().pending_main_thread_input_event_count_);
664 state->SetBoolean("awaiting_touch_start_response", 797 state->SetBoolean("awaiting_touch_start_response",
665 AnyThread().awaiting_touch_start_response_); 798 AnyThread().awaiting_touch_start_response_);
666 state->SetBoolean("begin_main_frame_on_critical_path", 799 state->SetBoolean("begin_main_frame_on_critical_path",
667 AnyThread().begin_main_frame_on_critical_path_); 800 AnyThread().begin_main_frame_on_critical_path_);
801 state->SetDouble("expected_loading_task_duration",
802 MainThreadOnly()
803 .loading_task_cost_estimator_.expected_task_duration()
804 .InMillisecondsF());
668 state->SetDouble("expected_timer_task_duration", 805 state->SetDouble("expected_timer_task_duration",
669 MainThreadOnly() 806 MainThreadOnly()
670 .timer_task_cost_estimator_.expected_task_duration() 807 .timer_task_cost_estimator_.expected_task_duration()
671 .InMillisecondsF()); 808 .InMillisecondsF());
672 // TODO(skyostil): Can we somehow trace how accurate these estimates were? 809 // TODO(skyostil): Can we somehow trace how accurate these estimates were?
673 state->SetDouble( 810 state->SetDouble(
674 "expected_short_idle_period_duration", 811 "expected_short_idle_period_duration",
675 MainThreadOnly().expected_short_idle_period_duration_.InMillisecondsF()); 812 MainThreadOnly().expected_short_idle_period_duration_.InMillisecondsF());
676 state->SetBoolean("timer_tasks_seem_expensive",
677 AnyThread().timer_tasks_seem_expensive_);
678 state->SetDouble("estimated_next_frame_begin", 813 state->SetDouble("estimated_next_frame_begin",
679 (MainThreadOnly().estimated_next_frame_begin_ - 814 (MainThreadOnly().estimated_next_frame_begin_ -
680 base::TimeTicks()).InMillisecondsF()); 815 base::TimeTicks()).InMillisecondsF());
681 state->SetBoolean("in_idle_period", AnyThread().in_idle_period_); 816 state->SetBoolean("in_idle_period", AnyThread().in_idle_period_);
682 817
683 return state; 818 return state;
684 } 819 }
685 820
686 void RendererSchedulerImpl::OnIdlePeriodStarted() { 821 void RendererSchedulerImpl::OnIdlePeriodStarted() {
687 base::AutoLock lock(any_thread_lock_); 822 base::AutoLock lock(any_thread_lock_);
(...skipping 16 matching lines...) Expand all
704 UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED); 839 UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED);
705 } 840 }
706 841
707 bool RendererSchedulerImpl::HadAnIdlePeriodRecently(base::TimeTicks now) const { 842 bool RendererSchedulerImpl::HadAnIdlePeriodRecently(base::TimeTicks now) const {
708 return (now - AnyThread().last_idle_period_end_time_) <= 843 return (now - AnyThread().last_idle_period_end_time_) <=
709 base::TimeDelta::FromMilliseconds( 844 base::TimeDelta::FromMilliseconds(
710 kIdlePeriodStarvationThresholdMillis); 845 kIdlePeriodStarvationThresholdMillis);
711 } 846 }
712 847
713 } // namespace scheduler 848 } // namespace scheduler
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698