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

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

Issue 2403363003: [Merge to 2883] Revert "[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"
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"
16 #include "platform/scheduler/renderer/renderer_scheduler_impl.h" 17 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
17 #include "platform/scheduler/renderer/throttled_time_domain.h" 18 #include "platform/scheduler/renderer/throttled_time_domain.h"
18 #include "platform/scheduler/renderer/web_frame_scheduler_impl.h" 19 #include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
19 #include "public/platform/WebFrameScheduler.h" 20 #include "public/platform/WebFrameScheduler.h"
20 21
21 namespace blink { 22 namespace blink {
22 namespace scheduler { 23 namespace scheduler {
23 24
24 namespace { 25 namespace {
25 const int kMaxBudgetLevelInSeconds = 1; 26 const int kMaxBudgetLevelInSeconds = 1;
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 return; 134 return;
134 is_enabled_ = false; 135 is_enabled_ = false;
135 136
136 for (TaskQueue* queue : associated_task_queues_) { 137 for (TaskQueue* queue : associated_task_queues_) {
137 if (!task_queue_throttler_->IsThrottled(queue)) 138 if (!task_queue_throttler_->IsThrottled(queue))
138 continue; 139 continue;
139 140
140 task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, lazy_now->Now(), 141 task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, lazy_now->Now(),
141 queue, base::nullopt); 142 queue, base::nullopt);
142 } 143 }
143
144 // TODO(altimin): We need to disable TimeBudgetQueues here or they will
145 // regenerate extra time budget when they are disabled.
146 } 144 }
147 145
148 bool TaskQueueThrottler::TimeBudgetPool::IsThrottlingEnabled() const { 146 bool TaskQueueThrottler::TimeBudgetPool::IsThrottlingEnabled() const {
149 return is_enabled_; 147 return is_enabled_;
150 } 148 }
151 149
152 void TaskQueueThrottler::TimeBudgetPool::Close() { 150 void TaskQueueThrottler::TimeBudgetPool::Close() {
153 DCHECK_EQ(0u, associated_task_queues_.size()); 151 DCHECK_EQ(0u, associated_task_queues_.size());
154 152
155 task_queue_throttler_->time_budget_pools_.erase(this); 153 task_queue_throttler_->time_budget_pools_.erase(this);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 } 224 }
227 225
228 TaskQueueThrottler::TaskQueueThrottler( 226 TaskQueueThrottler::TaskQueueThrottler(
229 RendererSchedulerImpl* renderer_scheduler, 227 RendererSchedulerImpl* renderer_scheduler,
230 const char* tracing_category) 228 const char* tracing_category)
231 : task_runner_(renderer_scheduler->ControlTaskRunner()), 229 : task_runner_(renderer_scheduler->ControlTaskRunner()),
232 renderer_scheduler_(renderer_scheduler), 230 renderer_scheduler_(renderer_scheduler),
233 tick_clock_(renderer_scheduler->tick_clock()), 231 tick_clock_(renderer_scheduler->tick_clock()),
234 tracing_category_(tracing_category), 232 tracing_category_(tracing_category),
235 time_domain_(new ThrottledTimeDomain(this, tracing_category)), 233 time_domain_(new ThrottledTimeDomain(this, tracing_category)),
236 allow_throttling_(true), 234 virtual_time_(false),
237 weak_factory_(this) { 235 weak_factory_(this) {
238 pump_throttled_tasks_closure_.Reset(base::Bind( 236 pump_throttled_tasks_closure_.Reset(base::Bind(
239 &TaskQueueThrottler::PumpThrottledTasks, weak_factory_.GetWeakPtr())); 237 &TaskQueueThrottler::PumpThrottledTasks, weak_factory_.GetWeakPtr()));
240 forward_immediate_work_callback_ = 238 forward_immediate_work_callback_ =
241 base::Bind(&TaskQueueThrottler::OnTimeDomainHasImmediateWork, 239 base::Bind(&TaskQueueThrottler::OnTimeDomainHasImmediateWork,
242 weak_factory_.GetWeakPtr()); 240 weak_factory_.GetWeakPtr());
243 241
244 renderer_scheduler_->RegisterTimeDomain(time_domain_.get()); 242 renderer_scheduler_->RegisterTimeDomain(time_domain_.get());
245 } 243 }
246 244
(...skipping 30 matching lines...) Expand all
277 if (!enabled) { 275 if (!enabled) {
278 task_queue->SetQueueEnabled(false); 276 task_queue->SetQueueEnabled(false);
279 MaybeSchedulePumpQueue(FROM_HERE, tick_clock_->NowTicks(), task_queue, 277 MaybeSchedulePumpQueue(FROM_HERE, tick_clock_->NowTicks(), task_queue,
280 base::nullopt); 278 base::nullopt);
281 } 279 }
282 } 280 }
283 281
284 void TaskQueueThrottler::IncreaseThrottleRefCount(TaskQueue* task_queue) { 282 void TaskQueueThrottler::IncreaseThrottleRefCount(TaskQueue* task_queue) {
285 DCHECK_NE(task_queue, task_runner_.get()); 283 DCHECK_NE(task_queue, task_runner_.get());
286 284
285 if (virtual_time_)
286 return;
287
287 std::pair<TaskQueueMap::iterator, bool> insert_result = 288 std::pair<TaskQueueMap::iterator, bool> insert_result =
288 queue_details_.insert(std::make_pair(task_queue, Metadata())); 289 queue_details_.insert(std::make_pair(task_queue, Metadata()));
289 290
290 if (!insert_result.first->second.IsThrottled()) { 291 if (!insert_result.first->second.IsThrottled()) {
291 // The insert was successful so we need to throttle the queue. 292 // The insert was successful so we need to throttle the queue.
292 insert_result.first->second.enabled = task_queue->IsQueueEnabled(); 293 insert_result.first->second.enabled = task_queue->IsQueueEnabled();
293 294
294 if (allow_throttling_) { 295 task_queue->SetTimeDomain(time_domain_.get());
295 task_queue->SetTimeDomain(time_domain_.get()); 296 task_queue->RemoveFence();
296 task_queue->RemoveFence(); 297 task_queue->SetQueueEnabled(false);
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 }
305 } 304 }
306 } 305 }
307 306
308 TRACE_EVENT1(tracing_category_, "TaskQueueThrottler_TaskQueueThrottled", 307 TRACE_EVENT1(tracing_category_, "TaskQueueThrottler_TaskQueueThrottled",
309 "task_queue", task_queue); 308 "task_queue", task_queue);
310 } 309 }
311 310
312 insert_result.first->second.throttling_ref_count++; 311 insert_result.first->second.throttling_ref_count++;
313 } 312 }
314 313
315 void TaskQueueThrottler::DecreaseThrottleRefCount(TaskQueue* task_queue) { 314 void TaskQueueThrottler::DecreaseThrottleRefCount(TaskQueue* task_queue) {
315 if (virtual_time_)
316 return;
317
316 TaskQueueMap::iterator iter = queue_details_.find(task_queue); 318 TaskQueueMap::iterator iter = queue_details_.find(task_queue);
317 319
318 if (iter != queue_details_.end() && 320 if (iter != queue_details_.end() &&
319 --iter->second.throttling_ref_count == 0) { 321 --iter->second.throttling_ref_count == 0) {
320 bool enabled = iter->second.enabled; 322 bool enabled = iter->second.enabled;
321 323
322 MaybeDeleteQueueMetadata(iter); 324 MaybeDeleteQueueMetadata(iter);
323 325
324 if (allow_throttling_) { 326 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain());
325 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain()); 327 task_queue->RemoveFence();
326 task_queue->RemoveFence(); 328 task_queue->SetQueueEnabled(enabled);
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 (!allow_throttling_) 449 if (virtual_time_)
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
474 TaskQueueThrottler::TimeBudgetPool* TaskQueueThrottler::CreateTimeBudgetPool( 498 TaskQueueThrottler::TimeBudgetPool* TaskQueueThrottler::CreateTimeBudgetPool(
475 const char* name) { 499 const char* name) {
476 TimeBudgetPool* time_budget_pool = 500 TimeBudgetPool* time_budget_pool =
477 new TimeBudgetPool(name, this, tick_clock_->NowTicks()); 501 new TimeBudgetPool(name, this, tick_clock_->NowTicks());
478 time_budget_pools_[time_budget_pool] = base::WrapUnique(time_budget_pool); 502 time_budget_pools_[time_budget_pool] = base::WrapUnique(time_budget_pool);
479 return time_budget_pool; 503 return time_budget_pool;
480 } 504 }
481 505
482 void TaskQueueThrottler::OnTaskRunTimeReported(TaskQueue* task_queue, 506 void TaskQueueThrottler::OnTaskRunTimeReported(TaskQueue* task_queue,
483 base::TimeTicks start_time, 507 base::TimeTicks start_time,
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 if (!time_budget_pool) 564 if (!time_budget_pool)
541 return now; 565 return now;
542 return std::max(now, time_budget_pool->GetNextAllowedRunTime()); 566 return std::max(now, time_budget_pool->GetNextAllowedRunTime());
543 } 567 }
544 568
545 void TaskQueueThrottler::MaybeDeleteQueueMetadata(TaskQueueMap::iterator it) { 569 void TaskQueueThrottler::MaybeDeleteQueueMetadata(TaskQueueMap::iterator it) {
546 if (!it->second.IsThrottled() && !it->second.time_budget_pool) 570 if (!it->second.IsThrottled() && !it->second.time_budget_pool)
547 queue_details_.erase(it); 571 queue_details_.erase(it);
548 } 572 }
549 573
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
590 } // namespace scheduler 574 } // namespace scheduler
591 } // namespace blink 575 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698