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

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: Support out-of-process frames 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),
171 timer_tasks_seem_expensive(false), 176 timer_tasks_seem_expensive(false),
172 touchstart_expected_soon(false), 177 touchstart_expected_soon(false),
173 have_seen_a_begin_main_frame(false), 178 have_seen_a_begin_main_frame(false),
174 have_reported_blocking_intervention_in_current_policy(false), 179 have_reported_blocking_intervention_in_current_policy(false),
175 have_reported_blocking_intervention_since_navigation(false), 180 have_reported_blocking_intervention_since_navigation(false),
176 has_visible_render_widget_with_touch_handler(false), 181 has_visible_render_widget_with_touch_handler(false),
177 begin_frame_not_expected_soon(false), 182 begin_frame_not_expected_soon(false),
178 in_idle_period_for_testing(false), 183 in_idle_period_for_testing(false),
179 use_virtual_time(false), 184 use_virtual_time(false),
185 is_audio_playing(false),
180 rail_mode_observer(nullptr) {} 186 rail_mode_observer(nullptr) {}
181 187
182 RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {} 188 RendererSchedulerImpl::MainThreadOnly::~MainThreadOnly() {}
183 189
184 RendererSchedulerImpl::AnyThread::AnyThread() 190 RendererSchedulerImpl::AnyThread::AnyThread()
185 : awaiting_touch_start_response(false), 191 : awaiting_touch_start_response(false),
186 in_idle_period(false), 192 in_idle_period(false),
187 begin_main_frame_on_critical_path(false), 193 begin_main_frame_on_critical_path(false),
188 last_gesture_was_compositor_driven(false), 194 last_gesture_was_compositor_driven(false),
189 default_gesture_prevented(true), 195 default_gesture_prevented(true),
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 MainThreadOnly().renderer_suspended = false; 475 MainThreadOnly().renderer_suspended = false;
470 476
471 base::TimeTicks now = tick_clock()->NowTicks(); 477 base::TimeTicks now = tick_clock()->NowTicks();
472 MainThreadOnly().foreground_main_thread_load_tracker.Resume(now); 478 MainThreadOnly().foreground_main_thread_load_tracker.Resume(now);
473 MainThreadOnly().background_main_thread_load_tracker.Pause(now); 479 MainThreadOnly().background_main_thread_load_tracker.Pause(now);
474 480
475 suspend_timers_when_backgrounded_closure_.Cancel(); 481 suspend_timers_when_backgrounded_closure_.Cancel();
476 ResumeTimerQueueWhenForegrounded(); 482 ResumeTimerQueueWhenForegrounded();
477 } 483 }
478 484
485 void RendererSchedulerImpl::OnAudioStateChanged() {
486 bool is_audio_playing = false;
487 for (WebViewSchedulerImpl* web_view_scheduler :
488 MainThreadOnly().web_view_schedulers) {
489 is_audio_playing = is_audio_playing || web_view_scheduler->IsAudioPlaying();
490 }
491
492 if (is_audio_playing == MainThreadOnly().is_audio_playing)
493 return;
494
495 MainThreadOnly().last_audio_state_change =
496 helper_.scheduler_tqm_delegate()->NowTicks();
497 MainThreadOnly().is_audio_playing = is_audio_playing;
498
499 UpdatePolicy();
500 }
501
479 void RendererSchedulerImpl::SuspendRenderer() { 502 void RendererSchedulerImpl::SuspendRenderer() {
480 helper_.CheckOnValidThread(); 503 helper_.CheckOnValidThread();
481 DCHECK(MainThreadOnly().renderer_backgrounded); 504 DCHECK(MainThreadOnly().renderer_backgrounded);
482 if (helper_.IsShutdown()) 505 if (helper_.IsShutdown())
483 return; 506 return;
484 suspend_timers_when_backgrounded_closure_.Cancel(); 507 suspend_timers_when_backgrounded_closure_.Cancel();
485 // TODO(hajimehoshi): We might need to suspend not only timer queue but also 508 // TODO(hajimehoshi): We might need to suspend not only timer queue but also
486 // e.g. loading tasks or postMessage. 509 // e.g. loading tasks or postMessage.
487 MainThreadOnly().renderer_suspended = true; 510 MainThreadOnly().renderer_suspended = true;
488 SuspendTimerQueueWhenBackgrounded(); 511 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| 822 // 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 823 // and |touchstart_expected_flag_valid_for_duration| unless one is zero in
801 // which case we choose the other. 824 // which case we choose the other.
802 base::TimeDelta new_policy_duration = expected_use_case_duration; 825 base::TimeDelta new_policy_duration = expected_use_case_duration;
803 if (new_policy_duration.is_zero() || 826 if (new_policy_duration.is_zero() ||
804 (touchstart_expected_flag_valid_for_duration > base::TimeDelta() && 827 (touchstart_expected_flag_valid_for_duration > base::TimeDelta() &&
805 new_policy_duration > touchstart_expected_flag_valid_for_duration)) { 828 new_policy_duration > touchstart_expected_flag_valid_for_duration)) {
806 new_policy_duration = touchstart_expected_flag_valid_for_duration; 829 new_policy_duration = touchstart_expected_flag_valid_for_duration;
807 } 830 }
808 831
832 // Do not throttle while audio is playing or for a short period after that
833 // to make sure that pages playing short audio clips powered by timers
834 // work.
835 if (MainThreadOnly().last_audio_state_change &&
836 !MainThreadOnly().is_audio_playing) {
837 base::TimeTicks audio_will_expire =
838 MainThreadOnly().last_audio_state_change.value() +
839 MainThreadOnly().throttling_delay_after_audio_is_played;
840
841 base::TimeDelta audio_will_expire_after = audio_will_expire - now;
842
843 if (audio_will_expire_after > base::TimeDelta()) {
844 if (new_policy_duration.is_zero()) {
845 new_policy_duration = audio_will_expire_after;
846 } else {
847 new_policy_duration =
848 std::min(new_policy_duration, audio_will_expire_after);
849 }
850 }
851 }
852
809 if (new_policy_duration > base::TimeDelta()) { 853 if (new_policy_duration > base::TimeDelta()) {
810 MainThreadOnly().current_policy_expiration_time = now + new_policy_duration; 854 MainThreadOnly().current_policy_expiration_time = now + new_policy_duration;
811 delayed_update_policy_runner_.SetDeadline(FROM_HERE, new_policy_duration, 855 delayed_update_policy_runner_.SetDeadline(FROM_HERE, new_policy_duration,
812 now); 856 now);
813 } else { 857 } else {
814 MainThreadOnly().current_policy_expiration_time = base::TimeTicks(); 858 MainThreadOnly().current_policy_expiration_time = base::TimeTicks();
815 } 859 }
816 860
817 // Avoid prioritizing main thread compositing (e.g., rAF) if it is extremely 861 // Avoid prioritizing main thread compositing (e.g., rAF) if it is extremely
818 // slow, because that can cause starvation in other task sources. 862 // slow, because that can cause starvation in other task sources.
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
954 } 998 }
955 999
956 if (MainThreadOnly().use_virtual_time) { 1000 if (MainThreadOnly().use_virtual_time) {
957 new_policy.compositor_queue_policy.time_domain_type = 1001 new_policy.compositor_queue_policy.time_domain_type =
958 TimeDomainType::VIRTUAL; 1002 TimeDomainType::VIRTUAL;
959 new_policy.default_queue_policy.time_domain_type = TimeDomainType::VIRTUAL; 1003 new_policy.default_queue_policy.time_domain_type = TimeDomainType::VIRTUAL;
960 new_policy.loading_queue_policy.time_domain_type = TimeDomainType::VIRTUAL; 1004 new_policy.loading_queue_policy.time_domain_type = TimeDomainType::VIRTUAL;
961 new_policy.timer_queue_policy.time_domain_type = TimeDomainType::VIRTUAL; 1005 new_policy.timer_queue_policy.time_domain_type = TimeDomainType::VIRTUAL;
962 } 1006 }
963 1007
1008 new_policy.should_disable_throttling =
1009 ShouldDisableThrottlingBecauseOfAudio(now) ||
1010 MainThreadOnly().use_virtual_time;
1011
964 // Tracing is done before the early out check, because it's quite possible we 1012 // Tracing is done before the early out check, because it's quite possible we
965 // will otherwise miss this information in traces. 1013 // will otherwise miss this information in traces.
966 CreateTraceEventObjectSnapshotLocked(); 1014 CreateTraceEventObjectSnapshotLocked();
967 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "use_case", 1015 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "use_case",
968 use_case); 1016 use_case);
969 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "rail_mode", 1017 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "rail_mode",
970 new_policy.rail_mode); 1018 new_policy.rail_mode);
971 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), 1019 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
972 "touchstart_expected_soon", 1020 "touchstart_expected_soon",
973 MainThreadOnly().touchstart_expected_soon); 1021 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. 1057 // are mostly dispatched on the default queue) need to be preserved.
1010 ApplyTaskQueuePolicy(helper_.DefaultTaskRunner().get(), 1058 ApplyTaskQueuePolicy(helper_.DefaultTaskRunner().get(),
1011 MainThreadOnly().current_policy.default_queue_policy, 1059 MainThreadOnly().current_policy.default_queue_policy,
1012 new_policy.default_queue_policy); 1060 new_policy.default_queue_policy);
1013 if (MainThreadOnly().rail_mode_observer && 1061 if (MainThreadOnly().rail_mode_observer &&
1014 new_policy.rail_mode != MainThreadOnly().current_policy.rail_mode) { 1062 new_policy.rail_mode != MainThreadOnly().current_policy.rail_mode) {
1015 MainThreadOnly().rail_mode_observer->OnRAILModeChanged( 1063 MainThreadOnly().rail_mode_observer->OnRAILModeChanged(
1016 new_policy.rail_mode); 1064 new_policy.rail_mode);
1017 } 1065 }
1018 1066
1067 if (new_policy.should_disable_throttling !=
1068 MainThreadOnly().current_policy.should_disable_throttling) {
1069 if (new_policy.should_disable_throttling) {
1070 task_queue_throttler()->DisableThrottling();
1071 } else {
1072 task_queue_throttler()->EnableThrottling();
1073 }
1074 }
1075
1019 DCHECK(compositor_task_runner_->IsQueueEnabled()); 1076 DCHECK(compositor_task_runner_->IsQueueEnabled());
1020 MainThreadOnly().current_policy = new_policy; 1077 MainThreadOnly().current_policy = new_policy;
1021 } 1078 }
1022 1079
1023 void RendererSchedulerImpl::ApplyTaskQueuePolicy( 1080 void RendererSchedulerImpl::ApplyTaskQueuePolicy(
1024 TaskQueue* task_queue, 1081 TaskQueue* task_queue,
1025 const TaskQueuePolicy& old_task_queue_policy, 1082 const TaskQueuePolicy& old_task_queue_policy,
1026 const TaskQueuePolicy& new_task_queue_policy) const { 1083 const TaskQueuePolicy& new_task_queue_policy) const {
1027 if (old_task_queue_policy.is_enabled != new_task_queue_policy.is_enabled) { 1084 if (old_task_queue_policy.is_enabled != new_task_queue_policy.is_enabled) {
1028 task_queue_throttler_->SetQueueEnabled(task_queue, 1085 task_queue_throttler_->SetQueueEnabled(task_queue,
(...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after
1531 } 1588 }
1532 1589
1533 void RendererSchedulerImpl::EnableVirtualTime() { 1590 void RendererSchedulerImpl::EnableVirtualTime() {
1534 MainThreadOnly().use_virtual_time = true; 1591 MainThreadOnly().use_virtual_time = true;
1535 1592
1536 // The |unthrottled_task_runners_| are not actively managed by UpdatePolicy(). 1593 // The |unthrottled_task_runners_| are not actively managed by UpdatePolicy().
1537 AutoAdvancingVirtualTimeDomain* time_domain = GetVirtualTimeDomain(); 1594 AutoAdvancingVirtualTimeDomain* time_domain = GetVirtualTimeDomain();
1538 for (const scoped_refptr<TaskQueue>& task_queue : unthrottled_task_runners_) 1595 for (const scoped_refptr<TaskQueue>& task_queue : unthrottled_task_runners_)
1539 task_queue->SetTimeDomain(time_domain); 1596 task_queue->SetTimeDomain(time_domain);
1540 1597
1541 task_queue_throttler_->EnableVirtualTime(); 1598 ForceUpdatePolicy();
1599 }
1542 1600
1543 ForceUpdatePolicy(); 1601 bool RendererSchedulerImpl::ShouldDisableThrottlingBecauseOfAudio(
1602 base::TimeTicks now) {
1603 if (!MainThreadOnly().last_audio_state_change)
1604 return false;
1605
1606 if (MainThreadOnly().is_audio_playing)
1607 return true;
1608
1609 return MainThreadOnly().last_audio_state_change.value() +
1610 MainThreadOnly().throttling_delay_after_audio_is_played >
1611 now;
1612 }
1613
1614 TimeDomain* RendererSchedulerImpl::GetActiveTimeDomain() {
1615 if (MainThreadOnly().use_virtual_time) {
1616 return GetVirtualTimeDomain();
1617 } else {
1618 return real_time_domain();
1619 }
1544 } 1620 }
1545 1621
1546 // static 1622 // static
1547 const char* RendererSchedulerImpl::UseCaseToString(UseCase use_case) { 1623 const char* RendererSchedulerImpl::UseCaseToString(UseCase use_case) {
1548 switch (use_case) { 1624 switch (use_case) {
1549 case UseCase::NONE: 1625 case UseCase::NONE:
1550 return "none"; 1626 return "none";
1551 case UseCase::COMPOSITOR_GESTURE: 1627 case UseCase::COMPOSITOR_GESTURE:
1552 return "compositor_gesture"; 1628 return "compositor_gesture";
1553 case UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING: 1629 case UseCase::MAIN_THREAD_CUSTOM_INPUT_HANDLING:
(...skipping 24 matching lines...) Expand all
1578 case v8::PERFORMANCE_LOAD: 1654 case v8::PERFORMANCE_LOAD:
1579 return "load"; 1655 return "load";
1580 default: 1656 default:
1581 NOTREACHED(); 1657 NOTREACHED();
1582 return nullptr; 1658 return nullptr;
1583 } 1659 }
1584 } 1660 }
1585 1661
1586 } // namespace scheduler 1662 } // namespace scheduler
1587 } // namespace blink 1663 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698