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

Side by Side Diff: third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc

Issue 2383473002: [scheduler] Teach scheduler about audio state (Closed)
Patch Set: Reverted DEPS Created 4 years, 2 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 "platform/scheduler/renderer/renderer_scheduler_impl.h" 5 #include "platform/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/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/ptr_util.h" 10 #include "base/memory/ptr_util.h"
11 #include "base/metrics/histogram_macros.h" 11 #include "base/metrics/histogram_macros.h"
12 #include "base/trace_event/trace_event.h" 12 #include "base/trace_event/trace_event.h"
13 #include "base/trace_event/trace_event_argument.h" 13 #include "base/trace_event/trace_event_argument.h"
14 #include "cc/output/begin_frame_args.h" 14 #include "cc/output/begin_frame_args.h"
15 #include "platform/scheduler/base/real_time_domain.h"
15 #include "platform/scheduler/base/task_queue_impl.h" 16 #include "platform/scheduler/base/task_queue_impl.h"
16 #include "platform/scheduler/base/task_queue_selector.h" 17 #include "platform/scheduler/base/task_queue_selector.h"
17 #include "platform/scheduler/base/virtual_time_domain.h" 18 #include "platform/scheduler/base/virtual_time_domain.h"
18 #include "platform/scheduler/child/scheduler_tqm_delegate.h" 19 #include "platform/scheduler/child/scheduler_tqm_delegate.h"
19 #include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h" 20 #include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h"
20 #include "platform/scheduler/renderer/task_queue_throttler.h" 21 #include "platform/scheduler/renderer/task_queue_throttler.h"
21 #include "platform/scheduler/renderer/web_view_scheduler_impl.h" 22 #include "platform/scheduler/renderer/web_view_scheduler_impl.h"
22 #include "platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.h" 23 #include "platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.h"
23 24
24 namespace blink { 25 namespace blink {
25 namespace scheduler { 26 namespace scheduler {
26 namespace { 27 namespace {
27 // The run time of loading tasks is strongly bimodal. The vast majority are 28 // The run time of loading tasks is strongly bimodal. The vast majority are
28 // very cheap, but there are usually a handful of very expensive tasks (e.g ~1 29 // very cheap, but there are usually a handful of very expensive tasks (e.g ~1
29 // second on a mobile device) so we take a very pessimistic view when estimating 30 // second on a mobile device) so we take a very pessimistic view when estimating
30 // the cost of loading tasks. 31 // the cost of loading tasks.
31 const int kLoadingTaskEstimationSampleCount = 1000; 32 const int kLoadingTaskEstimationSampleCount = 1000;
32 const double kLoadingTaskEstimationPercentile = 99; 33 const double kLoadingTaskEstimationPercentile = 99;
33 const int kTimerTaskEstimationSampleCount = 1000; 34 const int kTimerTaskEstimationSampleCount = 1000;
34 const double kTimerTaskEstimationPercentile = 99; 35 const double kTimerTaskEstimationPercentile = 99;
35 const int kShortIdlePeriodDurationSampleCount = 10; 36 const int kShortIdlePeriodDurationSampleCount = 10;
36 const double kShortIdlePeriodDurationPercentile = 50; 37 const double kShortIdlePeriodDurationPercentile = 50;
37 // Amount of idle time left in a frame (as a ratio of the vsync interval) above 38 // Amount of idle time left in a frame (as a ratio of the vsync interval) above
38 // which main thread compositing can be considered fast. 39 // which main thread compositing can be considered fast.
39 const double kFastCompositingIdleTimeThreshold = .2; 40 const double kFastCompositingIdleTimeThreshold = .2;
41 // We do not throttle anything while audio is played and shortly after that.
42 const int kThrottlingDelayAfterAudioIsPlayedInSeconds = 5;
40 43
41 void ReportForegroundRendererTaskLoad(base::TimeTicks time, double load) { 44 void ReportForegroundRendererTaskLoad(base::TimeTicks time, double load) {
42 int load_percentage = static_cast<int>(load * 100); 45 int load_percentage = static_cast<int>(load * 100);
43 UMA_HISTOGRAM_PERCENTAGE("RendererScheduler.ForegroundRendererMainThreadLoad", 46 UMA_HISTOGRAM_PERCENTAGE("RendererScheduler.ForegroundRendererMainThreadLoad",
44 load_percentage); 47 load_percentage);
45 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), 48 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
46 "RendererScheduler.ForegroundRendererLoad", load_percentage); 49 "RendererScheduler.ForegroundRendererLoad", load_percentage);
47 } 50 }
48 51
49 void ReportBackgroundRendererTaskLoad(base::TimeTicks time, double load) { 52 void ReportBackgroundRendererTaskLoad(base::TimeTicks time, double load) {
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 time_source, 154 time_source,
152 kShortIdlePeriodDurationSampleCount, 155 kShortIdlePeriodDurationSampleCount,
153 kShortIdlePeriodDurationPercentile), 156 kShortIdlePeriodDurationPercentile),
154 background_main_thread_load_tracker( 157 background_main_thread_load_tracker(
155 now, 158 now,
156 base::Bind(&ReportBackgroundRendererTaskLoad)), 159 base::Bind(&ReportBackgroundRendererTaskLoad)),
157 foreground_main_thread_load_tracker( 160 foreground_main_thread_load_tracker(
158 now, 161 now,
159 base::Bind(&ReportForegroundRendererTaskLoad)), 162 base::Bind(&ReportForegroundRendererTaskLoad)),
160 current_use_case(UseCase::NONE), 163 current_use_case(UseCase::NONE),
164 throttling_delay_after_audio_is_played(base::TimeDelta::FromSeconds(
165 kThrottlingDelayAfterAudioIsPlayedInSeconds)),
161 timer_queue_suspend_count(0), 166 timer_queue_suspend_count(0),
162 navigation_task_expected_count(0), 167 navigation_task_expected_count(0),
163 expensive_task_policy(ExpensiveTaskPolicy::RUN), 168 expensive_task_policy(ExpensiveTaskPolicy::RUN),
164 renderer_hidden(false), 169 renderer_hidden(false),
165 renderer_backgrounded(false), 170 renderer_backgrounded(false),
166 renderer_suspended(false), 171 renderer_suspended(false),
167 timer_queue_suspension_when_backgrounded_enabled(false), 172 timer_queue_suspension_when_backgrounded_enabled(false),
168 timer_queue_suspended_when_backgrounded(false), 173 timer_queue_suspended_when_backgrounded(false),
169 was_shutdown(false), 174 was_shutdown(false),
170 loading_tasks_seem_expensive(false), 175 loading_tasks_seem_expensive(false),
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 MainThreadOnly().renderer_suspended = false; 474 MainThreadOnly().renderer_suspended = false;
470 475
471 base::TimeTicks now = tick_clock()->NowTicks(); 476 base::TimeTicks now = tick_clock()->NowTicks();
472 MainThreadOnly().foreground_main_thread_load_tracker.Resume(now); 477 MainThreadOnly().foreground_main_thread_load_tracker.Resume(now);
473 MainThreadOnly().background_main_thread_load_tracker.Pause(now); 478 MainThreadOnly().background_main_thread_load_tracker.Pause(now);
474 479
475 suspend_timers_when_backgrounded_closure_.Cancel(); 480 suspend_timers_when_backgrounded_closure_.Cancel();
476 ResumeTimerQueueWhenForegrounded(); 481 ResumeTimerQueueWhenForegrounded();
477 } 482 }
478 483
484 void RendererSchedulerImpl::OnAudioStateChanged(bool is_audio_playing) {
485 MainThreadOnly().last_audio_state_change =
486 helper_.scheduler_tqm_delegate()->NowTicks();
487 MainThreadOnly().is_audio_playing = is_audio_playing;
488
489 UpdatePolicy();
490 }
491
479 void RendererSchedulerImpl::SuspendRenderer() { 492 void RendererSchedulerImpl::SuspendRenderer() {
480 helper_.CheckOnValidThread(); 493 helper_.CheckOnValidThread();
481 DCHECK(MainThreadOnly().renderer_backgrounded); 494 DCHECK(MainThreadOnly().renderer_backgrounded);
482 if (helper_.IsShutdown()) 495 if (helper_.IsShutdown())
483 return; 496 return;
484 suspend_timers_when_backgrounded_closure_.Cancel(); 497 suspend_timers_when_backgrounded_closure_.Cancel();
485 // TODO(hajimehoshi): We might need to suspend not only timer queue but also 498 // TODO(hajimehoshi): We might need to suspend not only timer queue but also
486 // e.g. loading tasks or postMessage. 499 // e.g. loading tasks or postMessage.
487 MainThreadOnly().renderer_suspended = true; 500 MainThreadOnly().renderer_suspended = true;
488 SuspendTimerQueueWhenBackgrounded(); 501 SuspendTimerQueueWhenBackgrounded();
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
799 // The |new_policy_duration| is the minimum of |expected_use_case_duration| 812 // The |new_policy_duration| is the minimum of |expected_use_case_duration|
800 // and |touchstart_expected_flag_valid_for_duration| unless one is zero in 813 // and |touchstart_expected_flag_valid_for_duration| unless one is zero in
801 // which case we choose the other. 814 // which case we choose the other.
802 base::TimeDelta new_policy_duration = expected_use_case_duration; 815 base::TimeDelta new_policy_duration = expected_use_case_duration;
803 if (new_policy_duration.is_zero() || 816 if (new_policy_duration.is_zero() ||
804 (touchstart_expected_flag_valid_for_duration > base::TimeDelta() && 817 (touchstart_expected_flag_valid_for_duration > base::TimeDelta() &&
805 new_policy_duration > touchstart_expected_flag_valid_for_duration)) { 818 new_policy_duration > touchstart_expected_flag_valid_for_duration)) {
806 new_policy_duration = touchstart_expected_flag_valid_for_duration; 819 new_policy_duration = touchstart_expected_flag_valid_for_duration;
807 } 820 }
808 821
822 if (MainThreadOnly().last_audio_state_change &&
alex clarke (OOO till 29th) 2016/09/30 10:33:46 Please add a brief comment outlining why we do thi
altimin 2016/10/03 11:15:25 Done.
823 !MainThreadOnly().is_audio_playing) {
824 base::TimeTicks audio_will_expire =
825 MainThreadOnly().last_audio_state_change.value() +
826 MainThreadOnly().throttling_delay_after_audio_is_played;
827
828 base::TimeDelta audio_will_expire_after = audio_will_expire - now;
829
830 if (audio_will_expire_after > base::TimeDelta()) {
831 if (new_policy_duration.is_zero()) {
832 new_policy_duration = audio_will_expire_after;
833 } else {
834 new_policy_duration =
835 std::min(new_policy_duration, audio_will_expire_after);
836 }
837 }
838 }
839
809 if (new_policy_duration > base::TimeDelta()) { 840 if (new_policy_duration > base::TimeDelta()) {
810 MainThreadOnly().current_policy_expiration_time = now + new_policy_duration; 841 MainThreadOnly().current_policy_expiration_time = now + new_policy_duration;
811 delayed_update_policy_runner_.SetDeadline(FROM_HERE, new_policy_duration, 842 delayed_update_policy_runner_.SetDeadline(FROM_HERE, new_policy_duration,
812 now); 843 now);
813 } else { 844 } else {
814 MainThreadOnly().current_policy_expiration_time = base::TimeTicks(); 845 MainThreadOnly().current_policy_expiration_time = base::TimeTicks();
815 } 846 }
816 847
817 // Avoid prioritizing main thread compositing (e.g., rAF) if it is extremely 848 // Avoid prioritizing main thread compositing (e.g., rAF) if it is extremely
818 // slow, because that can cause starvation in other task sources. 849 // slow, because that can cause starvation in other task sources.
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
954 } 985 }
955 986
956 if (MainThreadOnly().use_virtual_time) { 987 if (MainThreadOnly().use_virtual_time) {
957 new_policy.compositor_queue_policy.time_domain_type = 988 new_policy.compositor_queue_policy.time_domain_type =
958 TimeDomainType::VIRTUAL; 989 TimeDomainType::VIRTUAL;
959 new_policy.default_queue_policy.time_domain_type = TimeDomainType::VIRTUAL; 990 new_policy.default_queue_policy.time_domain_type = TimeDomainType::VIRTUAL;
960 new_policy.loading_queue_policy.time_domain_type = TimeDomainType::VIRTUAL; 991 new_policy.loading_queue_policy.time_domain_type = TimeDomainType::VIRTUAL;
961 new_policy.timer_queue_policy.time_domain_type = TimeDomainType::VIRTUAL; 992 new_policy.timer_queue_policy.time_domain_type = TimeDomainType::VIRTUAL;
962 } 993 }
963 994
995 new_policy.should_disable_throttling =
996 ShouldDisableThrottlingBecauseOfAudio(now) ||
Sami 2016/09/30 11:52:09 By the way, this means that we might get more scro
altimin 2016/10/03 11:15:25 How are throttling and scroll jank related? Are yo
Sami 2016/10/03 14:36:31 Not just visibility-based throttling. Previously w
997 MainThreadOnly().use_virtual_time;
998
964 // Tracing is done before the early out check, because it's quite possible we 999 // Tracing is done before the early out check, because it's quite possible we
965 // will otherwise miss this information in traces. 1000 // will otherwise miss this information in traces.
966 CreateTraceEventObjectSnapshotLocked(); 1001 CreateTraceEventObjectSnapshotLocked();
967 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "use_case", 1002 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "use_case",
968 use_case); 1003 use_case);
969 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "rail_mode", 1004 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "rail_mode",
970 new_policy.rail_mode); 1005 new_policy.rail_mode);
971 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), 1006 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
972 "touchstart_expected_soon", 1007 "touchstart_expected_soon",
973 MainThreadOnly().touchstart_expected_soon); 1008 MainThreadOnly().touchstart_expected_soon);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1009 // are mostly dispatched on the default queue) need to be preserved. 1044 // are mostly dispatched on the default queue) need to be preserved.
1010 ApplyTaskQueuePolicy(helper_.DefaultTaskRunner().get(), 1045 ApplyTaskQueuePolicy(helper_.DefaultTaskRunner().get(),
1011 MainThreadOnly().current_policy.default_queue_policy, 1046 MainThreadOnly().current_policy.default_queue_policy,
1012 new_policy.default_queue_policy); 1047 new_policy.default_queue_policy);
1013 if (MainThreadOnly().rail_mode_observer && 1048 if (MainThreadOnly().rail_mode_observer &&
1014 new_policy.rail_mode != MainThreadOnly().current_policy.rail_mode) { 1049 new_policy.rail_mode != MainThreadOnly().current_policy.rail_mode) {
1015 MainThreadOnly().rail_mode_observer->OnRAILModeChanged( 1050 MainThreadOnly().rail_mode_observer->OnRAILModeChanged(
1016 new_policy.rail_mode); 1051 new_policy.rail_mode);
1017 } 1052 }
1018 1053
1054 if (new_policy.should_disable_throttling !=
1055 MainThreadOnly().current_policy.should_disable_throttling) {
1056 if (new_policy.should_disable_throttling) {
1057 task_queue_throttler()->DisableThrottling();
1058 } else {
1059 task_queue_throttler()->EnableThrottling();
1060 }
1061 }
1062
1019 DCHECK(compositor_task_runner_->IsQueueEnabled()); 1063 DCHECK(compositor_task_runner_->IsQueueEnabled());
1020 MainThreadOnly().current_policy = new_policy; 1064 MainThreadOnly().current_policy = new_policy;
1021 } 1065 }
1022 1066
1023 void RendererSchedulerImpl::ApplyTaskQueuePolicy( 1067 void RendererSchedulerImpl::ApplyTaskQueuePolicy(
1024 TaskQueue* task_queue, 1068 TaskQueue* task_queue,
1025 const TaskQueuePolicy& old_task_queue_policy, 1069 const TaskQueuePolicy& old_task_queue_policy,
1026 const TaskQueuePolicy& new_task_queue_policy) const { 1070 const TaskQueuePolicy& new_task_queue_policy) const {
1027 if (old_task_queue_policy.is_enabled != new_task_queue_policy.is_enabled) { 1071 if (old_task_queue_policy.is_enabled != new_task_queue_policy.is_enabled) {
1028 task_queue_throttler_->SetQueueEnabled(task_queue, 1072 task_queue_throttler_->SetQueueEnabled(task_queue,
(...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after
1531 } 1575 }
1532 1576
1533 void RendererSchedulerImpl::EnableVirtualTime() { 1577 void RendererSchedulerImpl::EnableVirtualTime() {
1534 MainThreadOnly().use_virtual_time = true; 1578 MainThreadOnly().use_virtual_time = true;
1535 1579
1536 // The |unthrottled_task_runners_| are not actively managed by UpdatePolicy(). 1580 // The |unthrottled_task_runners_| are not actively managed by UpdatePolicy().
1537 AutoAdvancingVirtualTimeDomain* time_domain = GetVirtualTimeDomain(); 1581 AutoAdvancingVirtualTimeDomain* time_domain = GetVirtualTimeDomain();
1538 for (const scoped_refptr<TaskQueue>& task_queue : unthrottled_task_runners_) 1582 for (const scoped_refptr<TaskQueue>& task_queue : unthrottled_task_runners_)
1539 task_queue->SetTimeDomain(time_domain); 1583 task_queue->SetTimeDomain(time_domain);
1540 1584
1541 task_queue_throttler_->EnableVirtualTime(); 1585 ForceUpdatePolicy();
1586 }
1542 1587
1543 ForceUpdatePolicy(); 1588 bool RendererSchedulerImpl::ShouldDisableThrottlingBecauseOfAudio(
1589 base::TimeTicks now) {
1590 if (!MainThreadOnly().last_audio_state_change)
1591 return false;
1592
1593 if (MainThreadOnly().is_audio_playing)
1594 return true;
1595
1596 return MainThreadOnly().last_audio_state_change.value() +
1597 MainThreadOnly().throttling_delay_after_audio_is_played >
1598 now;
1599 }
1600
1601 TimeDomain* RendererSchedulerImpl::GetActiveTimeDomain() {
1602 if (MainThreadOnly().use_virtual_time) {
1603 return GetVirtualTimeDomain();
1604 } else {
1605 return real_time_domain();
1606 }
1544 } 1607 }
1545 1608
1546 // static 1609 // static
1547 const char* RendererSchedulerImpl::UseCaseToString(UseCase use_case) { 1610 const char* RendererSchedulerImpl::UseCaseToString(UseCase use_case) {
1548 switch (use_case) { 1611 switch (use_case) {
1549 case UseCase::NONE: 1612 case UseCase::NONE:
1550 return "none"; 1613 return "none";
1551 case UseCase::COMPOSITOR_GESTURE: 1614 case UseCase::COMPOSITOR_GESTURE:
1552 return "compositor_gesture"; 1615 return "compositor_gesture";
1553 case UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING: 1616 case UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING:
(...skipping 24 matching lines...) Expand all
1578 case v8::PERFORMANCE_LOAD: 1641 case v8::PERFORMANCE_LOAD:
1579 return "load"; 1642 return "load";
1580 default: 1643 default:
1581 NOTREACHED(); 1644 NOTREACHED();
1582 return nullptr; 1645 return nullptr;
1583 } 1646 }
1584 } 1647 }
1585 1648
1586 } // namespace scheduler 1649 } // namespace scheduler
1587 } // namespace blink 1650 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698