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..dc7c0d2c5144241e8dbdfc6852511359feaea21c 100644 |
--- a/third_party/WebKit/Source/platform/scheduler/renderer/budget_pool.cc |
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/budget_pool.cc |
@@ -48,20 +48,27 @@ void BudgetPool::AddQueue(base::TimeTicks now, TaskQueue* queue) { |
budget_pool_controller_->AddQueueToBudgetPool(queue, this); |
associated_task_queues_.insert(queue); |
- if (!is_enabled_ || !budget_pool_controller_->IsThrottled(queue)) |
+ if (!is_enabled_) |
return; |
+ budget_pool_controller_->UpdateQueueThrottlingState(now, queue); |
+} |
- budget_pool_controller_->BlockQueue(now, queue); |
+void BudgetPool::UnregisterQueue(TaskQueue* queue) { |
+ DissociateQueue(queue); |
} |
void BudgetPool::RemoveQueue(base::TimeTicks now, TaskQueue* queue) { |
- budget_pool_controller_->RemoveQueueFromBudgetPool(queue, this); |
- associated_task_queues_.erase(queue); |
+ DissociateQueue(queue); |
- if (!is_enabled_ || !budget_pool_controller_->IsThrottled(queue)) |
+ if (!is_enabled_) |
return; |
- budget_pool_controller_->UnblockQueue(now, queue); |
+ budget_pool_controller_->UpdateQueueThrottlingState(now, queue); |
+} |
+ |
+void BudgetPool::DissociateQueue(TaskQueue* queue) { |
+ budget_pool_controller_->RemoveQueueFromBudgetPool(queue, this); |
+ associated_task_queues_.erase(queue); |
} |
void BudgetPool::EnableThrottling(LazyNow* lazy_now) { |
@@ -82,10 +89,7 @@ void BudgetPool::DisableThrottling(LazyNow* lazy_now) { |
TRACE_EVENT0("renderer.scheduler", "BudgetPool_DisableThrottling"); |
for (TaskQueue* queue : associated_task_queues_) { |
- if (!budget_pool_controller_->IsThrottled(queue)) |
- continue; |
- |
- budget_pool_controller_->UnblockQueue(lazy_now->Now(), queue); |
+ budget_pool_controller_->UpdateQueueThrottlingState(lazy_now->Now(), queue); |
} |
// TODO(altimin): We need to disable TimeBudgetQueues here or they will |
@@ -104,7 +108,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_->UpdateQueueThrottlingState(now, queue); |
} |
CPUTimeBudgetPool::CPUTimeBudgetPool( |
@@ -117,6 +121,10 @@ CPUTimeBudgetPool::CPUTimeBudgetPool( |
CPUTimeBudgetPool::~CPUTimeBudgetPool() {} |
+QueueBlockType CPUTimeBudgetPool::GetBlockType() const { |
+ return QueueBlockType::kAllTasks; |
+} |
+ |
void CPUTimeBudgetPool::SetMaxBudgetLevel( |
base::TimeTicks now, |
base::Optional<base::TimeDelta> max_budget_level) { |
@@ -159,11 +167,18 @@ void CPUTimeBudgetPool::SetReportingCallback( |
reporting_callback_ = reporting_callback; |
} |
-bool CPUTimeBudgetPool::HasEnoughBudgetToRun(base::TimeTicks now) { |
- return now >= GetNextAllowedRunTime(); |
+bool CPUTimeBudgetPool::CanRunTasksAt(base::TimeTicks now, |
+ bool is_wake_up) const { |
+ return now >= GetNextAllowedRunTime(now); |
+} |
+ |
+bool CPUTimeBudgetPool::CanRunTasksUntil(base::TimeTicks now, |
+ base::TimeTicks moment) const { |
+ return CanRunTasksAt(now, false); |
} |
-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 +189,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); |
@@ -188,8 +204,20 @@ void CPUTimeBudgetPool::RecordTaskRunTime(base::TimeTicks start_time, |
reporting_callback_.Run(-current_budget_level_ / cpu_percentage_); |
} |
} |
+ |
+ if (current_budget_level_.InSecondsF() < 0) { |
+ BlockThrottledQueues(end_time); |
+ } |
+} |
+ |
+void CPUTimeBudgetPool::OnTaskQueueHasWork(TaskQueue* queue, |
+ base::TimeTicks now, |
+ base::TimeTicks desired_run_time) { |
+ budget_pool_controller_->UpdateQueueThrottlingState(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 +273,102 @@ void CPUTimeBudgetPool::EnforceBudgetLevelRestrictions() { |
} |
} |
+WakeUpBudgetPool::WakeUpBudgetPool(const char* name, |
+ BudgetPoolController* budget_pool_controller, |
+ base::TimeTicks now) |
+ : BudgetPool(name, budget_pool_controller), wakeups_per_second_(1) {} |
+ |
+WakeUpBudgetPool::~WakeUpBudgetPool() {} |
+ |
+QueueBlockType WakeUpBudgetPool::GetBlockType() const { |
+ return QueueBlockType::kNewTasksOnly; |
+} |
+ |
+void WakeUpBudgetPool::SetWakeUpRate(double wakeups_per_second) { |
+ wakeups_per_second_ = wakeups_per_second; |
+} |
+ |
+void WakeUpBudgetPool::SetWakeUpDuration(base::TimeDelta duration) { |
+ wakeup_duration_ = duration; |
+} |
+ |
+void WakeUpBudgetPool::RecordTaskRunTime(TaskQueue* queue, |
+ base::TimeTicks start_time, |
+ base::TimeTicks end_time) { |
+ budget_pool_controller_->UpdateQueueThrottlingState(end_time, queue); |
+} |
+ |
+base::Optional<base::TimeTicks> WakeUpBudgetPool::NextWakeUp() const { |
+ if (!last_wakeup_) |
+ return base::nullopt; |
+ // Subtract 1 microsecond to work with time alignment in task queue throttler. |
+ // This is needed due to alignment mechanism in task queue throttler -- |
+ // whole seconds need to be aligned to the next second to deal with immediate |
+ // tasks correctly. By subtracting 1 microsecond we ensure that next wakeup |
+ // gets aligned to a correct time. |
+ return last_wakeup_.value() + |
+ base::TimeDelta::FromSeconds(1 / wakeups_per_second_) - |
+ base::TimeDelta::FromMicroseconds(1); |
Sami
2017/04/26 13:09:08
Would it be less arbitrary to subtract base::TimeD
altimin
2017/04/26 14:31:29
The current approach is easier to test.
|
+} |
+ |
+bool WakeUpBudgetPool::CanRunTasksAt(base::TimeTicks now, |
+ bool is_wake_up) const { |
+ if (!last_wakeup_) |
Sami
2017/04/26 13:09:08
If we haven't had a wake up, should we allow every
altimin
2017/04/26 14:31:29
No, if we're throttled we should wait for a wake-u
Sami
2017/04/27 12:12:30
Okay, could you add a comment about that here plea
|
+ return false; |
+ if (last_wakeup_ == now && is_wake_up) |
+ return true; |
+ return now < last_wakeup_.value() + wakeup_duration_; |
+} |
+ |
+bool WakeUpBudgetPool::CanRunTasksUntil(base::TimeTicks now, |
+ base::TimeTicks moment) const { |
+ if (!last_wakeup_) |
+ return false; |
+ DCHECK_LE(now, moment); |
+ return now < last_wakeup_.value() + wakeup_duration_ && |
+ moment < last_wakeup_.value() + wakeup_duration_; |
+} |
+ |
+base::TimeTicks WakeUpBudgetPool::GetNextAllowedRunTime( |
+ base::TimeTicks desired_run_time) const { |
+ if (!last_wakeup_) |
+ return desired_run_time; |
+ if (desired_run_time < last_wakeup_.value() + wakeup_duration_) |
+ return desired_run_time; |
+ return std::max(desired_run_time, NextWakeUp().value()); |
+} |
+ |
+void WakeUpBudgetPool::OnTaskQueueHasWork(TaskQueue* queue, |
+ base::TimeTicks now, |
+ base::TimeTicks desired_run_time) { |
+ budget_pool_controller_->UpdateQueueThrottlingState(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()); |
+ if (last_wakeup_) { |
+ state->SetDouble("last_wakeup_seconds_ago", |
+ (now - last_wakeup_.value()).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 |