Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/scheduler/renderer_scheduler_impl.h" | 5 #include "content/renderer/scheduler/renderer_scheduler_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/debug/trace_event.h" | |
| 9 #include "base/debug/trace_event_argument.h" | |
| 10 #include "base/message_loop/message_loop_proxy.h" | |
| 8 #include "cc/output/begin_frame_args.h" | 11 #include "cc/output/begin_frame_args.h" |
| 9 #include "content/renderer/scheduler/renderer_task_queue_selector.h" | 12 #include "content/renderer/scheduler/renderer_task_queue_selector.h" |
| 10 #include "ui/gfx/frame_time.h" | 13 #include "ui/gfx/frame_time.h" |
| 11 | 14 |
| 12 namespace content { | 15 namespace content { |
| 13 | 16 |
| 14 RendererSchedulerImpl::RendererSchedulerImpl( | 17 RendererSchedulerImpl::RendererSchedulerImpl( |
| 15 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) | 18 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) |
| 16 : renderer_task_queue_selector_(new RendererTaskQueueSelector()), | 19 : renderer_task_queue_selector_(new RendererTaskQueueSelector()), |
| 17 task_queue_manager_( | 20 task_queue_manager_( |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 33 end_idle_period_closure_ = base::Bind(&RendererSchedulerImpl::EndIdlePeriod, | 36 end_idle_period_closure_ = base::Bind(&RendererSchedulerImpl::EndIdlePeriod, |
| 34 weak_renderer_scheduler_ptr_); | 37 weak_renderer_scheduler_ptr_); |
| 35 idle_task_runner_ = make_scoped_refptr(new SingleThreadIdleTaskRunner( | 38 idle_task_runner_ = make_scoped_refptr(new SingleThreadIdleTaskRunner( |
| 36 task_queue_manager_->TaskRunnerForQueue(IDLE_TASK_QUEUE), | 39 task_queue_manager_->TaskRunnerForQueue(IDLE_TASK_QUEUE), |
| 37 base::Bind(&RendererSchedulerImpl::CurrentIdleTaskDeadlineCallback, | 40 base::Bind(&RendererSchedulerImpl::CurrentIdleTaskDeadlineCallback, |
| 38 weak_renderer_scheduler_ptr_))); | 41 weak_renderer_scheduler_ptr_))); |
| 39 renderer_task_queue_selector_->SetQueuePriority( | 42 renderer_task_queue_selector_->SetQueuePriority( |
| 40 CONTROL_TASK_QUEUE, RendererTaskQueueSelector::CONTROL_PRIORITY); | 43 CONTROL_TASK_QUEUE, RendererTaskQueueSelector::CONTROL_PRIORITY); |
| 41 renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE); | 44 renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE); |
| 42 task_queue_manager_->SetAutoPump(IDLE_TASK_QUEUE, false); | 45 task_queue_manager_->SetAutoPump(IDLE_TASK_QUEUE, false); |
| 46 | |
| 47 for (size_t i = 0; i < TASK_QUEUE_COUNT; i++) { | |
| 48 task_queue_manager_->SetQueueName( | |
| 49 i, TaskQueueIdToString(static_cast<QueueId>(i))); | |
| 50 } | |
| 51 TRACE_EVENT_OBJECT_CREATED_WITH_ID( | |
| 52 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", | |
| 53 this); | |
| 43 } | 54 } |
| 44 | 55 |
| 45 RendererSchedulerImpl::~RendererSchedulerImpl() { | 56 RendererSchedulerImpl::~RendererSchedulerImpl() { |
| 57 TRACE_EVENT_OBJECT_DELETED_WITH_ID( | |
| 58 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", | |
| 59 this); | |
| 46 } | 60 } |
| 47 | 61 |
| 48 void RendererSchedulerImpl::Shutdown() { | 62 void RendererSchedulerImpl::Shutdown() { |
| 49 main_thread_checker_.CalledOnValidThread(); | 63 main_thread_checker_.CalledOnValidThread(); |
| 50 task_queue_manager_.reset(); | 64 task_queue_manager_.reset(); |
| 51 } | 65 } |
| 52 | 66 |
| 53 scoped_refptr<base::SingleThreadTaskRunner> | 67 scoped_refptr<base::SingleThreadTaskRunner> |
| 54 RendererSchedulerImpl::DefaultTaskRunner() { | 68 RendererSchedulerImpl::DefaultTaskRunner() { |
| 55 main_thread_checker_.CalledOnValidThread(); | 69 main_thread_checker_.CalledOnValidThread(); |
| 56 return default_task_runner_; | 70 return default_task_runner_; |
| 57 } | 71 } |
| 58 | 72 |
| 59 scoped_refptr<base::SingleThreadTaskRunner> | 73 scoped_refptr<base::SingleThreadTaskRunner> |
| 60 RendererSchedulerImpl::CompositorTaskRunner() { | 74 RendererSchedulerImpl::CompositorTaskRunner() { |
| 61 main_thread_checker_.CalledOnValidThread(); | 75 main_thread_checker_.CalledOnValidThread(); |
| 62 return compositor_task_runner_; | 76 return compositor_task_runner_; |
| 63 } | 77 } |
| 64 | 78 |
| 65 scoped_refptr<SingleThreadIdleTaskRunner> | 79 scoped_refptr<SingleThreadIdleTaskRunner> |
| 66 RendererSchedulerImpl::IdleTaskRunner() { | 80 RendererSchedulerImpl::IdleTaskRunner() { |
| 67 main_thread_checker_.CalledOnValidThread(); | 81 main_thread_checker_.CalledOnValidThread(); |
| 68 return idle_task_runner_; | 82 return idle_task_runner_; |
| 69 } | 83 } |
| 70 | 84 |
| 71 void RendererSchedulerImpl::WillBeginFrame(const cc::BeginFrameArgs& args) { | 85 void RendererSchedulerImpl::WillBeginFrame(const cc::BeginFrameArgs& args) { |
| 86 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | |
| 87 "RendererSchedulerImpl::WillBeginFrame", "args", args.AsValue()); | |
| 72 main_thread_checker_.CalledOnValidThread(); | 88 main_thread_checker_.CalledOnValidThread(); |
| 73 if (!task_queue_manager_) | 89 if (!task_queue_manager_) |
| 74 return; | 90 return; |
| 75 | 91 |
| 76 EndIdlePeriod(); | 92 EndIdlePeriod(); |
| 77 estimated_next_frame_begin_ = args.frame_time + args.interval; | 93 estimated_next_frame_begin_ = args.frame_time + args.interval; |
| 78 } | 94 } |
| 79 | 95 |
| 80 void RendererSchedulerImpl::DidCommitFrameToCompositor() { | 96 void RendererSchedulerImpl::DidCommitFrameToCompositor() { |
| 97 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | |
| 98 "RendererSchedulerImpl::DidCommitFrameToCompositor"); | |
| 81 main_thread_checker_.CalledOnValidThread(); | 99 main_thread_checker_.CalledOnValidThread(); |
| 82 if (!task_queue_manager_) | 100 if (!task_queue_manager_) |
| 83 return; | 101 return; |
| 84 | 102 |
| 85 base::TimeTicks now(Now()); | 103 base::TimeTicks now(Now()); |
| 86 if (now < estimated_next_frame_begin_) { | 104 if (now < estimated_next_frame_begin_) { |
| 87 StartIdlePeriod(); | 105 StartIdlePeriod(); |
| 88 control_task_runner_->PostDelayedTask(FROM_HERE, end_idle_period_closure_, | 106 control_task_runner_->PostDelayedTask(FROM_HERE, end_idle_period_closure_, |
| 89 estimated_next_frame_begin_ - now); | 107 estimated_next_frame_begin_ - now); |
| 90 } | 108 } |
| 91 } | 109 } |
| 92 | 110 |
| 93 void RendererSchedulerImpl::DidReceiveInputEventOnCompositorThread() { | 111 void RendererSchedulerImpl::DidReceiveInputEventOnCompositorThread() { |
| 112 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | |
| 113 "RendererSchedulerImpl::DidReceiveInputEventOnCompositorThread"); | |
| 94 // TODO(rmcilroy): Decide whether only a subset of input events should trigger | 114 // TODO(rmcilroy): Decide whether only a subset of input events should trigger |
| 95 // compositor priority policy - http://crbug.com/429814. | 115 // compositor priority policy - http://crbug.com/429814. |
| 96 base::AutoLock lock(incoming_signals_lock_); | 116 base::AutoLock lock(incoming_signals_lock_); |
| 97 if (last_input_time_.is_null()) { | 117 if (last_input_time_.is_null()) { |
| 98 // Update scheduler policy if should start a new compositor policy mode. | 118 // Update scheduler policy if should start a new compositor policy mode. |
| 99 policy_may_need_update_.SetLocked(true); | 119 policy_may_need_update_.SetLocked(true); |
| 100 PostUpdatePolicyOnControlRunner(base::TimeDelta()); | 120 PostUpdatePolicyOnControlRunner(base::TimeDelta()); |
| 101 } | 121 } |
| 102 last_input_time_ = Now(); | 122 last_input_time_ = Now(); |
| 103 } | 123 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 139 control_task_runner_->PostDelayedTask(FROM_HERE, update_policy_closure_, | 159 control_task_runner_->PostDelayedTask(FROM_HERE, update_policy_closure_, |
| 140 delay); | 160 delay); |
| 141 } | 161 } |
| 142 | 162 |
| 143 void RendererSchedulerImpl::UpdatePolicy() { | 163 void RendererSchedulerImpl::UpdatePolicy() { |
| 144 main_thread_checker_.CalledOnValidThread(); | 164 main_thread_checker_.CalledOnValidThread(); |
| 145 if (!task_queue_manager_) | 165 if (!task_queue_manager_) |
| 146 return; | 166 return; |
| 147 | 167 |
| 148 base::AutoLock lock(incoming_signals_lock_); | 168 base::AutoLock lock(incoming_signals_lock_); |
| 169 base::TimeTicks now; | |
| 149 policy_may_need_update_.SetLocked(false); | 170 policy_may_need_update_.SetLocked(false); |
| 150 | 171 |
| 151 Policy new_policy = NORMAL_PRIORITY_POLICY; | 172 Policy new_policy = NORMAL_PRIORITY_POLICY; |
| 152 if (!last_input_time_.is_null()) { | 173 if (!last_input_time_.is_null()) { |
| 153 base::TimeDelta compositor_priority_duration = | 174 base::TimeDelta compositor_priority_duration = |
| 154 base::TimeDelta::FromMilliseconds(kCompositorPriorityAfterTouchMillis); | 175 base::TimeDelta::FromMilliseconds(kCompositorPriorityAfterTouchMillis); |
| 155 base::TimeTicks compositor_priority_end(last_input_time_ + | 176 base::TimeTicks compositor_priority_end(last_input_time_ + |
| 156 compositor_priority_duration); | 177 compositor_priority_duration); |
| 157 base::TimeTicks now(Now()); | 178 now = Now(); |
| 158 if (compositor_priority_end > now) { | 179 if (compositor_priority_end > now) { |
| 159 PostUpdatePolicyOnControlRunner(compositor_priority_end - now); | 180 PostUpdatePolicyOnControlRunner(compositor_priority_end - now); |
| 160 new_policy = COMPOSITOR_PRIORITY_POLICY; | 181 new_policy = COMPOSITOR_PRIORITY_POLICY; |
| 161 } else { | 182 } else { |
| 162 // Null out last_input_time_ to ensure | 183 // Null out last_input_time_ to ensure |
| 163 // DidReceiveInputEventOnCompositorThread will post an | 184 // DidReceiveInputEventOnCompositorThread will post an |
| 164 // UpdatePolicy task when it's next called. | 185 // UpdatePolicy task when it's next called. |
| 165 last_input_time_ = base::TimeTicks(); | 186 last_input_time_ = base::TimeTicks(); |
| 166 } | 187 } |
| 167 } | 188 } |
| 168 | 189 |
| 169 if (new_policy == current_policy_) | 190 if (new_policy == current_policy_) |
| 170 return; | 191 return; |
| 171 | 192 |
| 172 switch (new_policy) { | 193 switch (new_policy) { |
| 173 case COMPOSITOR_PRIORITY_POLICY: | 194 case COMPOSITOR_PRIORITY_POLICY: |
| 174 renderer_task_queue_selector_->SetQueuePriority( | 195 renderer_task_queue_selector_->SetQueuePriority( |
| 175 COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::HIGH_PRIORITY); | 196 COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::HIGH_PRIORITY); |
| 176 break; | 197 break; |
| 177 case NORMAL_PRIORITY_POLICY: | 198 case NORMAL_PRIORITY_POLICY: |
| 178 renderer_task_queue_selector_->SetQueuePriority( | 199 renderer_task_queue_selector_->SetQueuePriority( |
| 179 COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::NORMAL_PRIORITY); | 200 COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::NORMAL_PRIORITY); |
| 180 break; | 201 break; |
| 181 } | 202 } |
| 182 current_policy_ = new_policy; | 203 current_policy_ = new_policy; |
| 204 | |
| 205 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( | |
| 206 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", | |
| 207 this, AsValueLocked(now)); | |
| 208 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | |
| 209 "RendererScheduler.policy", current_policy_); | |
| 183 } | 210 } |
| 184 | 211 |
| 185 void RendererSchedulerImpl::StartIdlePeriod() { | 212 void RendererSchedulerImpl::StartIdlePeriod() { |
| 213 TRACE_EVENT_ASYNC_BEGIN0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | |
| 214 "RendererSchedulerIdlePeriod", this); | |
| 186 main_thread_checker_.CalledOnValidThread(); | 215 main_thread_checker_.CalledOnValidThread(); |
| 187 renderer_task_queue_selector_->EnableQueue( | 216 renderer_task_queue_selector_->EnableQueue( |
| 188 IDLE_TASK_QUEUE, RendererTaskQueueSelector::BEST_EFFORT_PRIORITY); | 217 IDLE_TASK_QUEUE, RendererTaskQueueSelector::BEST_EFFORT_PRIORITY); |
| 189 task_queue_manager_->PumpQueue(IDLE_TASK_QUEUE); | 218 task_queue_manager_->PumpQueue(IDLE_TASK_QUEUE); |
| 190 } | 219 } |
| 191 | 220 |
| 192 void RendererSchedulerImpl::EndIdlePeriod() { | 221 void RendererSchedulerImpl::EndIdlePeriod() { |
| 222 TRACE_EVENT_ASYNC_END0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | |
| 223 "RendererSchedulerIdlePeriod", this); | |
| 193 main_thread_checker_.CalledOnValidThread(); | 224 main_thread_checker_.CalledOnValidThread(); |
| 194 renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE); | 225 renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE); |
| 195 } | 226 } |
| 196 | 227 |
| 197 base::TimeTicks RendererSchedulerImpl::Now() const { | 228 base::TimeTicks RendererSchedulerImpl::Now() const { |
| 198 return gfx::FrameTime::Now(); | 229 return gfx::FrameTime::Now(); |
| 199 } | 230 } |
| 200 | 231 |
| 201 RendererSchedulerImpl::PollableNeedsUpdateFlag::PollableNeedsUpdateFlag( | 232 RendererSchedulerImpl::PollableNeedsUpdateFlag::PollableNeedsUpdateFlag( |
| 202 base::Lock* write_lock_) | 233 base::Lock* write_lock_) |
| 203 : flag_(false), write_lock_(write_lock_) { | 234 : flag_(false), write_lock_(write_lock_) { |
| 204 } | 235 } |
| 205 | 236 |
| 206 RendererSchedulerImpl::PollableNeedsUpdateFlag::~PollableNeedsUpdateFlag() { | 237 RendererSchedulerImpl::PollableNeedsUpdateFlag::~PollableNeedsUpdateFlag() { |
| 207 } | 238 } |
| 208 | 239 |
| 209 void RendererSchedulerImpl::PollableNeedsUpdateFlag::SetLocked(bool value) { | 240 void RendererSchedulerImpl::PollableNeedsUpdateFlag::SetLocked(bool value) { |
| 210 write_lock_->AssertAcquired(); | 241 write_lock_->AssertAcquired(); |
| 211 base::subtle::Release_Store(&flag_, value); | 242 base::subtle::Release_Store(&flag_, value); |
| 212 } | 243 } |
| 213 | 244 |
| 214 bool RendererSchedulerImpl::PollableNeedsUpdateFlag::IsSet() const { | 245 bool RendererSchedulerImpl::PollableNeedsUpdateFlag::IsSet() const { |
| 215 thread_checker_.CalledOnValidThread(); | 246 thread_checker_.CalledOnValidThread(); |
| 216 return base::subtle::Acquire_Load(&flag_) != 0; | 247 return base::subtle::Acquire_Load(&flag_) != 0; |
| 217 } | 248 } |
| 249 | |
| 250 // static | |
| 251 const char* RendererSchedulerImpl::TaskQueueIdToString(QueueId queue_id) { | |
| 252 switch (queue_id) { | |
| 253 case DEFAULT_TASK_QUEUE: | |
| 254 return "default_tq"; | |
| 255 case COMPOSITOR_TASK_QUEUE: | |
| 256 return "compositor_tq"; | |
| 257 case IDLE_TASK_QUEUE: | |
| 258 return "idle_tq"; | |
| 259 case CONTROL_TASK_QUEUE: | |
| 260 return "control_tq"; | |
| 261 default: | |
| 262 NOTREACHED(); | |
| 263 return nullptr; | |
| 264 } | |
| 265 } | |
| 266 | |
| 267 // static | |
| 268 const char* RendererSchedulerImpl::PolicyToString(Policy policy) { | |
| 269 switch (policy) { | |
| 270 case NORMAL_PRIORITY_POLICY: | |
| 271 return "normal"; | |
| 272 case COMPOSITOR_PRIORITY_POLICY: | |
| 273 return "compositor"; | |
| 274 default: | |
| 275 NOTREACHED(); | |
| 276 return nullptr; | |
| 277 } | |
| 278 } | |
| 279 | |
| 280 scoped_refptr<base::debug::ConvertableToTraceFormat> | |
| 281 RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const { | |
| 282 main_thread_checker_.CalledOnValidThread(); | |
| 283 incoming_signals_lock_.AssertAcquired(); | |
| 284 | |
| 285 if (optional_now.is_null()) | |
| 286 optional_now = Now(); | |
| 287 scoped_refptr<base::debug::TracedValue> state = | |
| 288 new base::debug::TracedValue(); | |
| 289 | |
| 290 state->SetString("current_policy", PolicyToString(current_policy_)); | |
| 291 state->SetBoolean("has_task_queue_manager", task_queue_manager_.get()); | |
|
no sievers
2014/11/10 23:15:27
Do you really care about this? The only call site
| |
| 292 state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF()); | |
| 293 state->SetDouble("last_input_time", | |
| 294 (last_input_time_ - base::TimeTicks()).InMillisecondsF()); | |
| 295 state->SetDouble( | |
| 296 "estimated_next_frame_begin", | |
| 297 (estimated_next_frame_begin_ - base::TimeTicks()).InMillisecondsF()); | |
| 298 | |
| 299 return state; | |
| 300 } | |
| 301 | |
| 218 } // namespace content | 302 } // namespace content |
| OLD | NEW |