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

Side by Side Diff: third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc

Issue 2258133002: [scheduler] Implement time-based cpu throttling. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Changed similarity Created 4 years, 3 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"
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 delayed_update_policy_runner_( 79 delayed_update_policy_runner_(
80 base::Bind(&RendererSchedulerImpl::UpdatePolicy, 80 base::Bind(&RendererSchedulerImpl::UpdatePolicy,
81 base::Unretained(this)), 81 base::Unretained(this)),
82 helper_.ControlTaskRunner()), 82 helper_.ControlTaskRunner()),
83 main_thread_only_(this, 83 main_thread_only_(this,
84 compositor_task_runner_, 84 compositor_task_runner_,
85 helper_.scheduler_tqm_delegate().get(), 85 helper_.scheduler_tqm_delegate().get(),
86 helper_.scheduler_tqm_delegate()->NowTicks()), 86 helper_.scheduler_tqm_delegate()->NowTicks()),
87 policy_may_need_update_(&any_thread_lock_), 87 policy_may_need_update_(&any_thread_lock_),
88 weak_factory_(this) { 88 weak_factory_(this) {
89 throttling_helper_.reset(new ThrottlingHelper(this, "renderer.scheduler")); 89 task_queue_throttler_.reset(
90 new TaskQueueThrottler(this, "renderer.scheduler"));
90 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy, 91 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy,
91 weak_factory_.GetWeakPtr()); 92 weak_factory_.GetWeakPtr());
92 end_renderer_hidden_idle_period_closure_.Reset(base::Bind( 93 end_renderer_hidden_idle_period_closure_.Reset(base::Bind(
93 &RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr())); 94 &RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr()));
94 95
95 suspend_timers_when_backgrounded_closure_.Reset( 96 suspend_timers_when_backgrounded_closure_.Reset(
96 base::Bind(&RendererSchedulerImpl::SuspendTimerQueueWhenBackgrounded, 97 base::Bind(&RendererSchedulerImpl::SuspendTimerQueueWhenBackgrounded,
97 weak_factory_.GetWeakPtr())); 98 weak_factory_.GetWeakPtr()));
98 99
99 default_loading_task_runner_ = NewLoadingTaskRunner("default_loading_tq"); 100 default_loading_task_runner_ = NewLoadingTaskRunner("default_loading_tq");
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 RendererSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly() 193 RendererSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly()
193 : last_input_type(blink::WebInputEvent::Undefined) {} 194 : last_input_type(blink::WebInputEvent::Undefined) {}
194 195
195 RendererSchedulerImpl::CompositorThreadOnly::~CompositorThreadOnly() {} 196 RendererSchedulerImpl::CompositorThreadOnly::~CompositorThreadOnly() {}
196 197
197 void RendererSchedulerImpl::Shutdown() { 198 void RendererSchedulerImpl::Shutdown() {
198 base::TimeTicks now = tick_clock()->NowTicks(); 199 base::TimeTicks now = tick_clock()->NowTicks();
199 MainThreadOnly().background_main_thread_load_tracker.RecordIdle(now); 200 MainThreadOnly().background_main_thread_load_tracker.RecordIdle(now);
200 MainThreadOnly().foreground_main_thread_load_tracker.RecordIdle(now); 201 MainThreadOnly().foreground_main_thread_load_tracker.RecordIdle(now);
201 202
202 throttling_helper_.reset(); 203 task_queue_throttler_.reset();
203 helper_.Shutdown(); 204 helper_.Shutdown();
204 MainThreadOnly().was_shutdown = true; 205 MainThreadOnly().was_shutdown = true;
205 MainThreadOnly().rail_mode_observer = nullptr; 206 MainThreadOnly().rail_mode_observer = nullptr;
206 } 207 }
207 208
208 std::unique_ptr<blink::WebThread> RendererSchedulerImpl::CreateMainThread() { 209 std::unique_ptr<blink::WebThread> RendererSchedulerImpl::CreateMainThread() {
209 return base::MakeUnique<WebThreadImplForRendererScheduler>(this); 210 return base::MakeUnique<WebThreadImplForRendererScheduler>(this);
210 } 211 }
211 212
212 scoped_refptr<TaskQueue> RendererSchedulerImpl::DefaultTaskRunner() { 213 scoped_refptr<TaskQueue> RendererSchedulerImpl::DefaultTaskRunner() {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 TaskQueue::Spec(name).SetShouldMonitorQuiescence(true).SetTimeDomain( 246 TaskQueue::Spec(name).SetShouldMonitorQuiescence(true).SetTimeDomain(
246 MainThreadOnly().use_virtual_time ? GetVirtualTimeDomain() 247 MainThreadOnly().use_virtual_time ? GetVirtualTimeDomain()
247 : nullptr))); 248 : nullptr)));
248 loading_task_runners_.insert(loading_task_queue); 249 loading_task_runners_.insert(loading_task_queue);
249 loading_task_queue->SetQueueEnabled( 250 loading_task_queue->SetQueueEnabled(
250 MainThreadOnly().current_policy.loading_queue_policy.is_enabled); 251 MainThreadOnly().current_policy.loading_queue_policy.is_enabled);
251 loading_task_queue->SetQueuePriority( 252 loading_task_queue->SetQueuePriority(
252 MainThreadOnly().current_policy.loading_queue_policy.priority); 253 MainThreadOnly().current_policy.loading_queue_policy.priority);
253 if (MainThreadOnly().current_policy.loading_queue_policy.time_domain_type == 254 if (MainThreadOnly().current_policy.loading_queue_policy.time_domain_type ==
254 TimeDomainType::THROTTLED) { 255 TimeDomainType::THROTTLED) {
255 throttling_helper_->IncreaseThrottleRefCount(loading_task_queue.get()); 256 task_queue_throttler_->IncreaseThrottleRefCount(loading_task_queue.get());
256 } 257 }
257 loading_task_queue->AddTaskObserver( 258 loading_task_queue->AddTaskObserver(
258 &MainThreadOnly().loading_task_cost_estimator); 259 &MainThreadOnly().loading_task_cost_estimator);
259 return loading_task_queue; 260 return loading_task_queue;
260 } 261 }
261 262
262 scoped_refptr<TaskQueue> RendererSchedulerImpl::NewTimerTaskRunner( 263 scoped_refptr<TaskQueue> RendererSchedulerImpl::NewTimerTaskRunner(
263 const char* name) { 264 const char* name) {
264 helper_.CheckOnValidThread(); 265 helper_.CheckOnValidThread();
265 // TODO(alexclarke): Consider using ApplyTaskQueuePolicy() for brevity. 266 // TODO(alexclarke): Consider using ApplyTaskQueuePolicy() for brevity.
266 scoped_refptr<TaskQueue> timer_task_queue( 267 scoped_refptr<TaskQueue> timer_task_queue(
267 helper_.NewTaskQueue(TaskQueue::Spec(name) 268 helper_.NewTaskQueue(TaskQueue::Spec(name)
268 .SetShouldMonitorQuiescence(true) 269 .SetShouldMonitorQuiescence(true)
269 .SetShouldReportWhenExecutionBlocked(true) 270 .SetShouldReportWhenExecutionBlocked(true)
270 .SetTimeDomain(MainThreadOnly().use_virtual_time 271 .SetTimeDomain(MainThreadOnly().use_virtual_time
271 ? GetVirtualTimeDomain() 272 ? GetVirtualTimeDomain()
272 : nullptr))); 273 : nullptr)));
273 timer_task_runners_.insert(timer_task_queue); 274 timer_task_runners_.insert(timer_task_queue);
274 timer_task_queue->SetQueueEnabled( 275 timer_task_queue->SetQueueEnabled(
275 MainThreadOnly().current_policy.timer_queue_policy.is_enabled); 276 MainThreadOnly().current_policy.timer_queue_policy.is_enabled);
276 timer_task_queue->SetQueuePriority( 277 timer_task_queue->SetQueuePriority(
277 MainThreadOnly().current_policy.timer_queue_policy.priority); 278 MainThreadOnly().current_policy.timer_queue_policy.priority);
278 if (MainThreadOnly().current_policy.timer_queue_policy.time_domain_type == 279 if (MainThreadOnly().current_policy.timer_queue_policy.time_domain_type ==
279 TimeDomainType::THROTTLED) { 280 TimeDomainType::THROTTLED) {
280 throttling_helper_->IncreaseThrottleRefCount(timer_task_queue.get()); 281 task_queue_throttler_->IncreaseThrottleRefCount(timer_task_queue.get());
281 } 282 }
282 timer_task_queue->AddTaskObserver( 283 timer_task_queue->AddTaskObserver(
283 &MainThreadOnly().timer_task_cost_estimator); 284 &MainThreadOnly().timer_task_cost_estimator);
284 return timer_task_queue; 285 return timer_task_queue;
285 } 286 }
286 287
287 scoped_refptr<TaskQueue> RendererSchedulerImpl::NewUnthrottledTaskRunner( 288 scoped_refptr<TaskQueue> RendererSchedulerImpl::NewUnthrottledTaskRunner(
288 const char* name) { 289 const char* name) {
289 helper_.CheckOnValidThread(); 290 helper_.CheckOnValidThread();
290 scoped_refptr<TaskQueue> unthrottled_task_queue(helper_.NewTaskQueue( 291 scoped_refptr<TaskQueue> unthrottled_task_queue(helper_.NewTaskQueue(
291 TaskQueue::Spec(name).SetShouldMonitorQuiescence(true).SetTimeDomain( 292 TaskQueue::Spec(name).SetShouldMonitorQuiescence(true).SetTimeDomain(
292 MainThreadOnly().use_virtual_time ? GetVirtualTimeDomain() 293 MainThreadOnly().use_virtual_time ? GetVirtualTimeDomain()
293 : nullptr))); 294 : nullptr)));
294 unthrottled_task_runners_.insert(unthrottled_task_queue); 295 unthrottled_task_runners_.insert(unthrottled_task_queue);
295 return unthrottled_task_queue; 296 return unthrottled_task_queue;
296 } 297 }
297 298
298 std::unique_ptr<RenderWidgetSchedulingState> 299 std::unique_ptr<RenderWidgetSchedulingState>
299 RendererSchedulerImpl::NewRenderWidgetSchedulingState() { 300 RendererSchedulerImpl::NewRenderWidgetSchedulingState() {
300 return render_widget_scheduler_signals_.NewRenderWidgetSchedulingState(); 301 return render_widget_scheduler_signals_.NewRenderWidgetSchedulingState();
301 } 302 }
302 303
303 void RendererSchedulerImpl::OnUnregisterTaskQueue( 304 void RendererSchedulerImpl::OnUnregisterTaskQueue(
304 const scoped_refptr<TaskQueue>& task_queue) { 305 const scoped_refptr<TaskQueue>& task_queue) {
305 if (throttling_helper_.get()) 306 if (task_queue_throttler_.get())
306 throttling_helper_->UnregisterTaskQueue(task_queue.get()); 307 task_queue_throttler_->UnregisterTaskQueue(task_queue.get());
307 308
308 if (loading_task_runners_.find(task_queue) != loading_task_runners_.end()) { 309 if (loading_task_runners_.find(task_queue) != loading_task_runners_.end()) {
309 task_queue->RemoveTaskObserver( 310 task_queue->RemoveTaskObserver(
310 &MainThreadOnly().loading_task_cost_estimator); 311 &MainThreadOnly().loading_task_cost_estimator);
311 loading_task_runners_.erase(task_queue); 312 loading_task_runners_.erase(task_queue);
312 } else if (timer_task_runners_.find(task_queue) != 313 } else if (timer_task_runners_.find(task_queue) !=
313 timer_task_runners_.end()) { 314 timer_task_runners_.end()) {
314 task_queue->RemoveTaskObserver(&MainThreadOnly().timer_task_cost_estimator); 315 task_queue->RemoveTaskObserver(&MainThreadOnly().timer_task_cost_estimator);
315 timer_task_runners_.erase(task_queue); 316 timer_task_runners_.erase(task_queue);
316 } else if (unthrottled_task_runners_.find(task_queue) != 317 } else if (unthrottled_task_runners_.find(task_queue) !=
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after
1020 1021
1021 DCHECK(compositor_task_runner_->IsQueueEnabled()); 1022 DCHECK(compositor_task_runner_->IsQueueEnabled());
1022 MainThreadOnly().current_policy = new_policy; 1023 MainThreadOnly().current_policy = new_policy;
1023 } 1024 }
1024 1025
1025 void RendererSchedulerImpl::ApplyTaskQueuePolicy( 1026 void RendererSchedulerImpl::ApplyTaskQueuePolicy(
1026 TaskQueue* task_queue, 1027 TaskQueue* task_queue,
1027 const TaskQueuePolicy& old_task_queue_policy, 1028 const TaskQueuePolicy& old_task_queue_policy,
1028 const TaskQueuePolicy& new_task_queue_policy) const { 1029 const TaskQueuePolicy& new_task_queue_policy) const {
1029 if (old_task_queue_policy.is_enabled != new_task_queue_policy.is_enabled) { 1030 if (old_task_queue_policy.is_enabled != new_task_queue_policy.is_enabled) {
1030 throttling_helper_->SetQueueEnabled(task_queue, 1031 task_queue_throttler_->SetQueueEnabled(task_queue,
1031 new_task_queue_policy.is_enabled); 1032 new_task_queue_policy.is_enabled);
1032 } 1033 }
1033 1034
1034 if (old_task_queue_policy.priority != new_task_queue_policy.priority) 1035 if (old_task_queue_policy.priority != new_task_queue_policy.priority)
1035 task_queue->SetQueuePriority(new_task_queue_policy.priority); 1036 task_queue->SetQueuePriority(new_task_queue_policy.priority);
1036 1037
1037 if (old_task_queue_policy.time_domain_type != 1038 if (old_task_queue_policy.time_domain_type !=
1038 new_task_queue_policy.time_domain_type) { 1039 new_task_queue_policy.time_domain_type) {
1039 if (old_task_queue_policy.time_domain_type == TimeDomainType::THROTTLED) { 1040 if (old_task_queue_policy.time_domain_type == TimeDomainType::THROTTLED) {
1040 throttling_helper_->DecreaseThrottleRefCount(task_queue); 1041 task_queue_throttler_->DecreaseThrottleRefCount(task_queue);
1041 } else if (new_task_queue_policy.time_domain_type == 1042 } else if (new_task_queue_policy.time_domain_type ==
1042 TimeDomainType::THROTTLED) { 1043 TimeDomainType::THROTTLED) {
1043 throttling_helper_->IncreaseThrottleRefCount(task_queue); 1044 task_queue_throttler_->IncreaseThrottleRefCount(task_queue);
1044 } else if (new_task_queue_policy.time_domain_type == 1045 } else if (new_task_queue_policy.time_domain_type ==
1045 TimeDomainType::VIRTUAL) { 1046 TimeDomainType::VIRTUAL) {
1046 DCHECK(virtual_time_domain_); 1047 DCHECK(virtual_time_domain_);
1047 task_queue->SetTimeDomain(virtual_time_domain_.get()); 1048 task_queue->SetTimeDomain(virtual_time_domain_.get());
1048 } 1049 }
1049 } 1050 }
1050 } 1051 }
1051 1052
1052 RendererSchedulerImpl::UseCase RendererSchedulerImpl::ComputeCurrentUseCase( 1053 RendererSchedulerImpl::UseCase RendererSchedulerImpl::ComputeCurrentUseCase(
1053 base::TimeTicks now, 1054 base::TimeTicks now,
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
1454 true; 1455 true;
1455 BroadcastIntervention( 1456 BroadcastIntervention(
1456 "Blink deferred a task in order to make scrolling smoother. " 1457 "Blink deferred a task in order to make scrolling smoother. "
1457 "Your timer and network tasks should take less than 50ms to run " 1458 "Your timer and network tasks should take less than 50ms to run "
1458 "to avoid this. Please see " 1459 "to avoid this. Please see "
1459 "https://developers.google.com/web/tools/chrome-devtools/profile/evaluat e-performance/rail" 1460 "https://developers.google.com/web/tools/chrome-devtools/profile/evaluat e-performance/rail"
1460 " and https://crbug.com/574343#c40 for more information."); 1461 " and https://crbug.com/574343#c40 for more information.");
1461 } 1462 }
1462 } 1463 }
1463 1464
1464 void RendererSchedulerImpl::ReportTaskTime(double start_time, double end_time) { 1465 void RendererSchedulerImpl::ReportTaskTime(TaskQueue* task_queue,
1465 base::TimeTicks start_time_ticks = 1466 base::TimeTicks start_time,
1466 MonotonicTimeInSecondsToTimeTicks(start_time); 1467 base::TimeTicks end_time) {
1467 base::TimeTicks end_time_ticks = MonotonicTimeInSecondsToTimeTicks(end_time); 1468 MainThreadOnly().queueing_time_estimator.OnToplevelTaskCompleted(start_time,
1469 end_time);
1468 1470
1469 MainThreadOnly().queueing_time_estimator.OnToplevelTaskCompleted( 1471 task_queue_throttler()->OnTaskRunTimeReported(task_queue, start_time,
1470 start_time_ticks, end_time_ticks); 1472 end_time);
1473
1471 // We want to measure thread time here, but for efficiency reasons 1474 // We want to measure thread time here, but for efficiency reasons
1472 // we stick with wall time. 1475 // we stick with wall time.
1473 MainThreadOnly().foreground_main_thread_load_tracker.RecordTaskTime( 1476 MainThreadOnly().foreground_main_thread_load_tracker.RecordTaskTime(
1474 start_time_ticks, end_time_ticks); 1477 start_time, end_time);
1475 MainThreadOnly().background_main_thread_load_tracker.RecordTaskTime( 1478 MainThreadOnly().background_main_thread_load_tracker.RecordTaskTime(
1476 start_time_ticks, end_time_ticks); 1479 start_time, end_time);
1477 // TODO(altimin): Per-page metrics should also be considered. 1480 // TODO(altimin): Per-page metrics should also be considered.
1481
1478 UMA_HISTOGRAM_CUSTOM_COUNTS("RendererScheduler.TaskTime", 1482 UMA_HISTOGRAM_CUSTOM_COUNTS("RendererScheduler.TaskTime",
1479 (end_time_ticks - start_time_ticks).InMicroseconds (), 1, 1483 (end_time - start_time).InMicroseconds(), 1,
1480 1000000, 50); 1484 1000000, 50);
1481 } 1485 }
1482 1486
1483 void RendererSchedulerImpl::AddTaskTimeObserver( 1487 void RendererSchedulerImpl::AddTaskTimeObserver(
1484 TaskTimeObserver* task_time_observer) { 1488 TaskTimeObserver* task_time_observer) {
1485 helper_.AddTaskTimeObserver(task_time_observer); 1489 helper_.AddTaskTimeObserver(task_time_observer);
1486 } 1490 }
1487 1491
1488 void RendererSchedulerImpl::RemoveTaskTimeObserver( 1492 void RendererSchedulerImpl::RemoveTaskTimeObserver(
1489 TaskTimeObserver* task_time_observer) { 1493 TaskTimeObserver* task_time_observer) {
(...skipping 19 matching lines...) Expand all
1509 } 1513 }
1510 1514
1511 void RendererSchedulerImpl::EnableVirtualTime() { 1515 void RendererSchedulerImpl::EnableVirtualTime() {
1512 MainThreadOnly().use_virtual_time = true; 1516 MainThreadOnly().use_virtual_time = true;
1513 1517
1514 // The |unthrottled_task_runners_| are not actively managed by UpdatePolicy(). 1518 // The |unthrottled_task_runners_| are not actively managed by UpdatePolicy().
1515 AutoAdvancingVirtualTimeDomain* time_domain = GetVirtualTimeDomain(); 1519 AutoAdvancingVirtualTimeDomain* time_domain = GetVirtualTimeDomain();
1516 for (const scoped_refptr<TaskQueue>& task_queue : unthrottled_task_runners_) 1520 for (const scoped_refptr<TaskQueue>& task_queue : unthrottled_task_runners_)
1517 task_queue->SetTimeDomain(time_domain); 1521 task_queue->SetTimeDomain(time_domain);
1518 1522
1519 throttling_helper_->EnableVirtualTime(); 1523 task_queue_throttler_->EnableVirtualTime();
1520 1524
1521 ForceUpdatePolicy(); 1525 ForceUpdatePolicy();
1522 } 1526 }
1523 1527
1524 // static 1528 // static
1525 const char* RendererSchedulerImpl::UseCaseToString(UseCase use_case) { 1529 const char* RendererSchedulerImpl::UseCaseToString(UseCase use_case) {
1526 switch (use_case) { 1530 switch (use_case) {
1527 case UseCase::NONE: 1531 case UseCase::NONE:
1528 return "none"; 1532 return "none";
1529 case UseCase::COMPOSITOR_GESTURE: 1533 case UseCase::COMPOSITOR_GESTURE:
(...skipping 26 matching lines...) Expand all
1556 case v8::PERFORMANCE_LOAD: 1560 case v8::PERFORMANCE_LOAD:
1557 return "load"; 1561 return "load";
1558 default: 1562 default:
1559 NOTREACHED(); 1563 NOTREACHED();
1560 return nullptr; 1564 return nullptr;
1561 } 1565 }
1562 } 1566 }
1563 1567
1564 } // namespace scheduler 1568 } // namespace scheduler
1565 } // namespace blink 1569 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698