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

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

Issue 2778123003: [scheduler] Add WakeupBudgetPool. (Closed)
Patch Set: First meaningful version Created 3 years, 8 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.cc
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.cc b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.cc
index e9744e259d6f4b2ed021c828e9b90c8a4e1df9e1..fe25b85a505999d99e6987336ff7d216c0b3bd21 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.cc
@@ -144,10 +144,12 @@ void TaskQueueThrottler::IncreaseThrottleRefCount(TaskQueue* task_queue) {
void TaskQueueThrottler::DecreaseThrottleRefCount(TaskQueue* task_queue) {
TaskQueueMap::iterator iter = queue_details_.find(task_queue);
- if (iter == queue_details_.end() ||
- --iter->second.throttling_ref_count != 0) {
+ if (iter == queue_details_.end())
+ return;
+ if (iter->second.throttling_ref_count == 0)
alex clarke (OOO till 29th) 2017/04/21 09:14:19 That looks really weird. Is this papering over a
altimin 2017/04/25 13:22:35 There is a special test ensuring that extra Decrea
+ return;
+ if (--iter->second.throttling_ref_count != 0)
return;
- }
TRACE_EVENT1(tracing_category_, "TaskQueueThrottler_TaskQueueUnthrottled",
"task_queue", task_queue);
@@ -178,10 +180,9 @@ void TaskQueueThrottler::UnregisterTaskQueue(TaskQueue* task_queue) {
if (find_it == queue_details_.end())
return;
- LazyNow lazy_now(tick_clock_);
std::unordered_set<BudgetPool*> budget_pools = find_it->second.budget_pools;
for (BudgetPool* budget_pool : budget_pools) {
- budget_pool->RemoveQueue(lazy_now.Now(), task_queue);
+ budget_pool->UnregisterQueue(task_queue);
}
// Iterator may have been deleted by BudgetPool::RemoveQueue, so don't
@@ -210,9 +211,20 @@ void TaskQueueThrottler::OnQueueNextWakeUpChanged(
return;
base::TimeTicks now = tick_clock_->NowTicks();
+
+ auto find_it = queue_details_.find(queue);
alex clarke (OOO till 29th) 2017/04/21 09:14:19 I don't remember off hand if return value optimiza
altimin 2017/04/25 13:22:35 auto find_it is a common pattern here. I don't wan
+ if (find_it == queue_details_.end())
+ return;
+
+ for (BudgetPool* budget_pool : find_it->second.budget_pools) {
+ budget_pool->OnTaskQueueHasWork(queue, now, next_wake_up);
+ }
+
+ base::TimeTicks next_allowed_run_time =
+ GetNextAllowedRunTime(queue, now, next_wake_up);
+ // TODO(altimin): Remove after moving to budget pools completely.
MaybeSchedulePumpThrottledTasks(
- FROM_HERE, now,
- std::max(GetNextAllowedRunTime(now, queue), next_wake_up));
+ FROM_HERE, now, std::max(next_wake_up, next_allowed_run_time));
}
void TaskQueueThrottler::PumpThrottledTasks() {
@@ -222,37 +234,57 @@ void TaskQueueThrottler::PumpThrottledTasks() {
LazyNow lazy_now(tick_clock_);
base::Optional<base::TimeTicks> next_scheduled_delayed_task;
+ for (const auto& it : budget_pools_)
alex clarke (OOO till 29th) 2017/04/21 09:14:19 uber nit: s/it/pair ;)
altimin 2017/04/25 13:22:35 Done.
+ it.first->OnWakeup(lazy_now.Now());
+
for (const TaskQueueMap::value_type& map_entry : queue_details_) {
TaskQueue* task_queue = map_entry.first;
- if (task_queue->IsEmpty() || !IsThrottled(task_queue))
+ if (task_queue->IsEmpty() || !task_queue->IsQueueEnabled() ||
+ !IsThrottled(task_queue)) {
continue;
+ }
- // Don't enable queues whose budget pool doesn't allow them to run now.
- base::TimeTicks next_allowed_run_time =
- GetNextAllowedRunTime(lazy_now.Now(), task_queue);
base::Optional<base::TimeTicks> next_desired_run_time =
NextTaskRunTime(&lazy_now, task_queue);
- if (next_desired_run_time &&
- next_allowed_run_time > next_desired_run_time.value()) {
+ if (!next_desired_run_time) {
+ // This task queue does not any tasks.
alex clarke (OOO till 29th) 2017/04/21 09:14:19 Looks like you're missing a word in the comment.
altimin 2017/04/25 13:22:35 Done.
+ task_queue->InsertFence(TaskQueue::InsertFencePosition::NOW);
alex clarke (OOO till 29th) 2017/04/21 09:14:19 Is it possible to get here? The queue has to be e
altimin 2017/04/25 13:22:35 Done.
+ continue;
+ }
+
+ base::TimeTicks next_run_time = GetNextAllowedRunTime(
+ task_queue, lazy_now.Now(), next_desired_run_time.value());
+
+ if (next_run_time > lazy_now.Now()) {
TRACE_EVENT1(
tracing_category_,
"TaskQueueThrottler::PumpThrottledTasks_ExpensiveTaskThrottled",
"throttle_time_in_seconds",
- (next_allowed_run_time - next_desired_run_time.value()).InSecondsF());
+ (next_run_time - next_desired_run_time.value()).InSecondsF());
- // Schedule a pump for queue which was disabled because of time budget.
next_scheduled_delayed_task =
- Min(next_scheduled_delayed_task, next_allowed_run_time);
+ Min(next_scheduled_delayed_task, next_run_time);
continue;
}
- next_scheduled_delayed_task =
- Min(next_scheduled_delayed_task, task_queue->GetNextScheduledWakeUp());
+ base::Optional<base::TimeTicks> next_wake_up =
+ task_queue->GetNextScheduledWakeUp();
+
+ if (next_wake_up) {
+ next_scheduled_delayed_task =
+ Min(next_scheduled_delayed_task,
+ GetNextAllowedRunTime(task_queue, lazy_now.Now(),
+ next_wake_up.value()));
+ }
- if (next_allowed_run_time > lazy_now.Now())
+ if (CanRunTasksUntil(task_queue, lazy_now.Now(),
+ next_desired_run_time.value())) {
+ // Remove fence if we can new tasks until next wakeup.
+ task_queue->RemoveFence();
continue;
+ }
// Remove previous fence and install a new one, allowing all tasks posted
// on |task_queue| up until this point to run and block all further tasks.
@@ -315,6 +347,13 @@ CPUTimeBudgetPool* TaskQueueThrottler::CreateCPUTimeBudgetPool(
return time_budget_pool;
}
+WakeupBudgetPool* TaskQueueThrottler::CreateWakeupBudgetPool(const char* name) {
+ WakeupBudgetPool* wakeup_budget_pool =
+ new WakeupBudgetPool(name, this, tick_clock_->NowTicks());
+ budget_pools_[wakeup_budget_pool] = base::WrapUnique(wakeup_budget_pool);
+ return wakeup_budget_pool;
+}
+
void TaskQueueThrottler::OnTaskRunTimeReported(TaskQueue* task_queue,
base::TimeTicks start_time,
base::TimeTicks end_time) {
@@ -326,17 +365,25 @@ void TaskQueueThrottler::OnTaskRunTimeReported(TaskQueue* task_queue,
return;
for (BudgetPool* budget_pool : find_it->second.budget_pools) {
- budget_pool->RecordTaskRunTime(start_time, end_time);
- if (!budget_pool->HasEnoughBudgetToRun(end_time))
+ budget_pool->RecordTaskRunTime(task_queue, start_time, end_time);
+ if (!budget_pool->CanRunTasksAt(end_time))
budget_pool->BlockThrottledQueues(end_time);
}
}
-void TaskQueueThrottler::BlockQueue(base::TimeTicks now, TaskQueue* queue) {
+void TaskQueueThrottler::BlockQueue(QueueBlockType block_type,
+ base::TimeTicks now,
+ TaskQueue* queue) {
if (!IsThrottled(queue))
return;
- queue->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME);
+ if (block_type == QueueBlockType::FULL) {
+ queue->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME);
+ } else { // block_type == BlockType::NEW_TASKS_ONLY
+ if (!queue->HasFence()) {
+ queue->InsertFence(TaskQueue::InsertFencePosition::NOW);
+ }
+ }
SchedulePumpQueue(FROM_HERE, now, queue);
}
@@ -399,30 +446,36 @@ void TaskQueueThrottler::UnregisterBudgetPool(BudgetPool* budget_pool) {
}
void TaskQueueThrottler::UnblockQueue(base::TimeTicks now, TaskQueue* queue) {
- SchedulePumpQueue(FROM_HERE, now, queue);
+ if (queue->HasFence())
alex clarke (OOO till 29th) 2017/04/21 09:14:19 I hope we don't get tempted to use fences for some
altimin 2017/04/25 13:22:36 Actually, we don't need this condition here.
+ SchedulePumpQueue(FROM_HERE, now, queue);
}
void TaskQueueThrottler::SchedulePumpQueue(
const tracked_objects::Location& from_here,
base::TimeTicks now,
TaskQueue* queue) {
- if (!IsThrottled(queue))
+ if (!IsThrottled(queue) || !queue->IsQueueEnabled())
return;
LazyNow lazy_now(now);
base::Optional<base::TimeTicks> next_desired_run_time =
NextTaskRunTime(&lazy_now, queue);
- if (!next_desired_run_time)
+ if (!next_desired_run_time) {
return;
-
- base::Optional<base::TimeTicks> next_run_time =
- Max(next_desired_run_time, GetNextAllowedRunTime(now, queue));
+ }
+ base::Optional<base::TimeTicks> next_run_time;
+ if (next_desired_run_time) {
+ next_run_time =
+ GetNextAllowedRunTime(queue, now, next_desired_run_time.value());
+ }
MaybeSchedulePumpThrottledTasks(from_here, now, next_run_time.value());
}
-base::TimeTicks TaskQueueThrottler::GetNextAllowedRunTime(base::TimeTicks now,
- TaskQueue* queue) {
+base::TimeTicks TaskQueueThrottler::GetNextAllowedRunTime(
+ TaskQueue* queue,
+ base::TimeTicks now,
alex clarke (OOO till 29th) 2017/04/21 09:14:19 I'm not 100% on this, but I wonder if things would
altimin 2017/04/25 13:22:35 Agreed.
+ base::TimeTicks desired_run_time) {
base::TimeTicks next_run_time = now;
auto find_it = queue_details_.find(queue);
@@ -430,13 +483,42 @@ base::TimeTicks TaskQueueThrottler::GetNextAllowedRunTime(base::TimeTicks now,
return next_run_time;
for (BudgetPool* budget_pool : find_it->second.budget_pools) {
- next_run_time =
- std::max(next_run_time, budget_pool->GetNextAllowedRunTime());
+ next_run_time = std::max(
+ next_run_time, budget_pool->GetNextAllowedRunTime(desired_run_time));
}
return next_run_time;
}
+bool TaskQueueThrottler::CanRunTasksAt(TaskQueue* queue,
+ base::TimeTicks moment) {
+ auto find_it = queue_details_.find(queue);
+ if (find_it == queue_details_.end())
+ return true;
+
+ for (BudgetPool* budget_pool : find_it->second.budget_pools) {
+ if (!budget_pool->CanRunTasksAt(moment))
+ return false;
+ }
+
+ return true;
+}
+
+bool TaskQueueThrottler::CanRunTasksUntil(TaskQueue* queue,
+ base::TimeTicks now,
+ base::TimeTicks moment) {
+ auto find_it = queue_details_.find(queue);
+ if (find_it == queue_details_.end())
+ return true;
+
+ for (BudgetPool* budget_pool : find_it->second.budget_pools) {
+ if (!budget_pool->CanRunTasksUntil(now, moment))
+ return false;
+ }
+
+ return true;
+}
+
void TaskQueueThrottler::MaybeDeleteQueueMetadata(TaskQueueMap::iterator it) {
if (it->second.throttling_ref_count == 0 && it->second.budget_pools.empty())
queue_details_.erase(it);

Powered by Google App Engine
This is Rietveld 408576698