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

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

Issue 2258133002: [scheduler] Implement time-based cpu throttling. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Use double instead of base::TimeTicks Created 4 years, 3 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/throttling_helper.cc b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.cc
similarity index 29%
rename from third_party/WebKit/Source/platform/scheduler/renderer/throttling_helper.cc
rename to third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.cc
index 20ff3a1116f6628a01002daf48055ed181c184e0..93ddc757ae57998a738e0750c83f7ae696e38d15 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/throttling_helper.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler.cc
@@ -2,9 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "platform/scheduler/renderer/throttling_helper.h"
+#include "platform/scheduler/renderer/task_queue_throttler.h"
+#include <cstdint>
+
+#include "base/format_macros.h"
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/optional.h"
+#include "base/strings/stringprintf.h"
#include "platform/scheduler/base/real_time_domain.h"
#include "platform/scheduler/child/scheduler_tqm_delegate.h"
#include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h"
@@ -13,11 +19,165 @@
#include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
#include "public/platform/WebFrameScheduler.h"
+#include <iostream> // FIXME
+
namespace blink {
namespace scheduler {
-ThrottlingHelper::ThrottlingHelper(RendererSchedulerImpl* renderer_scheduler,
- const char* tracing_category)
+namespace {
+const int kMaxBudgetLevelInSeconds = 1;
+}
+
+TaskQueueThrottler::TimeBudgetPool::TimeBudgetPool(
+ const char* name,
+ TaskQueueThrottler* task_queue_throttler,
+ base::TimeTicks now)
+ : name_(name),
+ task_queue_throttler_(task_queue_throttler),
+ max_budget_level_(base::TimeDelta::FromSeconds(kMaxBudgetLevelInSeconds)),
+ last_checkpoint_(now),
+ cpu_percentage_(1),
+ is_enabled_(true) {}
+
+TaskQueueThrottler::TimeBudgetPool::~TimeBudgetPool() {}
+
+void TaskQueueThrottler::TimeBudgetPool::SetTimeBudget(base::TimeTicks now,
+ double cpu_percentage) {
+ Advance(now);
+ cpu_percentage_ = cpu_percentage;
+}
+
+void TaskQueueThrottler::TimeBudgetPool::AddQueue(base::TimeTicks now,
+ TaskQueue* queue) {
+ DCHECK(task_queue_throttler_->time_budget_pool_for_queue_.find(queue) ==
+ task_queue_throttler_->time_budget_pool_for_queue_.end());
+ task_queue_throttler_->time_budget_pool_for_queue_[queue] = this;
+
+ assosiated_task_queues_.insert(queue);
+
+ if (!task_queue_throttler_->IsThrottled(queue))
+ return;
+
+ queue->SetQueueEnabled(false);
alex clarke (OOO till 29th) 2016/09/12 17:45:26 Is this safe? See TaskQueueThrottler::SetQueueEna
altimin 2016/09/14 11:23:16 Yes, it's safe to disable a throttled queue. For e
+
+ task_queue_throttler_->MaybeSchedulePumpQueueWithBudget(FROM_HERE, now, queue,
+ this);
+}
+
+void TaskQueueThrottler::TimeBudgetPool::RemoveQueue(base::TimeTicks now,
+ TaskQueue* queue) {
+ DCHECK_EQ(task_queue_throttler_->time_budget_pool_for_queue_[queue], this);
+ task_queue_throttler_->time_budget_pool_for_queue_.erase(queue);
+
+ assosiated_task_queues_.erase(queue);
+
+ if (!task_queue_throttler_->IsThrottled(queue))
+ return;
+
+ task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, now, queue);
+}
+
+void TaskQueueThrottler::TimeBudgetPool::Enable(base::TimeTicks now) {
alex clarke (OOO till 29th) 2016/09/12 17:45:26 Lazy now?
altimin 2016/09/14 11:23:17 Done.
+ if (is_enabled_)
+ return;
+ is_enabled_ = true;
+
+ for (TaskQueue* queue : assosiated_task_queues_) {
+ if (!task_queue_throttler_->IsThrottled(queue))
+ continue;
+
+ queue->SetQueueEnabled(false);
alex clarke (OOO till 29th) 2016/09/12 17:45:26 Ditto.
altimin 2016/09/14 11:23:17 Same as above.
+
+ task_queue_throttler_->MaybeSchedulePumpQueueWithBudget(FROM_HERE, now,
+ queue, this);
+ }
+}
+
+void TaskQueueThrottler::TimeBudgetPool::Disable(base::TimeTicks now) {
alex clarke (OOO till 29th) 2016/09/12 17:45:26 Lazy now?
alex clarke (OOO till 29th) 2016/09/12 17:45:26 I can't see how this is going to be used but I not
altimin 2016/09/14 11:23:16 We can't enable queue here because of timer alignm
altimin 2016/09/14 11:23:17 Done.
+ if (!is_enabled_)
+ return;
+ is_enabled_ = false;
+
+ for (TaskQueue* queue : assosiated_task_queues_) {
+ if (!task_queue_throttler_->IsThrottled(queue))
+ continue;
+
+ task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, now, queue);
+ }
+}
+
+bool TaskQueueThrottler::TimeBudgetPool::IsEnabled() const {
+ return is_enabled_;
+}
+
+void TaskQueueThrottler::TimeBudgetPool::Close() {
+ DCHECK_EQ(0u, assosiated_task_queues_.size());
+
+ task_queue_throttler_->time_budget_pools_.erase(this);
+}
+
+bool TaskQueueThrottler::TimeBudgetPool::IsAllowedToRun(base::TimeTicks now) {
+ Advance(now);
+ return !is_enabled_ || current_budget_level_.InMicroseconds() >= 0;
+}
+
+base::TimeTicks TaskQueueThrottler::TimeBudgetPool::NextAllowedRunTime() {
+ if (!is_enabled_ || current_budget_level_.InMicroseconds() >= 0) {
+ return last_checkpoint_;
+ } else {
+ // Subtract because current_budget is negative.
+ return last_checkpoint_ - current_budget_level_ / cpu_percentage_;
+ }
+}
+
+void TaskQueueThrottler::TimeBudgetPool::RecordTaskRunTime(
+ base::TimeDelta task_run_time) {
+ if (is_enabled_) {
+ current_budget_level_ -= task_run_time;
+ }
+}
+
+const char* TaskQueueThrottler::TimeBudgetPool::Name() const {
+ return name_;
+}
+
+void TaskQueueThrottler::TimeBudgetPool::AsValueInto(
+ base::trace_event::TracedValue* state,
+ base::TimeTicks now) const {
+ state->BeginDictionary();
+
+ state->SetString("name", name_);
+ state->SetDouble("time_budget", cpu_percentage_);
+ state->SetDouble("time_budget_level_in_seconds",
+ current_budget_level_.InSecondsF());
+ state->SetDouble("last_checkpoint_seconds_ago",
+ (now - last_checkpoint_).InSecondsF());
+
+ state->BeginArray("task_queues");
+ for (TaskQueue* queue : assosiated_task_queues_) {
+ // Yes, that's memory-infra-approved way of tracing pointers. Deal with it.
Sami 2016/09/12 17:49:10 I think we can do without this comment :)
altimin 2016/09/14 11:23:16 Done.
+ state->AppendString(base::StringPrintf(
+ "%" PRIx64, static_cast<uint64_t>(reinterpret_cast<uintptr_t>(queue))));
+ }
+ state->EndArray();
+
+ state->EndDictionary();
+}
+
+void TaskQueueThrottler::TimeBudgetPool::Advance(base::TimeTicks now) {
+ if (now > last_checkpoint_) {
+ if (is_enabled_) {
+ current_budget_level_ = std::min(
+ current_budget_level_ + cpu_percentage_ * (now - last_checkpoint_),
+ max_budget_level_);
+ }
+ last_checkpoint_ = now;
+ }
+}
+
+TaskQueueThrottler::TaskQueueThrottler(
+ RendererSchedulerImpl* renderer_scheduler,
+ const char* tracing_category)
: task_runner_(renderer_scheduler->ControlTaskRunner()),
renderer_scheduler_(renderer_scheduler),
tick_clock_(renderer_scheduler->tick_clock()),
@@ -26,15 +186,15 @@ ThrottlingHelper::ThrottlingHelper(RendererSchedulerImpl* renderer_scheduler,
virtual_time_(false),
weak_factory_(this) {
pump_throttled_tasks_closure_.Reset(base::Bind(
- &ThrottlingHelper::PumpThrottledTasks, weak_factory_.GetWeakPtr()));
+ &TaskQueueThrottler::PumpThrottledTasks, weak_factory_.GetWeakPtr()));
forward_immediate_work_closure_ =
- base::Bind(&ThrottlingHelper::OnTimeDomainHasImmediateWork,
+ base::Bind(&TaskQueueThrottler::OnTimeDomainHasImmediateWork,
weak_factory_.GetWeakPtr());
renderer_scheduler_->RegisterTimeDomain(time_domain_.get());
}
-ThrottlingHelper::~ThrottlingHelper() {
+TaskQueueThrottler::~TaskQueueThrottler() {
// It's possible for queues to be still throttled, so we need to tidy up
// before unregistering the time domain.
for (const TaskQueueMap::value_type& map_entry : throttled_queues_) {
@@ -46,7 +206,7 @@ ThrottlingHelper::~ThrottlingHelper() {
renderer_scheduler_->UnregisterTimeDomain(time_domain_.get());
}
-void ThrottlingHelper::SetQueueEnabled(TaskQueue* task_queue, bool enabled) {
+void TaskQueueThrottler::SetQueueEnabled(TaskQueue* task_queue, bool enabled) {
TaskQueueMap::iterator find_it = throttled_queues_.find(task_queue);
if (find_it == throttled_queues_.end()) {
@@ -63,7 +223,7 @@ void ThrottlingHelper::SetQueueEnabled(TaskQueue* task_queue, bool enabled) {
task_queue->SetQueueEnabled(false);
}
-void ThrottlingHelper::IncreaseThrottleRefCount(TaskQueue* task_queue) {
+void TaskQueueThrottler::IncreaseThrottleRefCount(TaskQueue* task_queue) {
DCHECK_NE(task_queue, task_runner_.get());
if (virtual_time_)
@@ -74,17 +234,20 @@ void ThrottlingHelper::IncreaseThrottleRefCount(TaskQueue* task_queue) {
task_queue, Metadata(1, task_queue->IsQueueEnabled())));
if (insert_result.second) {
- // The insert was succesful so we need to throttle the queue.
+ // The insert was successful so we need to throttle the queue.
task_queue->SetTimeDomain(time_domain_.get());
task_queue->RemoveFence();
task_queue->SetQueueEnabled(false);
- if (!task_queue->IsEmpty()) {
- if (task_queue->HasPendingImmediateWork()) {
- OnTimeDomainHasImmediateWork();
- } else {
- OnTimeDomainHasDelayedWork();
- }
+ base::Optional<base::TimeTicks> next_run_time =
+ task_queue->GetNextTaskRunTime();
+
+ if (next_run_time) {
+ MaybeSchedulePumpThrottledTasks(FROM_HERE, tick_clock_->NowTicks(),
+ next_run_time.value());
+
+ TRACE_EVENT1(tracing_category_, "TaskQueueThrottler_TaskQueueThrottled",
+ "task_queue", task_queue);
}
} else {
// An entry already existed in the map so we need to increment the refcount.
@@ -92,7 +255,7 @@ void ThrottlingHelper::IncreaseThrottleRefCount(TaskQueue* task_queue) {
}
}
-void ThrottlingHelper::DecreaseThrottleRefCount(TaskQueue* task_queue) {
+void TaskQueueThrottler::DecreaseThrottleRefCount(TaskQueue* task_queue) {
if (virtual_time_)
return;
@@ -107,104 +270,158 @@ void ThrottlingHelper::DecreaseThrottleRefCount(TaskQueue* task_queue) {
task_queue->SetTimeDomain(renderer_scheduler_->real_time_domain());
task_queue->RemoveFence();
task_queue->SetQueueEnabled(enabled);
+
+ TRACE_EVENT1(tracing_category_, "TaskQueueThrottler_TaskQueueUntrottled",
+ "task_queue", task_queue);
}
}
-bool ThrottlingHelper::IsThrottled(TaskQueue* task_queue) const {
+bool TaskQueueThrottler::IsThrottled(TaskQueue* task_queue) const {
return throttled_queues_.find(task_queue) != throttled_queues_.end();
}
-void ThrottlingHelper::UnregisterTaskQueue(TaskQueue* task_queue) {
+void TaskQueueThrottler::UnregisterTaskQueue(TaskQueue* task_queue) {
throttled_queues_.erase(task_queue);
}
-void ThrottlingHelper::OnTimeDomainHasImmediateWork() {
+void TaskQueueThrottler::OnTimeDomainHasImmediateWork() {
// Forward to the main thread if called from another thread.
if (!task_runner_->RunsTasksOnCurrentThread()) {
task_runner_->PostTask(FROM_HERE, forward_immediate_work_closure_);
return;
}
TRACE_EVENT0(tracing_category_,
- "ThrottlingHelper::OnTimeDomainHasImmediateWork");
+ "TaskQueueThrottler::OnTimeDomainHasImmediateWork");
base::TimeTicks now = tick_clock_->NowTicks();
- MaybeSchedulePumpThrottledTasksLocked(FROM_HERE, now, now);
+ MaybeSchedulePumpThrottledTasks(FROM_HERE, now, now);
}
-void ThrottlingHelper::OnTimeDomainHasDelayedWork() {
+void TaskQueueThrottler::OnTimeDomainHasDelayedWork() {
TRACE_EVENT0(tracing_category_,
- "ThrottlingHelper::OnTimeDomainHasDelayedWork");
+ "TaskQueueThrottler::OnTimeDomainHasDelayedWork");
+ // TODO(altimin): Consider using TaskQueue::GetNextTaskRunTime here.
+ // to avoid unnecessary wakeups. Currently it's not possible because
+ // GetNextTaskRunTime requires a lock and OnTimeDomainHasDelayedWork
Sami 2016/09/12 17:49:10 nit: a lock on the queue?
altimin 2016/09/14 11:23:16 Done.
+ // can be called from TaskQueueImpl::SetTimeDomain, which acquires lock.
base::TimeTicks next_scheduled_delayed_task;
bool has_delayed_task =
time_domain_->NextScheduledRunTime(&next_scheduled_delayed_task);
DCHECK(has_delayed_task);
base::TimeTicks now = tick_clock_->NowTicks();
- MaybeSchedulePumpThrottledTasksLocked(FROM_HERE, now,
- next_scheduled_delayed_task);
+ MaybeSchedulePumpThrottledTasks(FROM_HERE, now, next_scheduled_delayed_task);
}
-void ThrottlingHelper::PumpThrottledTasks() {
- TRACE_EVENT0(tracing_category_, "ThrottlingHelper::PumpThrottledTasks");
- pending_pump_throttled_tasks_runtime_ = base::TimeTicks();
+namespace {
+
+template <class T>
+T Min(const base::Optional<T>& optional, const T& value) {
+ if (!optional) {
+ return value;
+ }
+ return std::min(optional.value(), value);
+}
+
+template <class T>
+base::Optional<T> Min(const base::Optional<T>& a, const base::Optional<T>& b) {
+ if (!b)
+ return a;
+ if (!a)
+ return b;
+ return std::min(a.value(), b.value());
+}
+
+} // namespace
+
+void TaskQueueThrottler::PumpThrottledTasks() {
+ TRACE_EVENT0("renderer.scheduler", "TaskQueueThrottler::PumpThrottledTasks");
+ pending_pump_throttled_tasks_runtime_.reset();
+
+ LazyNow lazy_now(tick_clock_);
+ base::Optional<base::TimeTicks> next_scheduled_delayed_task;
- LazyNow lazy_low(tick_clock_);
for (const TaskQueueMap::value_type& map_entry : throttled_queues_) {
TaskQueue* task_queue = map_entry.first;
if (!map_entry.second.enabled || task_queue->IsEmpty())
continue;
+ TimeBudgetPool* time_budget_pool = GetTimeBudgetPoolForQueue(task_queue);
+ if (time_budget_pool && !time_budget_pool->IsAllowedToRun(lazy_now.Now())) {
+ base::TimeTicks next_run_time =
+ std::max(time_budget_pool->NextAllowedRunTime(), lazy_now.Now());
+
+ next_scheduled_delayed_task =
+ Min(next_scheduled_delayed_task, next_run_time);
+
+ TRACE_EVENT1(
+ "renderer.scheduler",
+ "TaskQueueThrottler::PumpThrottledTasks_ExpensiveTaskThrottled",
+ "throttle_time_in_seconds",
+ (next_run_time - lazy_now.Now()).InSecondsF());
+
+ renderer_scheduler_->CreateTraceEventObjectSnapshot();
+
+ continue;
+ }
+
+ base::Optional<base::TimeTicks> wake_up =
+ task_queue->GetNextScheduledWakeUp();
+ next_scheduled_delayed_task = Min(next_scheduled_delayed_task, wake_up);
+
+ // GetNextScheduledWakeUp() moves tasks from incoming queue to delayed
alex clarke (OOO till 29th) 2016/09/12 17:45:26 1. I'm not sure that's right, InsertFence should n
altimin 2016/09/14 11:23:16 My comment was badly phrased. We just want to move
+ // queue,
Sami 2016/09/12 17:49:10 nit: please reformat
altimin 2016/09/14 11:23:16 Done.
+ // so InsertFence() should be called after it in order to correctly
+ // get next wake up time.
task_queue->SetQueueEnabled(true);
task_queue->InsertFence();
}
- // Make sure NextScheduledRunTime gives us an up-to date result.
- time_domain_->ClearExpiredWakeups();
- base::TimeTicks next_scheduled_delayed_task;
- // Maybe schedule a call to ThrottlingHelper::PumpThrottledTasks if there is
- // a pending delayed task. NOTE posting a non-delayed task in the future will
- // result in ThrottlingHelper::OnTimeDomainHasImmediateWork being called.
- if (time_domain_->NextScheduledRunTime(&next_scheduled_delayed_task)) {
- MaybeSchedulePumpThrottledTasksLocked(FROM_HERE, lazy_low.Now(),
- next_scheduled_delayed_task);
+ // Maybe schedule a call to TaskQueueThrottler::PumpThrottledTasks if there is
+ // a pending delayed task or a throttled task ready to run.
+ // NOTE: posting a non-delayed task in the future will result in
+ // TaskQueueThrottler::OnTimeDomainHasImmediateWork being called.
+ if (next_scheduled_delayed_task) {
+ MaybeSchedulePumpThrottledTasks(FROM_HERE, lazy_now.Now(),
+ *next_scheduled_delayed_task);
}
}
/* static */
-base::TimeTicks ThrottlingHelper::ThrottledRunTime(
+base::TimeTicks TaskQueueThrottler::AlignedThrottledRunTime(
base::TimeTicks unthrottled_runtime) {
const base::TimeDelta one_second = base::TimeDelta::FromSeconds(1);
return unthrottled_runtime + one_second -
((unthrottled_runtime - base::TimeTicks()) % one_second);
}
-void ThrottlingHelper::MaybeSchedulePumpThrottledTasksLocked(
+void TaskQueueThrottler::MaybeSchedulePumpThrottledTasks(
const tracked_objects::Location& from_here,
base::TimeTicks now,
- base::TimeTicks unthrottled_runtime) {
+ base::TimeTicks runtime) {
if (virtual_time_)
return;
- base::TimeTicks throttled_runtime =
- ThrottledRunTime(std::max(now, unthrottled_runtime));
+ runtime = std::max(now, AlignedThrottledRunTime(runtime));
+
// If there is a pending call to PumpThrottledTasks and it's sooner than
- // |unthrottled_runtime| then return.
- if (!pending_pump_throttled_tasks_runtime_.is_null() &&
- throttled_runtime >= pending_pump_throttled_tasks_runtime_) {
+ // |runtime| then return.
+ if (pending_pump_throttled_tasks_runtime_ &&
+ runtime >= pending_pump_throttled_tasks_runtime_.value()) {
return;
}
- pending_pump_throttled_tasks_runtime_ = throttled_runtime;
+ pending_pump_throttled_tasks_runtime_ = runtime;
pump_throttled_tasks_closure_.Cancel();
- base::TimeDelta delay = pending_pump_throttled_tasks_runtime_ - now;
+ base::TimeDelta delay = pending_pump_throttled_tasks_runtime_.value() - now;
TRACE_EVENT1(tracing_category_,
- "ThrottlingHelper::MaybeSchedulePumpThrottledTasksLocked",
+ "TaskQueueThrottler::MaybeSchedulePumpThrottledTasks",
"delay_till_next_pump_ms", delay.InMilliseconds());
task_runner_->PostDelayedTask(
from_here, pump_throttled_tasks_closure_.callback(), delay);
}
-void ThrottlingHelper::EnableVirtualTime() {
+void TaskQueueThrottler::EnableVirtualTime() {
virtual_time_ = true;
pump_throttled_tasks_closure_.Cancel();
@@ -221,5 +438,92 @@ void ThrottlingHelper::EnableVirtualTime() {
}
}
+TaskQueueThrottler::TimeBudgetPool* TaskQueueThrottler::CreateTimeBudgetPool(
+ const char* name) {
+ TimeBudgetPool* time_budget_pool =
+ new TimeBudgetPool(name, this, tick_clock_->NowTicks());
+ time_budget_pools_[time_budget_pool] = base::WrapUnique(time_budget_pool);
+ return time_budget_pool;
+}
+
+void TaskQueueThrottler::OnTaskRunTimeReported(TaskQueue* task_queue,
+ base::TimeTicks start_time,
+ base::TimeTicks end_time) {
+ if (throttled_queues_.find(task_queue) == throttled_queues_.end())
alex clarke (OOO till 29th) 2016/09/12 17:45:26 This is going to get called a lot, currently TaskQ
altimin 2016/09/14 11:23:16 Done.
+ return;
+
+ TimeBudgetPool* time_budget_pool = GetTimeBudgetPoolForQueue(task_queue);
+ if (time_budget_pool) {
+ time_budget_pool->RecordTaskRunTime(end_time - start_time);
+ if (!time_budget_pool->IsAllowedToRun(end_time)) {
+ // This task was too expensive and all following tasks are throttled
+ // until explicitly allowed.
+ task_queue->SetQueueEnabled(false);
+
+ if (task_queue->HasPendingImmediateWork()) {
+ MaybeSchedulePumpThrottledTasks(
+ FROM_HERE, end_time,
+ std::max(end_time, time_budget_pool->NextAllowedRunTime()));
+ }
+ }
+ }
+}
+
+void TaskQueueThrottler::AsValueInto(base::trace_event::TracedValue* state,
+ base::TimeTicks now) const {
+ if (pending_pump_throttled_tasks_runtime_) {
+ state->SetDouble(
+ "next_throttled_tasks_pump_in_seconds",
+ (pending_pump_throttled_tasks_runtime_.value() - now).InSecondsF());
+ }
+
+ state->BeginDictionary("time_budget_pools");
+
+ for (const auto& map_entry : time_budget_pools_) {
+ TaskQueueThrottler::TimeBudgetPool* pool = map_entry.first;
+ pool->AsValueInto(state, now);
+ }
+
+ state->EndDictionary();
+}
+
+TaskQueueThrottler::TimeBudgetPool*
+TaskQueueThrottler::GetTimeBudgetPoolForQueue(TaskQueue* queue) {
alex clarke (OOO till 29th) 2016/09/12 17:45:26 If you move TimeBudgetPool* into the Metadata stru
altimin 2016/09/14 11:23:16 It will break the assumption that we have only thr
+ auto find_it = time_budget_pool_for_queue_.find(queue);
+ if (find_it == time_budget_pool_for_queue_.end()) {
+ return nullptr;
+ } else {
+ TimeBudgetPool* result = find_it->second;
+ DCHECK(result);
+ return result;
+ }
+}
+
+void TaskQueueThrottler::MaybeSchedulePumpQueue(
+ const tracked_objects::Location& from_here,
+ base::TimeTicks now,
+ TaskQueue* queue) {
+ base::Optional<base::TimeTicks> next_run_time = queue->GetNextTaskRunTime();
+ if (next_run_time) {
+ MaybeSchedulePumpThrottledTasks(from_here, now, next_run_time.value());
+ }
+}
+
+void TaskQueueThrottler::MaybeSchedulePumpQueueWithBudget(
+ const tracked_objects::Location& from_here,
+ base::TimeTicks now,
+ TaskQueue* queue,
+ TaskQueueThrottler::TimeBudgetPool* budget) {
+ base::Optional<base::TimeTicks> next_run_time = budget->NextAllowedRunTime();
Sami 2016/09/12 17:49:10 I think it's a little weird for this to ask inform
altimin 2016/09/14 11:23:16 Done.
+
+ if (!budget->IsAllowedToRun(now)) {
+ next_run_time = Min(next_run_time, queue->GetNextTaskRunTime());
+ }
+
+ if (next_run_time) {
+ MaybeSchedulePumpThrottledTasks(from_here, now, next_run_time.value());
+ }
+}
+
} // namespace scheduler
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698