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 |