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

Side by Side Diff: content/renderer/scheduler/renderer_scheduler_impl.cc

Issue 994833003: Prevent multiple pending UpdatePolicy tasks. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Change for Ross Created 5 years, 9 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 "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/message_loop/message_loop_proxy.h" 8 #include "base/message_loop/message_loop_proxy.h"
9 #include "base/trace_event/trace_event.h" 9 #include "base/trace_event/trace_event.h"
10 #include "base/trace_event/trace_event_argument.h" 10 #include "base/trace_event/trace_event_argument.h"
(...skipping 13 matching lines...) Expand all
24 control_task_runner_( 24 control_task_runner_(
25 task_queue_manager_->TaskRunnerForQueue(CONTROL_TASK_QUEUE)), 25 task_queue_manager_->TaskRunnerForQueue(CONTROL_TASK_QUEUE)),
26 control_task_after_wakeup_runner_(task_queue_manager_->TaskRunnerForQueue( 26 control_task_after_wakeup_runner_(task_queue_manager_->TaskRunnerForQueue(
27 CONTROL_TASK_AFTER_WAKEUP_QUEUE)), 27 CONTROL_TASK_AFTER_WAKEUP_QUEUE)),
28 default_task_runner_( 28 default_task_runner_(
29 task_queue_manager_->TaskRunnerForQueue(DEFAULT_TASK_QUEUE)), 29 task_queue_manager_->TaskRunnerForQueue(DEFAULT_TASK_QUEUE)),
30 compositor_task_runner_( 30 compositor_task_runner_(
31 task_queue_manager_->TaskRunnerForQueue(COMPOSITOR_TASK_QUEUE)), 31 task_queue_manager_->TaskRunnerForQueue(COMPOSITOR_TASK_QUEUE)),
32 loading_task_runner_( 32 loading_task_runner_(
33 task_queue_manager_->TaskRunnerForQueue(LOADING_TASK_QUEUE)), 33 task_queue_manager_->TaskRunnerForQueue(LOADING_TASK_QUEUE)),
34 delayed_update_policy_runner_(
35 base::Bind(&RendererSchedulerImpl::UpdatePolicy,
36 base::Unretained(this)),
37 control_task_runner_),
34 current_policy_(Policy::NORMAL), 38 current_policy_(Policy::NORMAL),
35 last_input_type_(blink::WebInputEvent::Undefined), 39 last_input_type_(blink::WebInputEvent::Undefined),
36 input_stream_state_(InputStreamState::INACTIVE), 40 input_stream_state_(InputStreamState::INACTIVE),
37 policy_may_need_update_(&incoming_signals_lock_), 41 policy_may_need_update_(&incoming_signals_lock_),
38 weak_factory_(this) { 42 weak_factory_(this) {
39 weak_renderer_scheduler_ptr_ = weak_factory_.GetWeakPtr(); 43 weak_renderer_scheduler_ptr_ = weak_factory_.GetWeakPtr();
40 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy, 44 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy,
41 weak_renderer_scheduler_ptr_); 45 weak_renderer_scheduler_ptr_);
42 end_idle_period_closure_.Reset(base::Bind( 46 end_idle_period_closure_.Reset(base::Bind(
43 &RendererSchedulerImpl::EndIdlePeriod, weak_renderer_scheduler_ptr_)); 47 &RendererSchedulerImpl::EndIdlePeriod, weak_renderer_scheduler_ptr_));
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 void RendererSchedulerImpl::UpdateForInputEvent( 182 void RendererSchedulerImpl::UpdateForInputEvent(
179 blink::WebInputEvent::Type type) { 183 blink::WebInputEvent::Type type) {
180 base::AutoLock lock(incoming_signals_lock_); 184 base::AutoLock lock(incoming_signals_lock_);
181 185
182 InputStreamState new_input_stream_state = 186 InputStreamState new_input_stream_state =
183 ComputeNewInputStreamState(input_stream_state_, type, last_input_type_); 187 ComputeNewInputStreamState(input_stream_state_, type, last_input_type_);
184 188
185 if (input_stream_state_ != new_input_stream_state) { 189 if (input_stream_state_ != new_input_stream_state) {
186 // Update scheduler policy if we should start a new policy mode. 190 // Update scheduler policy if we should start a new policy mode.
187 input_stream_state_ = new_input_stream_state; 191 input_stream_state_ = new_input_stream_state;
188 policy_may_need_update_.SetWhileLocked(true); 192 EnsureUgentPolicyUpdatePostedOnMainThread(FROM_HERE);
189 PostUpdatePolicyOnControlRunner(base::TimeDelta());
190 } 193 }
191 last_input_receipt_time_on_compositor_ = Now(); 194 last_input_receipt_time_on_compositor_ = Now();
192 // Clear the last known input processing time so that we know an input event 195 // Clear the last known input processing time so that we know an input event
193 // is still queued up. This timestamp will be updated the next time the 196 // is still queued up. This timestamp will be updated the next time the
194 // compositor commits or becomes quiescent. Note that this function is always 197 // compositor commits or becomes quiescent. Note that this function is always
195 // called before the input event is processed either on the compositor or 198 // called before the input event is processed either on the compositor or
196 // main threads. 199 // main threads.
197 last_input_process_time_on_main_ = base::TimeTicks(); 200 last_input_process_time_on_main_ = base::TimeTicks();
198 last_input_type_ = type; 201 last_input_type_ = type;
199 } 202 }
200 203
201 void RendererSchedulerImpl::DidProcessInputEvent( 204 void RendererSchedulerImpl::DidProcessInputEvent(
202 base::TimeTicks begin_frame_time) { 205 base::TimeTicks begin_frame_time) {
206 DCHECK(main_thread_checker_.CalledOnValidThread());
203 base::AutoLock lock(incoming_signals_lock_); 207 base::AutoLock lock(incoming_signals_lock_);
204 if (input_stream_state_ == InputStreamState::INACTIVE) 208 if (input_stream_state_ == InputStreamState::INACTIVE)
205 return; 209 return;
206 // Avoid marking input that arrived after the BeginFrame as processed. 210 // Avoid marking input that arrived after the BeginFrame as processed.
207 if (!begin_frame_time.is_null() && 211 if (!begin_frame_time.is_null() &&
208 begin_frame_time < last_input_receipt_time_on_compositor_) 212 begin_frame_time < last_input_receipt_time_on_compositor_)
209 return; 213 return;
210 last_input_process_time_on_main_ = Now(); 214 last_input_process_time_on_main_ = Now();
211 policy_may_need_update_.SetWhileLocked(true); 215 UpdatePolicyLocked();
212 } 216 }
213 217
214 bool RendererSchedulerImpl::IsHighPriorityWorkAnticipated() { 218 bool RendererSchedulerImpl::IsHighPriorityWorkAnticipated() {
215 DCHECK(main_thread_checker_.CalledOnValidThread()); 219 DCHECK(main_thread_checker_.CalledOnValidThread());
216 if (!task_queue_manager_) 220 if (!task_queue_manager_)
217 return false; 221 return false;
218 222
219 MaybeUpdatePolicy(); 223 MaybeUpdatePolicy();
220 // The touchstart and compositor policies indicate a strong likelihood of 224 // The touchstart and compositor policies indicate a strong likelihood of
221 // high-priority work in the near future. 225 // high-priority work in the near future.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 return current_policy_; 265 return current_policy_;
262 } 266 }
263 267
264 void RendererSchedulerImpl::MaybeUpdatePolicy() { 268 void RendererSchedulerImpl::MaybeUpdatePolicy() {
265 DCHECK(main_thread_checker_.CalledOnValidThread()); 269 DCHECK(main_thread_checker_.CalledOnValidThread());
266 if (policy_may_need_update_.IsSet()) { 270 if (policy_may_need_update_.IsSet()) {
267 UpdatePolicy(); 271 UpdatePolicy();
268 } 272 }
269 } 273 }
270 274
271 void RendererSchedulerImpl::PostUpdatePolicyOnControlRunner( 275 void RendererSchedulerImpl::EnsureUgentPolicyUpdatePostedOnMainThread(
272 base::TimeDelta delay) { 276 const tracked_objects::Location& from_here) {
273 control_task_runner_->PostDelayedTask( 277 // TODO(scheduler-dev): Check that this method isn't called from the main
274 FROM_HERE, update_policy_closure_, delay); 278 // thread.
279 incoming_signals_lock_.AssertAcquired();
280 if (!policy_may_need_update_.IsSet()) {
281 policy_may_need_update_.SetWhileLocked(true);
282 control_task_runner_->PostTask(from_here, update_policy_closure_);
283 }
275 } 284 }
276 285
277 void RendererSchedulerImpl::UpdatePolicy() { 286 void RendererSchedulerImpl::UpdatePolicy() {
287 base::AutoLock lock(incoming_signals_lock_);
288 UpdatePolicyLocked();
289 }
290
291 void RendererSchedulerImpl::UpdatePolicyLocked() {
278 DCHECK(main_thread_checker_.CalledOnValidThread()); 292 DCHECK(main_thread_checker_.CalledOnValidThread());
293 incoming_signals_lock_.AssertAcquired();
279 if (!task_queue_manager_) 294 if (!task_queue_manager_)
280 return; 295 return;
281 296
282 base::AutoLock lock(incoming_signals_lock_); 297 base::TimeTicks now = Now();
283 base::TimeTicks now;
284 policy_may_need_update_.SetWhileLocked(false); 298 policy_may_need_update_.SetWhileLocked(false);
285 299
286 base::TimeDelta new_policy_duration; 300 base::TimeDelta new_policy_duration;
287 Policy new_policy = ComputeNewPolicy(&new_policy_duration); 301 Policy new_policy = ComputeNewPolicy(&new_policy_duration, now);
288 if (new_policy_duration > base::TimeDelta()) 302 if (new_policy_duration > base::TimeDelta())
289 PostUpdatePolicyOnControlRunner(new_policy_duration); 303 delayed_update_policy_runner_.SetDeadline(FROM_HERE, new_policy_duration,
Sami 2015/03/12 18:15:22 nit: add {} for multiline if.
alex clarke (OOO till 29th) 2015/03/12 18:24:08 Done.
304 now);
290 305
291 if (new_policy == current_policy_) 306 if (new_policy == current_policy_)
292 return; 307 return;
293 308
294 switch (new_policy) { 309 switch (new_policy) {
295 case Policy::COMPOSITOR_PRIORITY: 310 case Policy::COMPOSITOR_PRIORITY:
296 renderer_task_queue_selector_->SetQueuePriority( 311 renderer_task_queue_selector_->SetQueuePriority(
297 COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::HIGH_PRIORITY); 312 COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::HIGH_PRIORITY);
298 // TODO(scheduler-dev): Add a task priority between HIGH and BEST_EFFORT 313 // TODO(scheduler-dev): Add a task priority between HIGH and BEST_EFFORT
299 // that still has some guarantee of running. 314 // that still has some guarantee of running.
(...skipping 19 matching lines...) Expand all
319 current_policy_ = new_policy; 334 current_policy_ = new_policy;
320 335
321 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( 336 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
322 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", 337 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler",
323 this, AsValueLocked(now)); 338 this, AsValueLocked(now));
324 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), 339 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
325 "RendererScheduler.policy", current_policy_); 340 "RendererScheduler.policy", current_policy_);
326 } 341 }
327 342
328 RendererSchedulerImpl::Policy RendererSchedulerImpl::ComputeNewPolicy( 343 RendererSchedulerImpl::Policy RendererSchedulerImpl::ComputeNewPolicy(
329 base::TimeDelta* new_policy_duration) { 344 base::TimeDelta* new_policy_duration,
345 base::TimeTicks now) {
330 DCHECK(main_thread_checker_.CalledOnValidThread()); 346 DCHECK(main_thread_checker_.CalledOnValidThread());
331 incoming_signals_lock_.AssertAcquired(); 347 incoming_signals_lock_.AssertAcquired();
332 348
333 Policy new_policy = Policy::NORMAL; 349 Policy new_policy = Policy::NORMAL;
334 *new_policy_duration = base::TimeDelta(); 350 *new_policy_duration = base::TimeDelta();
335 351
336 if (input_stream_state_ == InputStreamState::INACTIVE) 352 if (input_stream_state_ == InputStreamState::INACTIVE)
337 return new_policy; 353 return new_policy;
338 354
339 base::TimeDelta new_priority_duration = 355 base::TimeDelta new_priority_duration =
340 base::TimeDelta::FromMilliseconds(kPriorityEscalationAfterInputMillis); 356 base::TimeDelta::FromMilliseconds(kPriorityEscalationAfterInputMillis);
341 Policy input_priority_policy = 357 Policy input_priority_policy =
342 input_stream_state_ == 358 input_stream_state_ ==
343 InputStreamState::ACTIVE_AND_AWAITING_TOUCHSTART_RESPONSE 359 InputStreamState::ACTIVE_AND_AWAITING_TOUCHSTART_RESPONSE
344 ? Policy::TOUCHSTART_PRIORITY 360 ? Policy::TOUCHSTART_PRIORITY
345 : Policy::COMPOSITOR_PRIORITY; 361 : Policy::COMPOSITOR_PRIORITY;
346 362
347 // If the input event is still pending, go into input prioritized policy 363 // If the input event is still pending, go into input prioritized policy
348 // and check again later. 364 // and check again later.
349 if (last_input_process_time_on_main_.is_null() && 365 if (last_input_process_time_on_main_.is_null() &&
350 !task_queue_manager_->IsQueueEmpty(COMPOSITOR_TASK_QUEUE)) { 366 !task_queue_manager_->IsQueueEmpty(COMPOSITOR_TASK_QUEUE)) {
351 new_policy = input_priority_policy; 367 new_policy = input_priority_policy;
352 *new_policy_duration = new_priority_duration; 368 *new_policy_duration = new_priority_duration;
353 } else { 369 } else {
354 // Otherwise make sure the input prioritization policy ends on time. 370 // Otherwise make sure the input prioritization policy ends on time.
355 base::TimeTicks new_priority_end( 371 base::TimeTicks new_priority_end(
356 std::max(last_input_receipt_time_on_compositor_, 372 std::max(last_input_receipt_time_on_compositor_,
357 last_input_process_time_on_main_) + 373 last_input_process_time_on_main_) +
358 new_priority_duration); 374 new_priority_duration);
359 base::TimeDelta time_left_in_policy = new_priority_end - Now(); 375 base::TimeDelta time_left_in_policy = new_priority_end - now;
360 376
361 if (time_left_in_policy > base::TimeDelta()) { 377 if (time_left_in_policy > base::TimeDelta()) {
362 new_policy = input_priority_policy; 378 new_policy = input_priority_policy;
363 *new_policy_duration = time_left_in_policy; 379 *new_policy_duration = time_left_in_policy;
364 } else { 380 } else {
365 // Reset |input_stream_state_| to ensure 381 // Reset |input_stream_state_| to ensure
366 // DidReceiveInputEventOnCompositorThread will post an UpdatePolicy task 382 // DidReceiveInputEventOnCompositorThread will post an UpdatePolicy task
367 // when it's next called. 383 // when it's next called.
368 input_stream_state_ = InputStreamState::INACTIVE; 384 input_stream_state_ = InputStreamState::INACTIVE;
369 } 385 }
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 } 571 }
556 572
557 void RendererSchedulerImpl::RemoveTaskObserver( 573 void RendererSchedulerImpl::RemoveTaskObserver(
558 base::MessageLoop::TaskObserver* task_observer) { 574 base::MessageLoop::TaskObserver* task_observer) {
559 DCHECK(main_thread_checker_.CalledOnValidThread()); 575 DCHECK(main_thread_checker_.CalledOnValidThread());
560 if (task_queue_manager_) 576 if (task_queue_manager_)
561 task_queue_manager_->RemoveTaskObserver(task_observer); 577 task_queue_manager_->RemoveTaskObserver(task_observer);
562 } 578 }
563 579
564 } // namespace content 580 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698