Chromium Code Reviews| Index: third_party/WebKit/Source/platform/scheduler/renderer/budget_pool.cc |
| diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/budget_pool.cc b/third_party/WebKit/Source/platform/scheduler/renderer/budget_pool.cc |
| index 0c68389330d7536300990bcd877a32a3f2acf551..6187294c5d90ad839b9af858cc4ca8a84f9714e3 100644 |
| --- a/third_party/WebKit/Source/platform/scheduler/renderer/budget_pool.cc |
| +++ b/third_party/WebKit/Source/platform/scheduler/renderer/budget_pool.cc |
| @@ -24,6 +24,13 @@ namespace scheduler { |
| namespace { |
| +base::Optional<base::TimeTicks> NextTaskRunTime(base::TimeTicks now, |
| + TaskQueue* queue) { |
| + if (queue->HasPendingImmediateWork()) |
| + return now; |
| + return queue->GetNextScheduledWakeUp(); |
| +} |
| + |
| std::string PointerToId(void* pointer) { |
| return base::StringPrintf( |
| "0x%" PRIx64, |
| @@ -51,7 +58,17 @@ void BudgetPool::AddQueue(base::TimeTicks now, TaskQueue* queue) { |
| if (!is_enabled_ || !budget_pool_controller_->IsThrottled(queue)) |
| return; |
| - budget_pool_controller_->BlockQueue(now, queue); |
| + base::Optional<base::TimeTicks> next_desired_run_time = |
| + NextTaskRunTime(now, queue); |
| + |
| + if (next_desired_run_time && !CanRunTasksAt(next_desired_run_time.value())) { |
| + budget_pool_controller_->BlockQueue(GetBlockType(), now, queue); |
| + } |
| +} |
| + |
| +void BudgetPool::UnregisterQueue(TaskQueue* queue) { |
| + budget_pool_controller_->RemoveQueueFromBudgetPool(queue, this); |
| + associated_task_queues_.erase(queue); |
| } |
| void BudgetPool::RemoveQueue(base::TimeTicks now, TaskQueue* queue) { |
| @@ -104,7 +121,7 @@ void BudgetPool::Close() { |
| void BudgetPool::BlockThrottledQueues(base::TimeTicks now) { |
| for (TaskQueue* queue : associated_task_queues_) |
| - budget_pool_controller_->BlockQueue(now, queue); |
| + budget_pool_controller_->BlockQueue(GetBlockType(), now, queue); |
| } |
| CPUTimeBudgetPool::CPUTimeBudgetPool( |
| @@ -117,6 +134,10 @@ CPUTimeBudgetPool::CPUTimeBudgetPool( |
| CPUTimeBudgetPool::~CPUTimeBudgetPool() {} |
| +QueueBlockType CPUTimeBudgetPool::GetBlockType() const { |
| + return QueueBlockType::FULL; |
| +} |
| + |
| void CPUTimeBudgetPool::SetMaxBudgetLevel( |
| base::TimeTicks now, |
| base::Optional<base::TimeDelta> max_budget_level) { |
| @@ -159,11 +180,17 @@ void CPUTimeBudgetPool::SetReportingCallback( |
| reporting_callback_ = reporting_callback; |
| } |
| -bool CPUTimeBudgetPool::HasEnoughBudgetToRun(base::TimeTicks now) { |
| - return now >= GetNextAllowedRunTime(); |
| +bool CPUTimeBudgetPool::CanRunTasksAt(base::TimeTicks now) const { |
| + return now >= GetNextAllowedRunTime(now); |
| +} |
| + |
| +bool CPUTimeBudgetPool::CanRunTasksUntil(base::TimeTicks now, |
| + base::TimeTicks moment) const { |
| + return CanRunTasksAt(now); |
| } |
| -base::TimeTicks CPUTimeBudgetPool::GetNextAllowedRunTime() { |
| +base::TimeTicks CPUTimeBudgetPool::GetNextAllowedRunTime( |
| + base::TimeTicks desired_run_time) const { |
| if (!is_enabled_ || current_budget_level_.InMicroseconds() >= 0) { |
| return last_checkpoint_; |
| } else { |
| @@ -174,7 +201,8 @@ base::TimeTicks CPUTimeBudgetPool::GetNextAllowedRunTime() { |
| } |
| } |
| -void CPUTimeBudgetPool::RecordTaskRunTime(base::TimeTicks start_time, |
| +void CPUTimeBudgetPool::RecordTaskRunTime(TaskQueue* queue, |
| + base::TimeTicks start_time, |
| base::TimeTicks end_time) { |
| DCHECK_LE(start_time, end_time); |
| Advance(end_time); |
| @@ -190,6 +218,18 @@ void CPUTimeBudgetPool::RecordTaskRunTime(base::TimeTicks start_time, |
| } |
| } |
| +void CPUTimeBudgetPool::OnTaskQueueHasWork(TaskQueue* queue, |
| + base::TimeTicks now, |
| + base::TimeTicks desired_run_time) { |
| + if (!CanRunTasksAt(desired_run_time)) { |
| + budget_pool_controller_->BlockQueue(GetBlockType(), now, queue); |
| + } else { |
| + budget_pool_controller_->UnblockQueue(now, queue); |
| + } |
| +} |
| + |
| +void CPUTimeBudgetPool::OnWakeup(base::TimeTicks now) {} |
| + |
| void CPUTimeBudgetPool::AsValueInto(base::trace_event::TracedValue* state, |
| base::TimeTicks now) const { |
| state->BeginDictionary(name_); |
| @@ -245,5 +285,101 @@ void CPUTimeBudgetPool::EnforceBudgetLevelRestrictions() { |
| } |
| } |
| +WakeupBudgetPool::WakeupBudgetPool(const char* name, |
| + BudgetPoolController* budget_pool_controller, |
| + base::TimeTicks now) |
| + : BudgetPool(name, budget_pool_controller), |
| + wakeups_per_second_(1), |
| + last_wakeup_(now) {} |
| + |
| +WakeupBudgetPool::~WakeupBudgetPool() {} |
| + |
| +QueueBlockType WakeupBudgetPool::GetBlockType() const { |
| + return QueueBlockType::NEW_TASKS_ONLY; |
| +} |
| + |
| +void WakeupBudgetPool::SetWakeupRate(base::TimeTicks now, |
| + double wakeups_per_second) { |
| + last_wakeup_ = now; |
| + wakeups_per_second_ = wakeups_per_second; |
| +} |
| + |
| +void WakeupBudgetPool::SetWakeupDuration(base::TimeTicks now, |
| + base::TimeDelta duration) { |
| + last_wakeup_ = now; |
| + wakeup_duration_ = duration; |
| +} |
| + |
| +void WakeupBudgetPool::RecordTaskRunTime(TaskQueue* queue, |
| + base::TimeTicks start_time, |
| + base::TimeTicks end_time) { |
| + base::Optional<base::TimeTicks> next_desired_run_time = |
| + NextTaskRunTime(end_time, queue); |
| + |
| + if (next_desired_run_time && !CanRunTasksAt(next_desired_run_time.value())) |
| + budget_pool_controller_->BlockQueue(GetBlockType(), end_time, queue); |
| +} |
| + |
| +base::TimeTicks WakeupBudgetPool::NextWakeup() const { |
| + // Subtract 1 microsecond to work with time alignment in task queue throttler. |
|
alex clarke (OOO till 29th)
2017/04/21 09:14:19
What happens if you don't do that?
altimin
2017/04/25 13:22:34
Alignment in PumpThrottledTasks happens. Improved
|
| + return last_wakeup_ + base::TimeDelta::FromSeconds(1 / wakeups_per_second_) - |
| + base::TimeDelta::FromMicroseconds(1); |
| +} |
| + |
| +bool WakeupBudgetPool::CanRunTasksAt(base::TimeTicks now) const { |
| + if (now < last_wakeup_ + wakeup_duration_) |
|
alex clarke (OOO till 29th)
2017/04/21 09:14:18
Shouldn't that be <= ?
altimin
2017/04/25 13:22:35
Added a comment.
|
| + return true; |
| + return now >= NextWakeup(); |
| +} |
| + |
| +bool WakeupBudgetPool::CanRunTasksUntil(base::TimeTicks now, |
| + base::TimeTicks moment) const { |
| + DCHECK_LE(now, moment); |
| + return now < last_wakeup_ + wakeup_duration_ && |
|
alex clarke (OOO till 29th)
2017/04/21 09:14:19
Ditto.
altimin
2017/04/25 13:22:34
Acknowledged.
|
| + moment < last_wakeup_ + wakeup_duration_; |
| +} |
| + |
| +base::TimeTicks WakeupBudgetPool::GetNextAllowedRunTime( |
| + base::TimeTicks desired_run_time) const { |
| + if (desired_run_time <= last_wakeup_ + wakeup_duration_) { |
| + return desired_run_time; |
| + } |
| + return std::max(desired_run_time, NextWakeup()); |
| +} |
| + |
| +void WakeupBudgetPool::OnTaskQueueHasWork(TaskQueue* queue, |
| + base::TimeTicks now, |
| + base::TimeTicks desired_run_time) { |
| + if (!CanRunTasksAt(desired_run_time)) { |
| + budget_pool_controller_->BlockQueue(GetBlockType(), now, queue); |
|
alex clarke (OOO till 29th)
2017/04/21 09:14:19
Maybe swap the order of these to avoid the negatio
altimin
2017/04/25 13:22:34
Done.
|
| + } else { |
| + budget_pool_controller_->UnblockQueue(now, queue); |
| + } |
| +} |
| + |
| +void WakeupBudgetPool::OnWakeup(base::TimeTicks now) { |
| + last_wakeup_ = now; |
| +} |
| + |
| +void WakeupBudgetPool::AsValueInto(base::trace_event::TracedValue* state, |
| + base::TimeTicks now) const { |
| + state->BeginDictionary(name_); |
| + |
| + state->SetString("name", name_); |
| + state->SetDouble("wakeups_per_second_rate", wakeups_per_second_); |
| + state->SetDouble("wakeup_duration_in_seconds", wakeup_duration_.InSecondsF()); |
| + state->SetDouble("last_wakeup_seconds_ago", |
| + (now - last_wakeup_).InSecondsF()); |
| + state->SetBoolean("is_enabled", is_enabled_); |
| + |
| + state->BeginArray("task_queues"); |
| + for (TaskQueue* queue : associated_task_queues_) { |
| + state->AppendString(PointerToId(queue)); |
| + } |
| + state->EndArray(); |
| + |
| + state->EndDictionary(); |
| +} |
| + |
| } // namespace scheduler |
| } // namespace blink |