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

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: WebFrames! 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"
11 #include "base/memory/ptr_util.h" 11 #include "base/memory/ptr_util.h"
12 #include "base/optional.h" 12 #include "base/optional.h"
13 #include "base/strings/stringprintf.h" 13 #include "base/strings/stringprintf.h"
14 #include "platform/scheduler/base/real_time_domain.h" 14 #include "platform/scheduler/base/real_time_domain.h"
15 #include "platform/scheduler/child/scheduler_tqm_delegate.h" 15 #include "platform/scheduler/child/scheduler_tqm_delegate.h"
16 #include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h"
17 #include "platform/scheduler/renderer/renderer_scheduler_impl.h" 16 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
18 #include "platform/scheduler/renderer/throttled_time_domain.h" 17 #include "platform/scheduler/renderer/throttled_time_domain.h"
19 #include "platform/scheduler/renderer/web_frame_scheduler_impl.h" 18 #include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
20 #include "public/platform/WebFrameScheduler.h" 19 #include "public/platform/WebFrameScheduler.h"
21 20
22 namespace blink { 21 namespace blink {
23 namespace scheduler { 22 namespace scheduler {
24 23
25 namespace { 24 namespace {
26 const int kMaxBudgetLevelInSeconds = 1; 25 const int kMaxBudgetLevelInSeconds = 1;
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 return; 133 return;
135 is_enabled_ = false; 134 is_enabled_ = false;
136 135
137 for (TaskQueue* queue : associated_task_queues_) { 136 for (TaskQueue* queue : associated_task_queues_) {
138 if (!task_queue_throttler_->IsThrottled(queue)) 137 if (!task_queue_throttler_->IsThrottled(queue))
139 continue; 138 continue;
140 139
141 task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, lazy_now->Now(), 140 task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, lazy_now->Now(),
142 queue, base::nullopt); 141 queue, base::nullopt);
143 } 142 }
143
144 // TODO(altimin): We need to disable TimeBudgetQueues here or they will
145 // regenerate extra time budget when they are disabled.
144 } 146 }
145 147
146 bool TaskQueueThrottler::TimeBudgetPool::IsThrottlingEnabled() const { 148 bool TaskQueueThrottler::TimeBudgetPool::IsThrottlingEnabled() const {
147 return is_enabled_; 149 return is_enabled_;
148 } 150 }
149 151
150 void TaskQueueThrottler::TimeBudgetPool::Close() { 152 void TaskQueueThrottler::TimeBudgetPool::Close() {
151 DCHECK_EQ(0u, associated_task_queues_.size()); 153 DCHECK_EQ(0u, associated_task_queues_.size());
152 154
153 task_queue_throttler_->time_budget_pools_.erase(this); 155 task_queue_throttler_->time_budget_pools_.erase(this);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 } 226 }
225 227
226 TaskQueueThrottler::TaskQueueThrottler( 228 TaskQueueThrottler::TaskQueueThrottler(
227 RendererSchedulerImpl* renderer_scheduler, 229 RendererSchedulerImpl* renderer_scheduler,
228 const char* tracing_category) 230 const char* tracing_category)
229 : task_runner_(renderer_scheduler->ControlTaskRunner()), 231 : task_runner_(renderer_scheduler->ControlTaskRunner()),
230 renderer_scheduler_(renderer_scheduler), 232 renderer_scheduler_(renderer_scheduler),
231 tick_clock_(renderer_scheduler->tick_clock()), 233 tick_clock_(renderer_scheduler->tick_clock()),
232 tracing_category_(tracing_category), 234 tracing_category_(tracing_category),
233 time_domain_(new ThrottledTimeDomain(this, tracing_category)), 235 time_domain_(new ThrottledTimeDomain(this, tracing_category)),
234 virtual_time_(false), 236 allow_throttling_(true),
235 weak_factory_(this) { 237 weak_factory_(this) {
236 pump_throttled_tasks_closure_.Reset(base::Bind( 238 pump_throttled_tasks_closure_.Reset(base::Bind(
237 &TaskQueueThrottler::PumpThrottledTasks, weak_factory_.GetWeakPtr())); 239 &TaskQueueThrottler::PumpThrottledTasks, weak_factory_.GetWeakPtr()));
238 forward_immediate_work_callback_ = 240 forward_immediate_work_callback_ =
239 base::Bind(&TaskQueueThrottler::OnTimeDomainHasImmediateWork, 241 base::Bind(&TaskQueueThrottler::OnTimeDomainHasImmediateWork,
240 weak_factory_.GetWeakPtr()); 242 weak_factory_.GetWeakPtr());
241 243
242 renderer_scheduler_->RegisterTimeDomain(time_domain_.get()); 244 renderer_scheduler_->RegisterTimeDomain(time_domain_.get());
243 } 245 }
244 246
(...skipping 30 matching lines...) Expand all
275 if (!enabled) { 277 if (!enabled) {
276 task_queue->SetQueueEnabled(false); 278 task_queue->SetQueueEnabled(false);
277 MaybeSchedulePumpQueue(FROM_HERE, tick_clock_->NowTicks(), task_queue, 279 MaybeSchedulePumpQueue(FROM_HERE, tick_clock_->NowTicks(), task_queue,
278 base::nullopt); 280 base::nullopt);
279 } 281 }
280 } 282 }
281 283
282 void TaskQueueThrottler::IncreaseThrottleRefCount(TaskQueue* task_queue) { 284 void TaskQueueThrottler::IncreaseThrottleRefCount(TaskQueue* task_queue) {
283 DCHECK_NE(task_queue, task_runner_.get()); 285 DCHECK_NE(task_queue, task_runner_.get());
284 286
285 if (virtual_time_)
286 return;
287
288 std::pair<TaskQueueMap::iterator, bool> insert_result = 287 std::pair<TaskQueueMap::iterator, bool> insert_result =
289 queue_details_.insert(std::make_pair(task_queue, Metadata())); 288 queue_details_.insert(std::make_pair(task_queue, Metadata()));
290 289
291 if (!insert_result.first->second.IsThrottled()) { 290 if (!insert_result.first->second.IsThrottled()) {
292 // The insert was successful so we need to throttle the queue. 291 // The insert was successful so we need to throttle the queue.
293 insert_result.first->second.enabled = task_queue->IsQueueEnabled(); 292 insert_result.first->second.enabled = task_queue->IsQueueEnabled();
294 293
295 task_queue->SetTimeDomain(time_domain_.get()); 294 if (allow_throttling_) {
296 task_queue->RemoveFence(); 295 task_queue->SetTimeDomain(time_domain_.get());
297 task_queue->SetQueueEnabled(false); 296 task_queue->RemoveFence();
297 task_queue->SetQueueEnabled(false);
298 298
299 if (!task_queue->IsEmpty()) { 299 if (!task_queue->IsEmpty()) {
300 if (task_queue->HasPendingImmediateWork()) { 300 if (task_queue->HasPendingImmediateWork()) {
301 OnTimeDomainHasImmediateWork(task_queue); 301 OnTimeDomainHasImmediateWork(task_queue);
302 } else { 302 } else {
303 OnTimeDomainHasDelayedWork(task_queue); 303 OnTimeDomainHasDelayedWork(task_queue);
304 }
304 } 305 }
305 } 306 }
306 307
307 TRACE_EVENT1(tracing_category_, "TaskQueueThrottler_TaskQueueThrottled", 308 TRACE_EVENT1(tracing_category_, "TaskQueueThrottler_TaskQueueThrottled",
308 "task_queue", task_queue); 309 "task_queue", task_queue);
309 } 310 }
310 311
311 insert_result.first->second.throttling_ref_count++; 312 insert_result.first->second.throttling_ref_count++;
312 } 313 }
313 314
314 void TaskQueueThrottler::DecreaseThrottleRefCount(TaskQueue* task_queue) { 315 void TaskQueueThrottler::DecreaseThrottleRefCount(TaskQueue* task_queue) {
315 if (virtual_time_)
316 return;
317
318 TaskQueueMap::iterator iter = queue_details_.find(task_queue); 316 TaskQueueMap::iterator iter = queue_details_.find(task_queue);
319 317
320 if (iter != queue_details_.end() && 318 if (iter != queue_details_.end() &&
321 --iter->second.throttling_ref_count == 0) { 319 --iter->second.throttling_ref_count == 0) {
322 bool enabled = iter->second.enabled; 320 bool enabled = iter->second.enabled;
323 321
324 MaybeDeleteQueueMetadata(iter); 322 MaybeDeleteQueueMetadata(iter);
325 323
326 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain()); 324 if (allow_throttling_) {
327 task_queue->RemoveFence(); 325 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain());
328 task_queue->SetQueueEnabled(enabled); 326 task_queue->RemoveFence();
327 task_queue->SetQueueEnabled(enabled);
328 }
329 329
330 TRACE_EVENT1(tracing_category_, "TaskQueueThrottler_TaskQueueUntrottled", 330 TRACE_EVENT1(tracing_category_, "TaskQueueThrottler_TaskQueueUntrottled",
331 "task_queue", task_queue); 331 "task_queue", task_queue);
332 } 332 }
333 } 333 }
334 334
335 bool TaskQueueThrottler::IsThrottled(TaskQueue* task_queue) const { 335 bool TaskQueueThrottler::IsThrottled(TaskQueue* task_queue) const {
336 auto find_it = queue_details_.find(task_queue); 336 auto find_it = queue_details_.find(task_queue);
337 if (find_it == queue_details_.end()) 337 if (find_it == queue_details_.end())
338 return false; 338 return false;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 base::TimeTicks unthrottled_runtime) { 439 base::TimeTicks unthrottled_runtime) {
440 const base::TimeDelta one_second = base::TimeDelta::FromSeconds(1); 440 const base::TimeDelta one_second = base::TimeDelta::FromSeconds(1);
441 return unthrottled_runtime + one_second - 441 return unthrottled_runtime + one_second -
442 ((unthrottled_runtime - base::TimeTicks()) % one_second); 442 ((unthrottled_runtime - base::TimeTicks()) % one_second);
443 } 443 }
444 444
445 void TaskQueueThrottler::MaybeSchedulePumpThrottledTasks( 445 void TaskQueueThrottler::MaybeSchedulePumpThrottledTasks(
446 const tracked_objects::Location& from_here, 446 const tracked_objects::Location& from_here,
447 base::TimeTicks now, 447 base::TimeTicks now,
448 base::TimeTicks unaligned_runtime) { 448 base::TimeTicks unaligned_runtime) {
449 if (virtual_time_) 449 if (!allow_throttling_)
450 return; 450 return;
451 451
452 base::TimeTicks runtime = 452 base::TimeTicks runtime =
453 std::max(now, AlignedThrottledRunTime(unaligned_runtime)); 453 std::max(now, AlignedThrottledRunTime(unaligned_runtime));
454 454
455 // If there is a pending call to PumpThrottledTasks and it's sooner than 455 // If there is a pending call to PumpThrottledTasks and it's sooner than
456 // |runtime| then return. 456 // |runtime| then return.
457 if (pending_pump_throttled_tasks_runtime_ && 457 if (pending_pump_throttled_tasks_runtime_ &&
458 runtime >= pending_pump_throttled_tasks_runtime_.value()) { 458 runtime >= pending_pump_throttled_tasks_runtime_.value()) {
459 return; 459 return;
460 } 460 }
461 461
462 pending_pump_throttled_tasks_runtime_ = runtime; 462 pending_pump_throttled_tasks_runtime_ = runtime;
463 463
464 pump_throttled_tasks_closure_.Cancel(); 464 pump_throttled_tasks_closure_.Cancel();
465 465
466 base::TimeDelta delay = pending_pump_throttled_tasks_runtime_.value() - now; 466 base::TimeDelta delay = pending_pump_throttled_tasks_runtime_.value() - now;
467 TRACE_EVENT1(tracing_category_, 467 TRACE_EVENT1(tracing_category_,
468 "TaskQueueThrottler::MaybeSchedulePumpThrottledTasks", 468 "TaskQueueThrottler::MaybeSchedulePumpThrottledTasks",
469 "delay_till_next_pump_ms", delay.InMilliseconds()); 469 "delay_till_next_pump_ms", delay.InMilliseconds());
470 task_runner_->PostDelayedTask( 470 task_runner_->PostDelayedTask(
471 from_here, pump_throttled_tasks_closure_.callback(), delay); 471 from_here, pump_throttled_tasks_closure_.callback(), delay);
472 } 472 }
473 473
474 void TaskQueueThrottler::EnableVirtualTime() {
475 virtual_time_ = true;
476
477 pump_throttled_tasks_closure_.Cancel();
478
479 for (auto it = queue_details_.begin(); it != queue_details_.end();) {
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 }
497
498 TaskQueueThrottler::TimeBudgetPool* TaskQueueThrottler::CreateTimeBudgetPool( 474 TaskQueueThrottler::TimeBudgetPool* TaskQueueThrottler::CreateTimeBudgetPool(
499 const char* name) { 475 const char* name) {
500 TimeBudgetPool* time_budget_pool = 476 TimeBudgetPool* time_budget_pool =
501 new TimeBudgetPool(name, this, tick_clock_->NowTicks()); 477 new TimeBudgetPool(name, this, tick_clock_->NowTicks());
502 time_budget_pools_[time_budget_pool] = base::WrapUnique(time_budget_pool); 478 time_budget_pools_[time_budget_pool] = base::WrapUnique(time_budget_pool);
503 return time_budget_pool; 479 return time_budget_pool;
504 } 480 }
505 481
506 void TaskQueueThrottler::OnTaskRunTimeReported(TaskQueue* task_queue, 482 void TaskQueueThrottler::OnTaskRunTimeReported(TaskQueue* task_queue,
507 base::TimeTicks start_time, 483 base::TimeTicks start_time,
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 if (!time_budget_pool) 540 if (!time_budget_pool)
565 return now; 541 return now;
566 return std::max(now, time_budget_pool->GetNextAllowedRunTime()); 542 return std::max(now, time_budget_pool->GetNextAllowedRunTime());
567 } 543 }
568 544
569 void TaskQueueThrottler::MaybeDeleteQueueMetadata(TaskQueueMap::iterator it) { 545 void TaskQueueThrottler::MaybeDeleteQueueMetadata(TaskQueueMap::iterator it) {
570 if (!it->second.IsThrottled() && !it->second.time_budget_pool) 546 if (!it->second.IsThrottled() && !it->second.time_budget_pool)
571 queue_details_.erase(it); 547 queue_details_.erase(it);
572 } 548 }
573 549
550 void TaskQueueThrottler::DisableThrottling() {
551 if (!allow_throttling_)
552 return;
553
554 allow_throttling_ = false;
555
556 for (const auto& map_entry : queue_details_) {
557 if (!map_entry.second.IsThrottled())
558 continue;
559
560 TaskQueue* queue = map_entry.first;
561
562 queue->SetTimeDomain(renderer_scheduler_->GetActiveTimeDomain());
563
564 queue->RemoveFence();
565 queue->SetQueueEnabled(map_entry.second.enabled);
566 }
567 }
568
569 void TaskQueueThrottler::EnableThrottling() {
570 if (allow_throttling_)
571 return;
572
573 allow_throttling_ = true;
574
575 LazyNow lazy_now(tick_clock_);
576
577 for (const auto& map_entry : queue_details_) {
578 if (!map_entry.second.IsThrottled())
579 continue;
580
581 TaskQueue* queue = map_entry.first;
582
583 queue->SetQueueEnabled(false);
584 queue->SetTimeDomain(time_domain_.get());
585 MaybeSchedulePumpQueue(FROM_HERE, lazy_now.Now(), queue,
586 GetNextAllowedRunTime(lazy_now.Now(), queue));
587 }
588 }
589
574 } // namespace scheduler 590 } // namespace scheduler
575 } // namespace blink 591 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698