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

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

Issue 2383473002: [scheduler] Teach scheduler about audio state (Closed)
Patch Set: Created 4 years, 2 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/task_queue_throttler.h" 5 #include "platform/scheduler/renderer/task_queue_throttler.h"
6 6
7 #include <cstdint> 7 #include <cstdint>
8 8
9 #include "base/format_macros.h" 9 #include "base/format_macros.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 return; 134 return;
135 is_enabled_ = false; 135 is_enabled_ = false;
136 136
137 for (TaskQueue* queue : associated_task_queues_) { 137 for (TaskQueue* queue : associated_task_queues_) {
138 if (!task_queue_throttler_->IsThrottled(queue)) 138 if (!task_queue_throttler_->IsThrottled(queue))
139 continue; 139 continue;
140 140
141 task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, lazy_now->Now(), 141 task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, lazy_now->Now(),
142 queue, base::nullopt); 142 queue, base::nullopt);
143 } 143 }
144
145 // TODO(altimin): We need to disable TimeBudgetQueues here or they will
146 // regenerate extra time budget when they are disabled.
144 } 147 }
145 148
146 bool TaskQueueThrottler::TimeBudgetPool::IsThrottlingEnabled() const { 149 bool TaskQueueThrottler::TimeBudgetPool::IsThrottlingEnabled() const {
147 return is_enabled_; 150 return is_enabled_;
148 } 151 }
149 152
150 void TaskQueueThrottler::TimeBudgetPool::Close() { 153 void TaskQueueThrottler::TimeBudgetPool::Close() {
151 DCHECK_EQ(0u, associated_task_queues_.size()); 154 DCHECK_EQ(0u, associated_task_queues_.size());
152 155
153 task_queue_throttler_->time_budget_pools_.erase(this); 156 task_queue_throttler_->time_budget_pools_.erase(this);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 } 227 }
225 228
226 TaskQueueThrottler::TaskQueueThrottler( 229 TaskQueueThrottler::TaskQueueThrottler(
227 RendererSchedulerImpl* renderer_scheduler, 230 RendererSchedulerImpl* renderer_scheduler,
228 const char* tracing_category) 231 const char* tracing_category)
229 : task_runner_(renderer_scheduler->ControlTaskRunner()), 232 : task_runner_(renderer_scheduler->ControlTaskRunner()),
230 renderer_scheduler_(renderer_scheduler), 233 renderer_scheduler_(renderer_scheduler),
231 tick_clock_(renderer_scheduler->tick_clock()), 234 tick_clock_(renderer_scheduler->tick_clock()),
232 tracing_category_(tracing_category), 235 tracing_category_(tracing_category),
233 time_domain_(new ThrottledTimeDomain(this, tracing_category)), 236 time_domain_(new ThrottledTimeDomain(this, tracing_category)),
237 is_throttling_disabled_(false),
234 virtual_time_(false), 238 virtual_time_(false),
239 is_audio_active_(false),
235 weak_factory_(this) { 240 weak_factory_(this) {
236 pump_throttled_tasks_closure_.Reset(base::Bind( 241 pump_throttled_tasks_closure_.Reset(base::Bind(
237 &TaskQueueThrottler::PumpThrottledTasks, weak_factory_.GetWeakPtr())); 242 &TaskQueueThrottler::PumpThrottledTasks, weak_factory_.GetWeakPtr()));
238 forward_immediate_work_callback_ = 243 forward_immediate_work_callback_ =
239 base::Bind(&TaskQueueThrottler::OnTimeDomainHasImmediateWork, 244 base::Bind(&TaskQueueThrottler::OnTimeDomainHasImmediateWork,
240 weak_factory_.GetWeakPtr()); 245 weak_factory_.GetWeakPtr());
241 246
242 renderer_scheduler_->RegisterTimeDomain(time_domain_.get()); 247 renderer_scheduler_->RegisterTimeDomain(time_domain_.get());
243 } 248 }
244 249
(...skipping 30 matching lines...) Expand all
275 if (!enabled) { 280 if (!enabled) {
276 task_queue->SetQueueEnabled(false); 281 task_queue->SetQueueEnabled(false);
277 MaybeSchedulePumpQueue(FROM_HERE, tick_clock_->NowTicks(), task_queue, 282 MaybeSchedulePumpQueue(FROM_HERE, tick_clock_->NowTicks(), task_queue,
278 base::nullopt); 283 base::nullopt);
279 } 284 }
280 } 285 }
281 286
282 void TaskQueueThrottler::IncreaseThrottleRefCount(TaskQueue* task_queue) { 287 void TaskQueueThrottler::IncreaseThrottleRefCount(TaskQueue* task_queue) {
283 DCHECK_NE(task_queue, task_runner_.get()); 288 DCHECK_NE(task_queue, task_runner_.get());
284 289
285 if (virtual_time_)
286 return;
287
288 std::pair<TaskQueueMap::iterator, bool> insert_result = 290 std::pair<TaskQueueMap::iterator, bool> insert_result =
289 queue_details_.insert(std::make_pair(task_queue, Metadata())); 291 queue_details_.insert(std::make_pair(task_queue, Metadata()));
290 292
291 if (!insert_result.first->second.IsThrottled()) { 293 if (!insert_result.first->second.IsThrottled()) {
292 // The insert was successful so we need to throttle the queue. 294 // The insert was successful so we need to throttle the queue.
293 insert_result.first->second.enabled = task_queue->IsQueueEnabled(); 295 insert_result.first->second.enabled = task_queue->IsQueueEnabled();
294 296
295 task_queue->SetTimeDomain(time_domain_.get()); 297 if (!is_throttling_disabled_) {
296 task_queue->RemoveFence(); 298 task_queue->SetTimeDomain(time_domain_.get());
297 task_queue->SetQueueEnabled(false); 299 task_queue->RemoveFence();
300 task_queue->SetQueueEnabled(false);
298 301
299 if (!task_queue->IsEmpty()) { 302 if (!task_queue->IsEmpty()) {
300 if (task_queue->HasPendingImmediateWork()) { 303 if (task_queue->HasPendingImmediateWork()) {
301 OnTimeDomainHasImmediateWork(task_queue); 304 OnTimeDomainHasImmediateWork(task_queue);
302 } else { 305 } else {
303 OnTimeDomainHasDelayedWork(task_queue); 306 OnTimeDomainHasDelayedWork(task_queue);
307 }
304 } 308 }
305 } 309 }
306 310
307 TRACE_EVENT1(tracing_category_, "TaskQueueThrottler_TaskQueueThrottled", 311 TRACE_EVENT1(tracing_category_, "TaskQueueThrottler_TaskQueueThrottled",
308 "task_queue", task_queue); 312 "task_queue", task_queue);
309 } 313 }
310 314
311 insert_result.first->second.throttling_ref_count++; 315 insert_result.first->second.throttling_ref_count++;
312 } 316 }
313 317
314 void TaskQueueThrottler::DecreaseThrottleRefCount(TaskQueue* task_queue) { 318 void TaskQueueThrottler::DecreaseThrottleRefCount(TaskQueue* task_queue) {
315 if (virtual_time_)
316 return;
317
318 TaskQueueMap::iterator iter = queue_details_.find(task_queue); 319 TaskQueueMap::iterator iter = queue_details_.find(task_queue);
319 320
320 if (iter != queue_details_.end() && 321 if (iter != queue_details_.end() &&
321 --iter->second.throttling_ref_count == 0) { 322 --iter->second.throttling_ref_count == 0) {
322 bool enabled = iter->second.enabled; 323 bool enabled = iter->second.enabled;
323 324
324 MaybeDeleteQueueMetadata(iter); 325 MaybeDeleteQueueMetadata(iter);
325 326
326 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain()); 327 if (!is_throttling_disabled_) {
327 task_queue->RemoveFence(); 328 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain());
328 task_queue->SetQueueEnabled(enabled); 329 task_queue->RemoveFence();
330 task_queue->SetQueueEnabled(enabled);
331 }
329 332
330 TRACE_EVENT1(tracing_category_, "TaskQueueThrottler_TaskQueueUntrottled", 333 TRACE_EVENT1(tracing_category_, "TaskQueueThrottler_TaskQueueUntrottled",
331 "task_queue", task_queue); 334 "task_queue", task_queue);
332 } 335 }
333 } 336 }
334 337
335 bool TaskQueueThrottler::IsThrottled(TaskQueue* task_queue) const { 338 bool TaskQueueThrottler::IsThrottled(TaskQueue* task_queue) const {
336 auto find_it = queue_details_.find(task_queue); 339 auto find_it = queue_details_.find(task_queue);
337 if (find_it == queue_details_.end()) 340 if (find_it == queue_details_.end())
338 return false; 341 return false;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 base::TimeTicks unthrottled_runtime) { 442 base::TimeTicks unthrottled_runtime) {
440 const base::TimeDelta one_second = base::TimeDelta::FromSeconds(1); 443 const base::TimeDelta one_second = base::TimeDelta::FromSeconds(1);
441 return unthrottled_runtime + one_second - 444 return unthrottled_runtime + one_second -
442 ((unthrottled_runtime - base::TimeTicks()) % one_second); 445 ((unthrottled_runtime - base::TimeTicks()) % one_second);
443 } 446 }
444 447
445 void TaskQueueThrottler::MaybeSchedulePumpThrottledTasks( 448 void TaskQueueThrottler::MaybeSchedulePumpThrottledTasks(
446 const tracked_objects::Location& from_here, 449 const tracked_objects::Location& from_here,
447 base::TimeTicks now, 450 base::TimeTicks now,
448 base::TimeTicks unaligned_runtime) { 451 base::TimeTicks unaligned_runtime) {
449 if (virtual_time_) 452 if (is_throttling_disabled_)
450 return; 453 return;
451 454
452 base::TimeTicks runtime = 455 base::TimeTicks runtime =
453 std::max(now, AlignedThrottledRunTime(unaligned_runtime)); 456 std::max(now, AlignedThrottledRunTime(unaligned_runtime));
454 457
455 // If there is a pending call to PumpThrottledTasks and it's sooner than 458 // If there is a pending call to PumpThrottledTasks and it's sooner than
456 // |runtime| then return. 459 // |runtime| then return.
457 if (pending_pump_throttled_tasks_runtime_ && 460 if (pending_pump_throttled_tasks_runtime_ &&
458 runtime >= pending_pump_throttled_tasks_runtime_.value()) { 461 runtime >= pending_pump_throttled_tasks_runtime_.value()) {
459 return; 462 return;
460 } 463 }
461 464
462 pending_pump_throttled_tasks_runtime_ = runtime; 465 pending_pump_throttled_tasks_runtime_ = runtime;
463 466
464 pump_throttled_tasks_closure_.Cancel(); 467 pump_throttled_tasks_closure_.Cancel();
465 468
466 base::TimeDelta delay = pending_pump_throttled_tasks_runtime_.value() - now; 469 base::TimeDelta delay = pending_pump_throttled_tasks_runtime_.value() - now;
467 TRACE_EVENT1(tracing_category_, 470 TRACE_EVENT1(tracing_category_,
468 "TaskQueueThrottler::MaybeSchedulePumpThrottledTasks", 471 "TaskQueueThrottler::MaybeSchedulePumpThrottledTasks",
469 "delay_till_next_pump_ms", delay.InMilliseconds()); 472 "delay_till_next_pump_ms", delay.InMilliseconds());
470 task_runner_->PostDelayedTask( 473 task_runner_->PostDelayedTask(
471 from_here, pump_throttled_tasks_closure_.callback(), delay); 474 from_here, pump_throttled_tasks_closure_.callback(), delay);
472 } 475 }
473 476
474 void TaskQueueThrottler::EnableVirtualTime() { 477 void TaskQueueThrottler::EnableVirtualTime() {
475 virtual_time_ = true; 478 virtual_time_ = true;
479 UpdateGlobalThrottlingSetting();
480 }
476 481
477 pump_throttled_tasks_closure_.Cancel(); 482 void TaskQueueThrottler::SetIsAudioActive(bool is_audio_active) {
478 483 is_audio_active_ = is_audio_active;
479 for (auto it = queue_details_.begin(); it != queue_details_.end();) { 484 UpdateGlobalThrottlingSetting();
480 TaskQueue* task_queue = it->first;
481 bool enabled = it->second.enabled;
482
483 if (!it->second.time_budget_pool) {
484 it = queue_details_.erase(it);
485 } else {
486 // Fall back to default values.
487 it->second.throttling_ref_count = 0;
488 it->second.enabled = false;
489 it++;
490 }
491
492 task_queue->SetTimeDomain(renderer_scheduler_->GetVirtualTimeDomain());
493 task_queue->RemoveFence();
494 task_queue->SetQueueEnabled(enabled);
495 }
496 } 485 }
497 486
498 TaskQueueThrottler::TimeBudgetPool* TaskQueueThrottler::CreateTimeBudgetPool( 487 TaskQueueThrottler::TimeBudgetPool* TaskQueueThrottler::CreateTimeBudgetPool(
499 const char* name) { 488 const char* name) {
500 TimeBudgetPool* time_budget_pool = 489 TimeBudgetPool* time_budget_pool =
501 new TimeBudgetPool(name, this, tick_clock_->NowTicks()); 490 new TimeBudgetPool(name, this, tick_clock_->NowTicks());
502 time_budget_pools_[time_budget_pool] = base::WrapUnique(time_budget_pool); 491 time_budget_pools_[time_budget_pool] = base::WrapUnique(time_budget_pool);
503 return time_budget_pool; 492 return time_budget_pool;
504 } 493 }
505 494
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 if (!time_budget_pool) 553 if (!time_budget_pool)
565 return now; 554 return now;
566 return std::max(now, time_budget_pool->GetNextAllowedRunTime()); 555 return std::max(now, time_budget_pool->GetNextAllowedRunTime());
567 } 556 }
568 557
569 void TaskQueueThrottler::MaybeDeleteQueueMetadata(TaskQueueMap::iterator it) { 558 void TaskQueueThrottler::MaybeDeleteQueueMetadata(TaskQueueMap::iterator it) {
570 if (!it->second.IsThrottled() && !it->second.time_budget_pool) 559 if (!it->second.IsThrottled() && !it->second.time_budget_pool)
571 queue_details_.erase(it); 560 queue_details_.erase(it);
572 } 561 }
573 562
563 void TaskQueueThrottler::DisableThrottling() {
564 is_throttling_disabled_ = true;
565
566 for (const auto& map_entry : queue_details_) {
567 if (!map_entry.second.IsThrottled())
568 continue;
569
570 TaskQueue* queue = map_entry.first;
571
572 if (virtual_time_) {
573 queue->SetTimeDomain(renderer_scheduler_->GetVirtualTimeDomain());
574 } else {
575 queue->SetTimeDomain(renderer_scheduler_->real_time_domain());
576 }
577 queue->RemoveFence();
578 queue->SetQueueEnabled(map_entry.second.enabled);
579 }
580 }
581
582 void TaskQueueThrottler::EnableThrottling() {
583 is_throttling_disabled_ = false;
584
585 LazyNow lazy_now(tick_clock_);
586
587 for (const auto& map_entry : queue_details_) {
588 if (!map_entry.second.IsThrottled())
589 continue;
590
591 TaskQueue* queue = map_entry.first;
592
593 queue->SetQueueEnabled(false);
594 queue->SetTimeDomain(time_domain_.get());
595 MaybeSchedulePumpQueue(FROM_HERE, lazy_now.Now(), queue,
596 GetNextAllowedRunTime(lazy_now.Now(), queue));
597 }
598 }
599
600 void TaskQueueThrottler::UpdateGlobalThrottlingSetting() {
601 pump_throttled_tasks_closure_.Cancel();
602
603 bool should_disable_throttling = virtual_time_ || is_audio_active_;
604 if (should_disable_throttling == is_throttling_disabled_)
605 return;
606
607 if (should_disable_throttling) {
608 DisableThrottling();
609 } else {
610 EnableThrottling();
611 }
612 }
613
574 } // namespace scheduler 614 } // namespace scheduler
575 } // namespace blink 615 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698