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( |
94 blink::WebInputEvent::Type type) { | 112 blink::WebInputEvent::Type type) { |
| 113 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 114 "RendererSchedulerImpl::DidReceiveInputEventOnCompositorThread"); |
95 // Ignore mouse events because on windows these can very frequent. | 115 // Ignore mouse events because on windows these can very frequent. |
96 // Ignore keyboard events because it doesn't really make sense to enter | 116 // Ignore keyboard events because it doesn't really make sense to enter |
97 // compositor priority for them. | 117 // compositor priority for them. |
98 if (blink::WebInputEvent::isMouseEventType(type) || | 118 if (blink::WebInputEvent::isMouseEventType(type) || |
99 blink::WebInputEvent::isKeyboardEventType(type)) { | 119 blink::WebInputEvent::isKeyboardEventType(type)) { |
100 return; | 120 return; |
101 } | 121 } |
102 UpdateForInputEvent(); | 122 UpdateForInputEvent(); |
103 } | 123 } |
104 | 124 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 control_task_runner_->PostDelayedTask(FROM_HERE, update_policy_closure_, | 173 control_task_runner_->PostDelayedTask(FROM_HERE, update_policy_closure_, |
154 delay); | 174 delay); |
155 } | 175 } |
156 | 176 |
157 void RendererSchedulerImpl::UpdatePolicy() { | 177 void RendererSchedulerImpl::UpdatePolicy() { |
158 main_thread_checker_.CalledOnValidThread(); | 178 main_thread_checker_.CalledOnValidThread(); |
159 if (!task_queue_manager_) | 179 if (!task_queue_manager_) |
160 return; | 180 return; |
161 | 181 |
162 base::AutoLock lock(incoming_signals_lock_); | 182 base::AutoLock lock(incoming_signals_lock_); |
| 183 base::TimeTicks now; |
163 policy_may_need_update_.SetLocked(false); | 184 policy_may_need_update_.SetLocked(false); |
164 | 185 |
165 Policy new_policy = NORMAL_PRIORITY_POLICY; | 186 Policy new_policy = NORMAL_PRIORITY_POLICY; |
166 if (!last_input_time_.is_null()) { | 187 if (!last_input_time_.is_null()) { |
167 base::TimeDelta compositor_priority_duration = | 188 base::TimeDelta compositor_priority_duration = |
168 base::TimeDelta::FromMilliseconds(kCompositorPriorityAfterTouchMillis); | 189 base::TimeDelta::FromMilliseconds(kCompositorPriorityAfterTouchMillis); |
169 base::TimeTicks compositor_priority_end(last_input_time_ + | 190 base::TimeTicks compositor_priority_end(last_input_time_ + |
170 compositor_priority_duration); | 191 compositor_priority_duration); |
171 base::TimeTicks now(Now()); | 192 now = Now(); |
172 if (compositor_priority_end > now) { | 193 if (compositor_priority_end > now) { |
173 PostUpdatePolicyOnControlRunner(compositor_priority_end - now); | 194 PostUpdatePolicyOnControlRunner(compositor_priority_end - now); |
174 new_policy = COMPOSITOR_PRIORITY_POLICY; | 195 new_policy = COMPOSITOR_PRIORITY_POLICY; |
175 } else { | 196 } else { |
176 // Null out last_input_time_ to ensure | 197 // Null out last_input_time_ to ensure |
177 // DidReceiveInputEventOnCompositorThread will post an | 198 // DidReceiveInputEventOnCompositorThread will post an |
178 // UpdatePolicy task when it's next called. | 199 // UpdatePolicy task when it's next called. |
179 last_input_time_ = base::TimeTicks(); | 200 last_input_time_ = base::TimeTicks(); |
180 } | 201 } |
181 } | 202 } |
182 | 203 |
183 if (new_policy == current_policy_) | 204 if (new_policy == current_policy_) |
184 return; | 205 return; |
185 | 206 |
186 switch (new_policy) { | 207 switch (new_policy) { |
187 case COMPOSITOR_PRIORITY_POLICY: | 208 case COMPOSITOR_PRIORITY_POLICY: |
188 renderer_task_queue_selector_->SetQueuePriority( | 209 renderer_task_queue_selector_->SetQueuePriority( |
189 COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::HIGH_PRIORITY); | 210 COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::HIGH_PRIORITY); |
190 break; | 211 break; |
191 case NORMAL_PRIORITY_POLICY: | 212 case NORMAL_PRIORITY_POLICY: |
192 renderer_task_queue_selector_->SetQueuePriority( | 213 renderer_task_queue_selector_->SetQueuePriority( |
193 COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::NORMAL_PRIORITY); | 214 COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::NORMAL_PRIORITY); |
194 break; | 215 break; |
195 } | 216 } |
196 current_policy_ = new_policy; | 217 current_policy_ = new_policy; |
| 218 |
| 219 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
| 220 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", |
| 221 this, AsValueLocked(now)); |
| 222 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 223 "RendererScheduler.policy", current_policy_); |
197 } | 224 } |
198 | 225 |
199 void RendererSchedulerImpl::StartIdlePeriod() { | 226 void RendererSchedulerImpl::StartIdlePeriod() { |
| 227 TRACE_EVENT_ASYNC_BEGIN0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 228 "RendererSchedulerIdlePeriod", this); |
200 main_thread_checker_.CalledOnValidThread(); | 229 main_thread_checker_.CalledOnValidThread(); |
201 renderer_task_queue_selector_->EnableQueue( | 230 renderer_task_queue_selector_->EnableQueue( |
202 IDLE_TASK_QUEUE, RendererTaskQueueSelector::BEST_EFFORT_PRIORITY); | 231 IDLE_TASK_QUEUE, RendererTaskQueueSelector::BEST_EFFORT_PRIORITY); |
203 task_queue_manager_->PumpQueue(IDLE_TASK_QUEUE); | 232 task_queue_manager_->PumpQueue(IDLE_TASK_QUEUE); |
204 } | 233 } |
205 | 234 |
206 void RendererSchedulerImpl::EndIdlePeriod() { | 235 void RendererSchedulerImpl::EndIdlePeriod() { |
| 236 TRACE_EVENT_ASYNC_END0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 237 "RendererSchedulerIdlePeriod", this); |
207 main_thread_checker_.CalledOnValidThread(); | 238 main_thread_checker_.CalledOnValidThread(); |
208 renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE); | 239 renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE); |
209 } | 240 } |
210 | 241 |
211 base::TimeTicks RendererSchedulerImpl::Now() const { | 242 base::TimeTicks RendererSchedulerImpl::Now() const { |
212 return gfx::FrameTime::Now(); | 243 return gfx::FrameTime::Now(); |
213 } | 244 } |
214 | 245 |
215 RendererSchedulerImpl::PollableNeedsUpdateFlag::PollableNeedsUpdateFlag( | 246 RendererSchedulerImpl::PollableNeedsUpdateFlag::PollableNeedsUpdateFlag( |
216 base::Lock* write_lock_) | 247 base::Lock* write_lock_) |
217 : flag_(false), write_lock_(write_lock_) { | 248 : flag_(false), write_lock_(write_lock_) { |
218 } | 249 } |
219 | 250 |
220 RendererSchedulerImpl::PollableNeedsUpdateFlag::~PollableNeedsUpdateFlag() { | 251 RendererSchedulerImpl::PollableNeedsUpdateFlag::~PollableNeedsUpdateFlag() { |
221 } | 252 } |
222 | 253 |
223 void RendererSchedulerImpl::PollableNeedsUpdateFlag::SetLocked(bool value) { | 254 void RendererSchedulerImpl::PollableNeedsUpdateFlag::SetLocked(bool value) { |
224 write_lock_->AssertAcquired(); | 255 write_lock_->AssertAcquired(); |
225 base::subtle::Release_Store(&flag_, value); | 256 base::subtle::Release_Store(&flag_, value); |
226 } | 257 } |
227 | 258 |
228 bool RendererSchedulerImpl::PollableNeedsUpdateFlag::IsSet() const { | 259 bool RendererSchedulerImpl::PollableNeedsUpdateFlag::IsSet() const { |
229 thread_checker_.CalledOnValidThread(); | 260 thread_checker_.CalledOnValidThread(); |
230 return base::subtle::Acquire_Load(&flag_) != 0; | 261 return base::subtle::Acquire_Load(&flag_) != 0; |
231 } | 262 } |
| 263 |
| 264 // static |
| 265 const char* RendererSchedulerImpl::TaskQueueIdToString(QueueId queue_id) { |
| 266 switch (queue_id) { |
| 267 case DEFAULT_TASK_QUEUE: |
| 268 return "default_tq"; |
| 269 case COMPOSITOR_TASK_QUEUE: |
| 270 return "compositor_tq"; |
| 271 case IDLE_TASK_QUEUE: |
| 272 return "idle_tq"; |
| 273 case CONTROL_TASK_QUEUE: |
| 274 return "control_tq"; |
| 275 default: |
| 276 NOTREACHED(); |
| 277 return nullptr; |
| 278 } |
| 279 } |
| 280 |
| 281 // static |
| 282 const char* RendererSchedulerImpl::PolicyToString(Policy policy) { |
| 283 switch (policy) { |
| 284 case NORMAL_PRIORITY_POLICY: |
| 285 return "normal"; |
| 286 case COMPOSITOR_PRIORITY_POLICY: |
| 287 return "compositor"; |
| 288 default: |
| 289 NOTREACHED(); |
| 290 return nullptr; |
| 291 } |
| 292 } |
| 293 |
| 294 scoped_refptr<base::debug::ConvertableToTraceFormat> |
| 295 RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const { |
| 296 main_thread_checker_.CalledOnValidThread(); |
| 297 incoming_signals_lock_.AssertAcquired(); |
| 298 |
| 299 if (optional_now.is_null()) |
| 300 optional_now = Now(); |
| 301 scoped_refptr<base::debug::TracedValue> state = |
| 302 new base::debug::TracedValue(); |
| 303 |
| 304 state->SetString("current_policy", PolicyToString(current_policy_)); |
| 305 state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF()); |
| 306 state->SetDouble("last_input_time", |
| 307 (last_input_time_ - base::TimeTicks()).InMillisecondsF()); |
| 308 state->SetDouble( |
| 309 "estimated_next_frame_begin", |
| 310 (estimated_next_frame_begin_ - base::TimeTicks()).InMillisecondsF()); |
| 311 |
| 312 return state; |
| 313 } |
| 314 |
232 } // namespace content | 315 } // namespace content |
OLD | NEW |