| OLD | NEW |
| 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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 | 56 |
| 57 template <class T> | 57 template <class T> |
| 58 base::Optional<T> Max(const base::Optional<T>& a, const base::Optional<T>& b) { | 58 base::Optional<T> Max(const base::Optional<T>& a, const base::Optional<T>& b) { |
| 59 if (!b) | 59 if (!b) |
| 60 return a; | 60 return a; |
| 61 if (!a) | 61 if (!a) |
| 62 return b; | 62 return b; |
| 63 return std::max(a.value(), b.value()); | 63 return std::max(a.value(), b.value()); |
| 64 } | 64 } |
| 65 | 65 |
| 66 std::string PointerToId(void* pointer) { |
| 67 return base::StringPrintf( |
| 68 "%" PRIx64, static_cast<uint64_t>(reinterpret_cast<uintptr_t>(pointer))); |
| 69 } |
| 70 |
| 66 } // namespace | 71 } // namespace |
| 67 | 72 |
| 68 TaskQueueThrottler::TimeBudgetPool::TimeBudgetPool( | 73 TaskQueueThrottler::TimeBudgetPool::TimeBudgetPool( |
| 69 const char* name, | 74 const char* name, |
| 70 TaskQueueThrottler* task_queue_throttler, | 75 TaskQueueThrottler* task_queue_throttler, |
| 71 base::TimeTicks now, | 76 base::TimeTicks now, |
| 72 base::Optional<base::TimeDelta> max_budget_level, | 77 base::Optional<base::TimeDelta> max_budget_level, |
| 73 base::Optional<base::TimeDelta> max_throttling_duration) | 78 base::Optional<base::TimeDelta> max_throttling_duration) |
| 74 : name_(name), | 79 : name_(name), |
| 75 task_queue_throttler_(task_queue_throttler), | 80 task_queue_throttler_(task_queue_throttler), |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 | 130 |
| 126 task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, now, queue, | 131 task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, now, queue, |
| 127 base::nullopt); | 132 base::nullopt); |
| 128 } | 133 } |
| 129 | 134 |
| 130 void TaskQueueThrottler::TimeBudgetPool::EnableThrottling(LazyNow* lazy_now) { | 135 void TaskQueueThrottler::TimeBudgetPool::EnableThrottling(LazyNow* lazy_now) { |
| 131 if (is_enabled_) | 136 if (is_enabled_) |
| 132 return; | 137 return; |
| 133 is_enabled_ = true; | 138 is_enabled_ = true; |
| 134 | 139 |
| 140 TRACE_EVENT0(task_queue_throttler_->tracing_category_, |
| 141 "TaskQueueThrottler_TimeBudgetPool_EnableThrottling"); |
| 142 |
| 135 BlockThrottledQueues(lazy_now->Now()); | 143 BlockThrottledQueues(lazy_now->Now()); |
| 136 } | 144 } |
| 137 | 145 |
| 138 void TaskQueueThrottler::TimeBudgetPool::DisableThrottling(LazyNow* lazy_now) { | 146 void TaskQueueThrottler::TimeBudgetPool::DisableThrottling(LazyNow* lazy_now) { |
| 139 if (!is_enabled_) | 147 if (!is_enabled_) |
| 140 return; | 148 return; |
| 141 is_enabled_ = false; | 149 is_enabled_ = false; |
| 142 | 150 |
| 151 TRACE_EVENT0(task_queue_throttler_->tracing_category_, |
| 152 "TaskQueueThrottler_TimeBudgetPool_DisableThrottling"); |
| 153 |
| 143 for (TaskQueue* queue : associated_task_queues_) { | 154 for (TaskQueue* queue : associated_task_queues_) { |
| 144 if (!task_queue_throttler_->IsThrottled(queue)) | 155 if (!task_queue_throttler_->IsThrottled(queue)) |
| 145 continue; | 156 continue; |
| 146 | 157 |
| 147 task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, lazy_now->Now(), | 158 task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, lazy_now->Now(), |
| 148 queue, base::nullopt); | 159 queue, base::nullopt); |
| 149 } | 160 } |
| 150 | 161 |
| 151 // TODO(altimin): We need to disable TimeBudgetQueues here or they will | 162 // TODO(altimin): We need to disable TimeBudgetQueues here or they will |
| 152 // regenerate extra time budget when they are disabled. | 163 // regenerate extra time budget when they are disabled. |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 state->SetString("name", name_); | 230 state->SetString("name", name_); |
| 220 state->SetDouble("time_budget", cpu_percentage_); | 231 state->SetDouble("time_budget", cpu_percentage_); |
| 221 state->SetDouble("time_budget_level_in_seconds", | 232 state->SetDouble("time_budget_level_in_seconds", |
| 222 current_budget_level_.InSecondsF()); | 233 current_budget_level_.InSecondsF()); |
| 223 state->SetDouble("last_checkpoint_seconds_ago", | 234 state->SetDouble("last_checkpoint_seconds_ago", |
| 224 (now - last_checkpoint_).InSecondsF()); | 235 (now - last_checkpoint_).InSecondsF()); |
| 225 state->SetBoolean("is_enabled", is_enabled_); | 236 state->SetBoolean("is_enabled", is_enabled_); |
| 226 | 237 |
| 227 state->BeginArray("task_queues"); | 238 state->BeginArray("task_queues"); |
| 228 for (TaskQueue* queue : associated_task_queues_) { | 239 for (TaskQueue* queue : associated_task_queues_) { |
| 229 state->AppendString(base::StringPrintf( | 240 state->AppendString(PointerToId(queue)); |
| 230 "%" PRIx64, static_cast<uint64_t>(reinterpret_cast<uintptr_t>(queue)))); | |
| 231 } | 241 } |
| 232 state->EndArray(); | 242 state->EndArray(); |
| 233 | 243 |
| 234 state->EndDictionary(); | 244 state->EndDictionary(); |
| 235 } | 245 } |
| 236 | 246 |
| 237 void TaskQueueThrottler::TimeBudgetPool::Advance(base::TimeTicks now) { | 247 void TaskQueueThrottler::TimeBudgetPool::Advance(base::TimeTicks now) { |
| 238 if (now > last_checkpoint_) { | 248 if (now > last_checkpoint_) { |
| 239 if (is_enabled_) { | 249 if (is_enabled_) { |
| 240 current_budget_level_ += cpu_percentage_ * (now - last_checkpoint_); | 250 current_budget_level_ += cpu_percentage_ * (now - last_checkpoint_); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 bool enabled = iter->second.enabled; | 378 bool enabled = iter->second.enabled; |
| 369 | 379 |
| 370 MaybeDeleteQueueMetadata(iter); | 380 MaybeDeleteQueueMetadata(iter); |
| 371 | 381 |
| 372 if (allow_throttling_) { | 382 if (allow_throttling_) { |
| 373 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain()); | 383 task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain()); |
| 374 task_queue->RemoveFence(); | 384 task_queue->RemoveFence(); |
| 375 task_queue->SetQueueEnabled(enabled); | 385 task_queue->SetQueueEnabled(enabled); |
| 376 } | 386 } |
| 377 | 387 |
| 378 TRACE_EVENT1(tracing_category_, "TaskQueueThrottler_TaskQueueUntrottled", | 388 TRACE_EVENT1(tracing_category_, "TaskQueueThrottler_TaskQueueUnthrottled", |
| 379 "task_queue", task_queue); | 389 "task_queue", task_queue); |
| 380 } | 390 } |
| 381 } | 391 } |
| 382 | 392 |
| 383 bool TaskQueueThrottler::IsThrottled(TaskQueue* task_queue) const { | 393 bool TaskQueueThrottler::IsThrottled(TaskQueue* task_queue) const { |
| 384 auto find_it = queue_details_.find(task_queue); | 394 auto find_it = queue_details_.find(task_queue); |
| 385 if (find_it == queue_details_.end()) | 395 if (find_it == queue_details_.end()) |
| 386 return false; | 396 return false; |
| 387 return find_it->second.IsThrottled(); | 397 return find_it->second.IsThrottled(); |
| 388 } | 398 } |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 } | 556 } |
| 547 | 557 |
| 548 void TaskQueueThrottler::AsValueInto(base::trace_event::TracedValue* state, | 558 void TaskQueueThrottler::AsValueInto(base::trace_event::TracedValue* state, |
| 549 base::TimeTicks now) const { | 559 base::TimeTicks now) const { |
| 550 if (pending_pump_throttled_tasks_runtime_) { | 560 if (pending_pump_throttled_tasks_runtime_) { |
| 551 state->SetDouble( | 561 state->SetDouble( |
| 552 "next_throttled_tasks_pump_in_seconds", | 562 "next_throttled_tasks_pump_in_seconds", |
| 553 (pending_pump_throttled_tasks_runtime_.value() - now).InSecondsF()); | 563 (pending_pump_throttled_tasks_runtime_.value() - now).InSecondsF()); |
| 554 } | 564 } |
| 555 | 565 |
| 566 state->SetBoolean("allow_throttling", allow_throttling_); |
| 567 |
| 556 state->BeginDictionary("time_budget_pools"); | 568 state->BeginDictionary("time_budget_pools"); |
| 557 | |
| 558 for (const auto& map_entry : time_budget_pools_) { | 569 for (const auto& map_entry : time_budget_pools_) { |
| 559 TaskQueueThrottler::TimeBudgetPool* pool = map_entry.first; | 570 TaskQueueThrottler::TimeBudgetPool* pool = map_entry.first; |
| 560 pool->AsValueInto(state, now); | 571 pool->AsValueInto(state, now); |
| 561 } | 572 } |
| 573 state->EndDictionary(); |
| 562 | 574 |
| 575 state->BeginDictionary("queue_details"); |
| 576 for (const auto& map_entry : queue_details_) { |
| 577 state->BeginDictionaryWithCopiedName(PointerToId(map_entry.first)); |
| 578 |
| 579 state->SetInteger("throttling_ref_count", |
| 580 map_entry.second.throttling_ref_count); |
| 581 state->SetBoolean("enabled", map_entry.second.enabled); |
| 582 |
| 583 state->EndDictionary(); |
| 584 } |
| 563 state->EndDictionary(); | 585 state->EndDictionary(); |
| 564 } | 586 } |
| 565 | 587 |
| 566 TaskQueueThrottler::TimeBudgetPool* | 588 TaskQueueThrottler::TimeBudgetPool* |
| 567 TaskQueueThrottler::GetTimeBudgetPoolForQueue(TaskQueue* queue) { | 589 TaskQueueThrottler::GetTimeBudgetPoolForQueue(TaskQueue* queue) { |
| 568 auto find_it = queue_details_.find(queue); | 590 auto find_it = queue_details_.find(queue); |
| 569 if (find_it == queue_details_.end()) | 591 if (find_it == queue_details_.end()) |
| 570 return nullptr; | 592 return nullptr; |
| 571 return find_it->second.time_budget_pool; | 593 return find_it->second.time_budget_pool; |
| 572 } | 594 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 611 TaskQueue* queue = map_entry.first; | 633 TaskQueue* queue = map_entry.first; |
| 612 | 634 |
| 613 queue->SetTimeDomain(renderer_scheduler_->GetActiveTimeDomain()); | 635 queue->SetTimeDomain(renderer_scheduler_->GetActiveTimeDomain()); |
| 614 | 636 |
| 615 queue->RemoveFence(); | 637 queue->RemoveFence(); |
| 616 queue->SetQueueEnabled(map_entry.second.enabled); | 638 queue->SetQueueEnabled(map_entry.second.enabled); |
| 617 } | 639 } |
| 618 | 640 |
| 619 pump_throttled_tasks_closure_.Cancel(); | 641 pump_throttled_tasks_closure_.Cancel(); |
| 620 pending_pump_throttled_tasks_runtime_ = base::nullopt; | 642 pending_pump_throttled_tasks_runtime_ = base::nullopt; |
| 643 |
| 644 TRACE_EVENT0(tracing_category_, "TaskQueueThrottler_DisableThrottling"); |
| 621 } | 645 } |
| 622 | 646 |
| 623 void TaskQueueThrottler::EnableThrottling() { | 647 void TaskQueueThrottler::EnableThrottling() { |
| 624 if (allow_throttling_) | 648 if (allow_throttling_) |
| 625 return; | 649 return; |
| 626 | 650 |
| 627 allow_throttling_ = true; | 651 allow_throttling_ = true; |
| 628 | 652 |
| 629 LazyNow lazy_now(tick_clock_); | 653 LazyNow lazy_now(tick_clock_); |
| 630 | 654 |
| 631 for (const auto& map_entry : queue_details_) { | 655 for (const auto& map_entry : queue_details_) { |
| 632 if (!map_entry.second.IsThrottled()) | 656 if (!map_entry.second.IsThrottled()) |
| 633 continue; | 657 continue; |
| 634 | 658 |
| 635 TaskQueue* queue = map_entry.first; | 659 TaskQueue* queue = map_entry.first; |
| 636 | 660 |
| 637 queue->SetQueueEnabled(false); | 661 queue->SetQueueEnabled(false); |
| 638 queue->SetTimeDomain(time_domain_.get()); | 662 queue->SetTimeDomain(time_domain_.get()); |
| 639 MaybeSchedulePumpQueue(FROM_HERE, lazy_now.Now(), queue, | 663 MaybeSchedulePumpQueue(FROM_HERE, lazy_now.Now(), queue, |
| 640 GetNextAllowedRunTime(lazy_now.Now(), queue)); | 664 GetNextAllowedRunTime(lazy_now.Now(), queue)); |
| 641 } | 665 } |
| 666 |
| 667 TRACE_EVENT0(tracing_category_, "TaskQueueThrottler_EnableThrottling"); |
| 642 } | 668 } |
| 643 | 669 |
| 644 } // namespace scheduler | 670 } // namespace scheduler |
| 645 } // namespace blink | 671 } // namespace blink |
| OLD | NEW |