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 |