Commit e6d316b4 authored by altimin's avatar altimin Committed by Commit bot

[scheduler] Move TimeBudgetPool to a separate file.

This is one of the few CLs refactoring budget pool mechanisms for the
addition of the new WakeupBudgetPool.

- Move TimeBudgetPool into budget_pool.h to keep task_queue_throttler
size manageable.
- Split TimeBudgetPool into BudgetPool (interface) and TimeBudgetPool
(realisation).

There will be a separate CL uncoupling TaskQueueThrottler from BudgetPool.

R=alexclarke@chromium.org,skyostil@chromium.org

BUG=699541

Review-Url: https://codereview.chromium.org/2741473002
Cr-Commit-Position: refs/heads/master@{#455747}
parent b4509020
...@@ -1202,6 +1202,8 @@ component("platform") { ...@@ -1202,6 +1202,8 @@ component("platform") {
"scheduler/child/worker_scheduler_impl.h", "scheduler/child/worker_scheduler_impl.h",
"scheduler/renderer/auto_advancing_virtual_time_domain.cc", "scheduler/renderer/auto_advancing_virtual_time_domain.cc",
"scheduler/renderer/auto_advancing_virtual_time_domain.h", "scheduler/renderer/auto_advancing_virtual_time_domain.h",
"scheduler/renderer/budget_pool.cc",
"scheduler/renderer/budget_pool.h",
"scheduler/renderer/deadline_task_runner.cc", "scheduler/renderer/deadline_task_runner.cc",
"scheduler/renderer/deadline_task_runner.h", "scheduler/renderer/deadline_task_runner.h",
"scheduler/renderer/idle_time_estimator.cc", "scheduler/renderer/idle_time_estimator.cc",
...@@ -1770,6 +1772,7 @@ test("blink_platform_unittests") { ...@@ -1770,6 +1772,7 @@ test("blink_platform_unittests") {
"scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc", "scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc",
"scheduler/child/worker_scheduler_impl_unittest.cc", "scheduler/child/worker_scheduler_impl_unittest.cc",
"scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc", "scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc",
"scheduler/renderer/budget_pool_unittest.cc",
"scheduler/renderer/deadline_task_runner_unittest.cc", "scheduler/renderer/deadline_task_runner_unittest.cc",
"scheduler/renderer/idle_time_estimator_unittest.cc", "scheduler/renderer/idle_time_estimator_unittest.cc",
"scheduler/renderer/renderer_scheduler_impl_unittest.cc", "scheduler/renderer/renderer_scheduler_impl_unittest.cc",
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "platform/scheduler/renderer/budget_pool.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/WebFrameScheduler.h"
#include "platform/scheduler/base/real_time_domain.h"
#include "platform/scheduler/child/scheduler_tqm_delegate.h"
#include "platform/scheduler/renderer/renderer_scheduler_impl.h"
#include "platform/scheduler/renderer/task_queue_throttler.h"
#include "platform/scheduler/renderer/throttled_time_domain.h"
#include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
namespace blink {
namespace scheduler {
namespace {
std::string PointerToId(void* pointer) {
return base::StringPrintf(
"0x%" PRIx64,
static_cast<uint64_t>(reinterpret_cast<uintptr_t>(pointer)));
}
} // namespace
BudgetPool::~BudgetPool() {}
CPUTimeBudgetPool::CPUTimeBudgetPool(
const char* name,
TaskQueueThrottler* task_queue_throttler,
base::TimeTicks now,
base::Optional<base::TimeDelta> max_budget_level,
base::Optional<base::TimeDelta> max_throttling_duration)
: name_(name),
task_queue_throttler_(task_queue_throttler),
max_budget_level_(max_budget_level),
max_throttling_duration_(max_throttling_duration),
last_checkpoint_(now),
cpu_percentage_(1),
is_enabled_(true) {}
CPUTimeBudgetPool::~CPUTimeBudgetPool() {}
void CPUTimeBudgetPool::SetTimeBudgetRecoveryRate(base::TimeTicks now,
double cpu_percentage) {
Advance(now);
cpu_percentage_ = cpu_percentage;
EnforceBudgetLevelRestrictions();
}
void CPUTimeBudgetPool::AddQueue(base::TimeTicks now, TaskQueue* queue) {
std::pair<TaskQueueThrottler::TaskQueueMap::iterator, bool> insert_result =
task_queue_throttler_->queue_details_.insert(
std::make_pair(queue, TaskQueueThrottler::Metadata()));
TaskQueueThrottler::Metadata& metadata = insert_result.first->second;
DCHECK(!metadata.time_budget_pool);
metadata.time_budget_pool = this;
associated_task_queues_.insert(queue);
if (!is_enabled_ || !task_queue_throttler_->IsThrottled(queue))
return;
queue->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME);
task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, now, queue,
GetNextAllowedRunTime());
}
void CPUTimeBudgetPool::RemoveQueue(base::TimeTicks now, TaskQueue* queue) {
auto find_it = task_queue_throttler_->queue_details_.find(queue);
DCHECK(find_it != task_queue_throttler_->queue_details_.end() &&
find_it->second.time_budget_pool == this);
find_it->second.time_budget_pool = nullptr;
bool is_throttled = task_queue_throttler_->IsThrottled(queue);
task_queue_throttler_->MaybeDeleteQueueMetadata(find_it);
associated_task_queues_.erase(queue);
if (!is_enabled_ || !is_throttled)
return;
task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, now, queue,
base::nullopt);
}
void CPUTimeBudgetPool::EnableThrottling(LazyNow* lazy_now) {
if (is_enabled_)
return;
is_enabled_ = true;
TRACE_EVENT0(task_queue_throttler_->tracing_category_,
"CPUTimeBudgetPool_EnableThrottling");
BlockThrottledQueues(lazy_now->Now());
}
void CPUTimeBudgetPool::DisableThrottling(LazyNow* lazy_now) {
if (!is_enabled_)
return;
is_enabled_ = false;
TRACE_EVENT0(task_queue_throttler_->tracing_category_,
"CPUTimeBudgetPool_DisableThrottling");
for (TaskQueue* queue : associated_task_queues_) {
if (!task_queue_throttler_->IsThrottled(queue))
continue;
task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, lazy_now->Now(),
queue, base::nullopt);
}
// TODO(altimin): We need to disable TimeBudgetQueues here or they will
// regenerate extra time budget when they are disabled.
}
bool CPUTimeBudgetPool::IsThrottlingEnabled() const {
return is_enabled_;
}
void CPUTimeBudgetPool::GrantAdditionalBudget(base::TimeTicks now,
base::TimeDelta budget_level) {
Advance(now);
current_budget_level_ += budget_level;
EnforceBudgetLevelRestrictions();
}
void CPUTimeBudgetPool::SetReportingCallback(
base::Callback<void(base::TimeDelta)> reporting_callback) {
reporting_callback_ = reporting_callback;
}
void CPUTimeBudgetPool::Close() {
DCHECK_EQ(0u, associated_task_queues_.size());
task_queue_throttler_->time_budget_pools_.erase(this);
}
bool CPUTimeBudgetPool::HasEnoughBudgetToRun(base::TimeTicks now) {
Advance(now);
return !is_enabled_ || current_budget_level_.InMicroseconds() >= 0;
}
base::TimeTicks CPUTimeBudgetPool::GetNextAllowedRunTime() {
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 CPUTimeBudgetPool::RecordTaskRunTime(base::TimeTicks start_time,
base::TimeTicks end_time) {
DCHECK_LE(start_time, end_time);
Advance(end_time);
if (is_enabled_) {
base::TimeDelta old_budget_level = current_budget_level_;
current_budget_level_ -= (end_time - start_time);
EnforceBudgetLevelRestrictions();
if (!reporting_callback_.is_null() && old_budget_level.InSecondsF() > 0 &&
current_budget_level_.InSecondsF() < 0) {
reporting_callback_.Run(-current_budget_level_ / cpu_percentage_);
}
}
}
const char* CPUTimeBudgetPool::Name() const {
return name_;
}
void CPUTimeBudgetPool::AsValueInto(base::trace_event::TracedValue* state,
base::TimeTicks now) const {
state->BeginDictionary(name_);
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->SetBoolean("is_enabled", is_enabled_);
state->BeginArray("task_queues");
for (TaskQueue* queue : associated_task_queues_) {
state->AppendString(PointerToId(queue));
}
state->EndArray();
state->EndDictionary();
}
void CPUTimeBudgetPool::Advance(base::TimeTicks now) {
if (now > last_checkpoint_) {
if (is_enabled_) {
current_budget_level_ += cpu_percentage_ * (now - last_checkpoint_);
EnforceBudgetLevelRestrictions();
}
last_checkpoint_ = now;
}
}
void CPUTimeBudgetPool::BlockThrottledQueues(base::TimeTicks now) {
for (TaskQueue* queue : associated_task_queues_) {
if (!task_queue_throttler_->IsThrottled(queue))
continue;
queue->InsertFence(TaskQueue::InsertFencePosition::BEGINNING_OF_TIME);
task_queue_throttler_->MaybeSchedulePumpQueue(FROM_HERE, now, queue,
base::nullopt);
}
}
void CPUTimeBudgetPool::EnforceBudgetLevelRestrictions() {
if (max_budget_level_) {
current_budget_level_ =
std::min(current_budget_level_, max_budget_level_.value());
}
if (max_throttling_duration_) {
// Current budget level may be negative.
current_budget_level_ =
std::max(current_budget_level_,
-max_throttling_duration_.value() * cpu_percentage_);
}
}
} // namespace scheduler
} // namespace blink
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_BUDGET_POOL_H_
#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_BUDGET_POOL_H_
#include <unordered_set>
#include "base/callback.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/optional.h"
#include "base/time/time.h"
#include "platform/scheduler/base/lazy_now.h"
namespace base {
namespace trace_event {
class TracedValue;
}
}
namespace blink {
namespace scheduler {
class TaskQueue;
class TaskQueueThrottler;
// BudgetPool represents a group of task queues which share a limit
// on a resource. This limit applies when task queues are already throttled
// by TaskQueueThrottler.
class BLINK_PLATFORM_EXPORT BudgetPool {
public:
virtual ~BudgetPool();
virtual const char* Name() const = 0;
// Adds |queue| to given pool. If the pool restriction does not allow
// a task to be run immediately and |queue| is throttled, |queue| becomes
// disabled.
virtual void AddQueue(base::TimeTicks now, TaskQueue* queue) = 0;
// Removes |queue| from given pool. If it is throttled, it does not
// become enabled immediately, but a call to |PumpThrottledTasks|
// is scheduled.
virtual void RemoveQueue(base::TimeTicks now, TaskQueue* queue) = 0;
// Enables this time budget pool. Queues from this pool will be
// throttled based on their run time.
virtual void EnableThrottling(LazyNow* now) = 0;
// Disables with time budget pool. Queues from this pool will not be
// throttled based on their run time. A call to |PumpThrottledTasks|
// will be scheduled to enable this queues back again and respect
// timer alignment. Internal budget level will not regenerate with time.
virtual void DisableThrottling(LazyNow* now) = 0;
virtual bool IsThrottlingEnabled() const = 0;
// Report task run time to the budget pool.
virtual void RecordTaskRunTime(base::TimeTicks start_time,
base::TimeTicks end_time) = 0;
// All queues should be removed before calling Close().
virtual void Close() = 0;
// Retuns earliest time (can be in the past) when the next task can run.
virtual base::TimeTicks GetNextAllowedRunTime() = 0;
// Returns true at a task can be run immediately at the given time.
virtual bool HasEnoughBudgetToRun(base::TimeTicks now) = 0;
// Returns state for tracing.
virtual void AsValueInto(base::trace_event::TracedValue* state,
base::TimeTicks now) const = 0;
};
// CPUTimeBudgetPool represents a collection of task queues which share a limit
// on total cpu time.
class BLINK_PLATFORM_EXPORT CPUTimeBudgetPool : public BudgetPool {
public:
~CPUTimeBudgetPool();
// Throttle task queues from this time budget pool if tasks are running
// for more than |cpu_percentage| per cent of wall time.
// This function does not affect internal time budget level.
void SetTimeBudgetRecoveryRate(base::TimeTicks now, double cpu_percentage);
// Increase budget level by given value. This function DOES NOT unblock
// queues even if they are allowed to run with increased budget level.
void GrantAdditionalBudget(base::TimeTicks now, base::TimeDelta budget_level);
// Set callback which will be called every time when this budget pool
// is throttled. Throttling duration (time until the queue is allowed
// to run again) is passed as a parameter to callback.
void SetReportingCallback(
base::Callback<void(base::TimeDelta)> reporting_callback);
// BudgetPool implementation:
const char* Name() const override;
void AddQueue(base::TimeTicks now, TaskQueue* queue) override;
void RemoveQueue(base::TimeTicks now, TaskQueue* queue) override;
void EnableThrottling(LazyNow* now) override;
void DisableThrottling(LazyNow* now) override;
bool IsThrottlingEnabled() const override;
void RecordTaskRunTime(base::TimeTicks start_time,
base::TimeTicks end_time) override;
void Close() override;
bool HasEnoughBudgetToRun(base::TimeTicks now) override;
base::TimeTicks GetNextAllowedRunTime() override;
void AsValueInto(base::trace_event::TracedValue* state,
base::TimeTicks now) const override;
private:
friend class TaskQueueThrottler;
FRIEND_TEST_ALL_PREFIXES(TaskQueueThrottlerTest, CPUTimeBudgetPool);
CPUTimeBudgetPool(const char* name,
TaskQueueThrottler* task_queue_throttler,
base::TimeTicks now,
base::Optional<base::TimeDelta> max_budget_level,
base::Optional<base::TimeDelta> max_throttling_duration);
// Advances |last_checkpoint_| to |now| if needed and recalculates
// budget level.
void Advance(base::TimeTicks now);
// Disable all associated throttled queues.
void BlockThrottledQueues(base::TimeTicks now);
// Increase |current_budget_level_| to satisfy max throttling duration
// condition if necessary.
// Decrease |current_budget_level_| to satisfy max budget level
// condition if necessary.
void EnforceBudgetLevelRestrictions();
const char* name_; // NOT OWNED
TaskQueueThrottler* task_queue_throttler_;
// Max budget level which we can accrue.
// Tasks will be allowed to run for this time before being throttled
// after a very long period of inactivity.
base::Optional<base::TimeDelta> max_budget_level_;
// Max throttling duration places a lower limit on time budget level,
// ensuring that one long task does not cause extremely long throttling.
// Note that this is not the guarantee that every task will run
// after desired run time + max throttling duration, but a guarantee
// that at least one task will be run every max_throttling_duration.
base::Optional<base::TimeDelta> max_throttling_duration_;
base::TimeDelta current_budget_level_;
base::TimeTicks last_checkpoint_;
double cpu_percentage_;
bool is_enabled_;
std::unordered_set<TaskQueue*> associated_task_queues_;
base::Callback<void(base::TimeDelta)> reporting_callback_;
DISALLOW_COPY_AND_ASSIGN(CPUTimeBudgetPool);
};
} // namespace scheduler
} // namespace blink
#endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_BUDGET_POOL_H_
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "platform/scheduler/renderer/task_queue_throttler.h"
#include <stddef.h>
#include <memory>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/test/simple_test_tick_clock.h"
#include "cc/test/ordered_simple_task_runner.h"
#include "platform/scheduler/base/task_queue_impl.h"
#include "platform/scheduler/base/test_time_source.h"
#include "platform/scheduler/child/scheduler_tqm_delegate_for_test.h"
#include "platform/scheduler/renderer/budget_pool.h"
#include "platform/scheduler/renderer/renderer_scheduler_impl.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace blink {
namespace scheduler {
class BudgetPoolTest : public testing::Test {
public:
BudgetPoolTest() {}
~BudgetPoolTest() override {}
void SetUp() override {
clock_.reset(new base::SimpleTestTickClock());
clock_->Advance(base::TimeDelta::FromMicroseconds(5000));
mock_task_runner_ =
make_scoped_refptr(new cc::OrderedSimpleTaskRunner(clock_.get(), true));
delegate_ = SchedulerTqmDelegateForTest::Create(
mock_task_runner_, base::MakeUnique<TestTimeSource>(clock_.get()));
scheduler_.reset(new RendererSchedulerImpl(delegate_));
task_queue_throttler_ = scheduler_->task_queue_throttler();
}
void TearDown() override {
scheduler_->Shutdown();
scheduler_.reset();
}
protected:
std::unique_ptr<base::SimpleTestTickClock> clock_;
scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
scoped_refptr<SchedulerTqmDelegate> delegate_;
std::unique_ptr<RendererSchedulerImpl> scheduler_;
TaskQueueThrottler* task_queue_throttler_; // NOT OWNED
DISALLOW_COPY_AND_ASSIGN(BudgetPoolTest);
};
TEST_F(BudgetPoolTest, CPUTimeBudgetPool) {
CPUTimeBudgetPool* pool = task_queue_throttler_->CreateCPUTimeBudgetPool(
"test", base::nullopt, base::nullopt);
base::TimeTicks time_zero = clock_->NowTicks();
pool->SetTimeBudgetRecoveryRate(time_zero, 0.1);
EXPECT_TRUE(pool->HasEnoughBudgetToRun(time_zero));
EXPECT_EQ(time_zero, pool->GetNextAllowedRunTime());
// Run an expensive task and make sure that we're throttled.
pool->RecordTaskRunTime(time_zero,
time_zero + base::TimeDelta::FromMilliseconds(100));
EXPECT_FALSE(pool->HasEnoughBudgetToRun(
time_zero + base::TimeDelta::FromMilliseconds(500)));
EXPECT_EQ(time_zero + base::TimeDelta::FromMilliseconds(1000),
pool->GetNextAllowedRunTime());
EXPECT_TRUE(pool->HasEnoughBudgetToRun(
time_zero + base::TimeDelta::FromMilliseconds(1000)));
// Run a cheap task and make sure that it doesn't affect anything.
EXPECT_TRUE(pool->HasEnoughBudgetToRun(
time_zero + base::TimeDelta::FromMilliseconds(2000)));
pool->RecordTaskRunTime(time_zero + base::TimeDelta::FromMilliseconds(2000),
time_zero + base::TimeDelta::FromMilliseconds(2020));
EXPECT_TRUE(pool->HasEnoughBudgetToRun(
time_zero + base::TimeDelta::FromMilliseconds(2020)));
EXPECT_EQ(time_zero + base::TimeDelta::FromMilliseconds(2020),
pool->GetNextAllowedRunTime());
pool->Close();
}
} // namespace scheduler
} // namespace blink
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "platform/scheduler/child/scheduler_tqm_delegate_for_test.h" #include "platform/scheduler/child/scheduler_tqm_delegate_for_test.h"
#include "platform/scheduler/child/scheduler_tqm_delegate_impl.h" #include "platform/scheduler/child/scheduler_tqm_delegate_impl.h"
#include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h" #include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h"
#include "platform/scheduler/renderer/budget_pool.h"
#include "platform/scheduler/renderer/web_frame_scheduler_impl.h" #include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -3697,8 +3698,8 @@ TEST_F(RendererSchedulerImplTest, Tracing) { ...@@ -3697,8 +3698,8 @@ TEST_F(RendererSchedulerImplTest, Tracing) {
new WebViewSchedulerImpl(nullptr, nullptr, scheduler_.get(), false)); new WebViewSchedulerImpl(nullptr, nullptr, scheduler_.get(), false));
scheduler_->AddWebViewScheduler(web_view_scheduler2.get()); scheduler_->AddWebViewScheduler(web_view_scheduler2.get());
TaskQueueThrottler::TimeBudgetPool* time_budget_pool = CPUTimeBudgetPool* time_budget_pool =
scheduler_->task_queue_throttler()->CreateTimeBudgetPool( scheduler_->task_queue_throttler()->CreateCPUTimeBudgetPool(
"test", base::nullopt, base::nullopt); "test", base::nullopt, base::nullopt);
time_budget_pool->AddQueue(base::TimeTicks(), time_budget_pool->AddQueue(base::TimeTicks(),
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_THROTTLING_HELPER_H_ #ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_TASK_QUEUE_THROTTLER_H_
#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_THROTTLING_HELPER_H_ #define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_TASK_QUEUE_THROTTLER_H_
#include <set> #include <set>
#include <unordered_map> #include <unordered_map>
...@@ -16,16 +16,24 @@ ...@@ -16,16 +16,24 @@
#include "platform/scheduler/base/time_domain.h" #include "platform/scheduler/base/time_domain.h"
#include "public/platform/WebViewScheduler.h" #include "public/platform/WebViewScheduler.h"
namespace base {
namespace trace_event {
class TracedValue;
}
}
namespace blink { namespace blink {
namespace scheduler { namespace scheduler {
class BudgetPool;
class RendererSchedulerImpl; class RendererSchedulerImpl;
class ThrottledTimeDomain; class ThrottledTimeDomain;
class CPUTimeBudgetPool;
// The job of the TaskQueueThrottler is to control when tasks posted on // The job of the TaskQueueThrottler is to control when tasks posted on
// throttled queues get run. The TaskQueueThrottler: // throttled queues get run. The TaskQueueThrottler:
// - runs throttled tasks once per second, // - runs throttled tasks once per second,
// - controls time budget for task queues grouped in TimeBudgetPools. // - controls time budget for task queues grouped in CPUTimeBudgetPools.
// //
// This is done by disabling throttled queues and running // This is done by disabling throttled queues and running
// a special "heart beat" function |PumpThrottledTasks| which when run // a special "heart beat" function |PumpThrottledTasks| which when run
...@@ -46,117 +54,6 @@ class ThrottledTimeDomain; ...@@ -46,117 +54,6 @@ class ThrottledTimeDomain;
// This class is main-thread only. // This class is main-thread only.
class BLINK_PLATFORM_EXPORT TaskQueueThrottler : public TimeDomain::Observer { class BLINK_PLATFORM_EXPORT TaskQueueThrottler : public TimeDomain::Observer {
public: public:
// TimeBudgetPool represents a group of task queues which share a limit
// on execution time. This limit applies when task queues are already
// throttled by TaskQueueThrottler.
class BLINK_PLATFORM_EXPORT TimeBudgetPool {
public:
~TimeBudgetPool();
// Throttle task queues from this time budget pool if tasks are running
// for more than |cpu_percentage| per cent of wall time.
// This function does not affect internal time budget level.
void SetTimeBudgetRecoveryRate(base::TimeTicks now, double cpu_percentage);
// Adds |queue| to given pool. If the pool restriction does not allow
// a task to be run immediately and |queue| is throttled, |queue| becomes
// disabled.
void AddQueue(base::TimeTicks now, TaskQueue* queue);
// Removes |queue| from given pool. If it is throttled, it does not
// become enabled immediately, but a call to |PumpThrottledTasks|
// is scheduled.
void RemoveQueue(base::TimeTicks now, TaskQueue* queue);
void RecordTaskRunTime(base::TimeTicks start_time,
base::TimeTicks end_time);
// Enables this time budget pool. Queues from this pool will be
// throttled based on their run time.
void EnableThrottling(LazyNow* now);
// Disables with time budget pool. Queues from this pool will not be
// throttled based on their run time. A call to |PumpThrottledTasks|
// will be scheduled to enable this queues back again and respect
// timer alignment. Internal budget level will not regenerate with time.
void DisableThrottling(LazyNow* now);
bool IsThrottlingEnabled() const;
// Increase budget level by given value. This function DOES NOT unblock
// queues even if they are allowed to run with increased budget level.
void GrantAdditionalBudget(base::TimeTicks now,
base::TimeDelta budget_level);
const char* Name() const;
// Set callback which will be called every time when this budget pool
// is throttled. Throttling duration (time until the queue is allowed
// to run again) is passed as a parameter to callback.
void SetReportingCallback(
base::Callback<void(base::TimeDelta)> reporting_callback);
// All queues should be removed before calling Close().
void Close();
private:
friend class TaskQueueThrottler;
FRIEND_TEST_ALL_PREFIXES(TaskQueueThrottlerTest, TimeBudgetPool);
TimeBudgetPool(const char* name,
TaskQueueThrottler* task_queue_throttler,
base::TimeTicks now,
base::Optional<base::TimeDelta> max_budget_level,
base::Optional<base::TimeDelta> max_throttling_duration);
bool HasEnoughBudgetToRun(base::TimeTicks now);
base::TimeTicks GetNextAllowedRunTime();
// Advances |last_checkpoint_| to |now| if needed and recalculates
// budget level.
void Advance(base::TimeTicks now);
// Returns state for tracing.
void AsValueInto(base::trace_event::TracedValue* state,
base::TimeTicks now) const;
// Disable all associated throttled queues.
void BlockThrottledQueues(base::TimeTicks now);
// Increase |current_budget_level_| to satisfy max throttling duration
// condition if necessary.
// Decrease |current_budget_level_| to satisfy max budget level
// condition if necessary.
void EnforceBudgetLevelRestrictions();
const char* name_; // NOT OWNED
TaskQueueThrottler* task_queue_throttler_;
// Max budget level which we can accrue.
// Tasks will be allowed to run for this time before being throttled
// after a very long period of inactivity.
base::Optional<base::TimeDelta> max_budget_level_;
// Max throttling duration places a lower limit on time budget level,
// ensuring that one long task does not cause extremely long throttling.
// Note that this is not the guarantee that every task will run
// after desired run time + max throttling duration, but a guarantee
// that at least one task will be run every max_throttling_duration.
base::Optional<base::TimeDelta> max_throttling_duration_;
base::TimeDelta current_budget_level_;
base::TimeTicks last_checkpoint_;
double cpu_percentage_;
bool is_enabled_;
std::unordered_set<TaskQueue*> associated_task_queues_;
base::Callback<void(base::TimeDelta)> reporting_callback_;
DISALLOW_COPY_AND_ASSIGN(TimeBudgetPool);
};
// TODO(altimin): Do not pass tracing category as const char*, // TODO(altimin): Do not pass tracing category as const char*,
// hard-code string instead. // hard-code string instead.
TaskQueueThrottler(RendererSchedulerImpl* renderer_scheduler, TaskQueueThrottler(RendererSchedulerImpl* renderer_scheduler,
...@@ -199,7 +96,7 @@ class BLINK_PLATFORM_EXPORT TaskQueueThrottler : public TimeDomain::Observer { ...@@ -199,7 +96,7 @@ class BLINK_PLATFORM_EXPORT TaskQueueThrottler : public TimeDomain::Observer {
const scoped_refptr<TaskQueue>& task_runner() const { return task_runner_; } const scoped_refptr<TaskQueue>& task_runner() const { return task_runner_; }
// Returned object is owned by |TaskQueueThrottler|. // Returned object is owned by |TaskQueueThrottler|.
TimeBudgetPool* CreateTimeBudgetPool( CPUTimeBudgetPool* CreateCPUTimeBudgetPool(
const char* name, const char* name,
base::Optional<base::TimeDelta> max_budget_level, base::Optional<base::TimeDelta> max_budget_level,
base::Optional<base::TimeDelta> max_throttling_duration); base::Optional<base::TimeDelta> max_throttling_duration);
...@@ -213,12 +110,15 @@ class BLINK_PLATFORM_EXPORT TaskQueueThrottler : public TimeDomain::Observer { ...@@ -213,12 +110,15 @@ class BLINK_PLATFORM_EXPORT TaskQueueThrottler : public TimeDomain::Observer {
base::TimeTicks now) const; base::TimeTicks now) const;
private: private:
friend class BudgetPool;
friend class CPUTimeBudgetPool;
struct Metadata { struct Metadata {
Metadata() : throttling_ref_count(0), time_budget_pool(nullptr) {} Metadata() : throttling_ref_count(0), time_budget_pool(nullptr) {}
size_t throttling_ref_count; size_t throttling_ref_count;
TimeBudgetPool* time_budget_pool; CPUTimeBudgetPool* time_budget_pool;
}; };
using TaskQueueMap = std::unordered_map<TaskQueue*, Metadata>; using TaskQueueMap = std::unordered_map<TaskQueue*, Metadata>;
...@@ -232,7 +132,7 @@ class BLINK_PLATFORM_EXPORT TaskQueueThrottler : public TimeDomain::Observer { ...@@ -232,7 +132,7 @@ class BLINK_PLATFORM_EXPORT TaskQueueThrottler : public TimeDomain::Observer {
base::TimeTicks now, base::TimeTicks now,
base::TimeTicks runtime); base::TimeTicks runtime);
TimeBudgetPool* GetTimeBudgetPoolForQueue(TaskQueue* queue); CPUTimeBudgetPool* GetTimeBudgetPoolForQueue(TaskQueue* queue);
// Schedule pumping because of given task queue. // Schedule pumping because of given task queue.
void MaybeSchedulePumpQueue( void MaybeSchedulePumpQueue(
...@@ -259,7 +159,7 @@ class BLINK_PLATFORM_EXPORT TaskQueueThrottler : public TimeDomain::Observer { ...@@ -259,7 +159,7 @@ class BLINK_PLATFORM_EXPORT TaskQueueThrottler : public TimeDomain::Observer {
base::Optional<base::TimeTicks> pending_pump_throttled_tasks_runtime_; base::Optional<base::TimeTicks> pending_pump_throttled_tasks_runtime_;
bool allow_throttling_; bool allow_throttling_;
std::unordered_map<TimeBudgetPool*, std::unique_ptr<TimeBudgetPool>> std::unordered_map<BudgetPool*, std::unique_ptr<BudgetPool>>
time_budget_pools_; time_budget_pools_;
base::WeakPtrFactory<TaskQueueThrottler> weak_factory_; base::WeakPtrFactory<TaskQueueThrottler> weak_factory_;
...@@ -270,4 +170,4 @@ class BLINK_PLATFORM_EXPORT TaskQueueThrottler : public TimeDomain::Observer { ...@@ -270,4 +170,4 @@ class BLINK_PLATFORM_EXPORT TaskQueueThrottler : public TimeDomain::Observer {
} // namespace scheduler } // namespace scheduler
} // namespace blink } // namespace blink
#endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_THROTTLING_HELPER_H_ #endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_TASK_QUEUE_THROTTLER_H_
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "platform/scheduler/base/test_time_source.h" #include "platform/scheduler/base/test_time_source.h"
#include "platform/scheduler/child/scheduler_tqm_delegate_for_test.h" #include "platform/scheduler/child/scheduler_tqm_delegate_for_test.h"
#include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h" #include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h"
#include "platform/scheduler/renderer/budget_pool.h"
#include "platform/scheduler/renderer/renderer_scheduler_impl.h" #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
#include "platform/scheduler/renderer/web_frame_scheduler_impl.h" #include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
#include "platform/scheduler/renderer/web_view_scheduler_impl.h" #include "platform/scheduler/renderer/web_view_scheduler_impl.h"
...@@ -491,42 +492,6 @@ TEST_F(TaskQueueThrottlerTest, IncrementThenEnableVirtualTime) { ...@@ -491,42 +492,6 @@ TEST_F(TaskQueueThrottlerTest, IncrementThenEnableVirtualTime) {
EXPECT_EQ(timer_queue_->GetTimeDomain(), scheduler_->GetVirtualTimeDomain()); EXPECT_EQ(timer_queue_->GetTimeDomain(), scheduler_->GetVirtualTimeDomain());
} }
TEST_F(TaskQueueThrottlerTest, TimeBudgetPool) {
TaskQueueThrottler::TimeBudgetPool* pool =
task_queue_throttler_->CreateTimeBudgetPool("test", base::nullopt,
base::nullopt);
base::TimeTicks time_zero = clock_->NowTicks();
pool->SetTimeBudgetRecoveryRate(time_zero, 0.1);
EXPECT_TRUE(pool->HasEnoughBudgetToRun(time_zero));
EXPECT_EQ(time_zero, pool->GetNextAllowedRunTime());
// Run an expensive task and make sure that we're throttled.
pool->RecordTaskRunTime(time_zero,
time_zero + base::TimeDelta::FromMilliseconds(100));
EXPECT_FALSE(pool->HasEnoughBudgetToRun(
time_zero + base::TimeDelta::FromMilliseconds(500)));
EXPECT_EQ(time_zero + base::TimeDelta::FromMilliseconds(1000),
pool->GetNextAllowedRunTime());
EXPECT_TRUE(pool->HasEnoughBudgetToRun(
time_zero + base::TimeDelta::FromMilliseconds(1000)));
// Run a cheap task and make sure that it doesn't affect anything.
EXPECT_TRUE(pool->HasEnoughBudgetToRun(
time_zero + base::TimeDelta::FromMilliseconds(2000)));
pool->RecordTaskRunTime(time_zero + base::TimeDelta::FromMilliseconds(2000),
time_zero + base::TimeDelta::FromMilliseconds(2020));
EXPECT_TRUE(pool->HasEnoughBudgetToRun(
time_zero + base::TimeDelta::FromMilliseconds(2020)));
EXPECT_EQ(time_zero + base::TimeDelta::FromMilliseconds(2020),
pool->GetNextAllowedRunTime());
pool->Close();
}
namespace { namespace {
void ExpensiveTestTask(std::vector<base::TimeTicks>* run_times, void ExpensiveTestTask(std::vector<base::TimeTicks>* run_times,
...@@ -540,9 +505,8 @@ void ExpensiveTestTask(std::vector<base::TimeTicks>* run_times, ...@@ -540,9 +505,8 @@ void ExpensiveTestTask(std::vector<base::TimeTicks>* run_times,
TEST_F(TaskQueueThrottlerTest, TimeBasedThrottling) { TEST_F(TaskQueueThrottlerTest, TimeBasedThrottling) {
std::vector<base::TimeTicks> run_times; std::vector<base::TimeTicks> run_times;
TaskQueueThrottler::TimeBudgetPool* pool = CPUTimeBudgetPool* pool = task_queue_throttler_->CreateCPUTimeBudgetPool(
task_queue_throttler_->CreateTimeBudgetPool("test", base::nullopt, "test", base::nullopt, base::nullopt);
base::nullopt);
pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1); pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
pool->AddQueue(base::TimeTicks(), timer_queue_.get()); pool->AddQueue(base::TimeTicks(), timer_queue_.get());
...@@ -567,7 +531,7 @@ TEST_F(TaskQueueThrottlerTest, TimeBasedThrottling) { ...@@ -567,7 +531,7 @@ TEST_F(TaskQueueThrottlerTest, TimeBasedThrottling) {
pool->RemoveQueue(clock_->NowTicks(), timer_queue_.get()); pool->RemoveQueue(clock_->NowTicks(), timer_queue_.get());
run_times.clear(); run_times.clear();
// Queue was removed from TimeBudgetPool, only timer alignment should be // Queue was removed from CPUTimeBudgetPool, only timer alignment should be
// active now. // active now.
timer_queue_->PostDelayedTask( timer_queue_->PostDelayedTask(
FROM_HERE, base::Bind(&ExpensiveTestTask, &run_times, clock_.get()), FROM_HERE, base::Bind(&ExpensiveTestTask, &run_times, clock_.get()),
...@@ -587,12 +551,11 @@ TEST_F(TaskQueueThrottlerTest, TimeBasedThrottling) { ...@@ -587,12 +551,11 @@ TEST_F(TaskQueueThrottlerTest, TimeBasedThrottling) {
pool->Close(); pool->Close();
} }
TEST_F(TaskQueueThrottlerTest, EnableAndDisableTimeBudgetPool) { TEST_F(TaskQueueThrottlerTest, EnableAndDisableCPUTimeBudgetPool) {
std::vector<base::TimeTicks> run_times; std::vector<base::TimeTicks> run_times;
TaskQueueThrottler::TimeBudgetPool* pool = CPUTimeBudgetPool* pool = task_queue_throttler_->CreateCPUTimeBudgetPool(
task_queue_throttler_->CreateTimeBudgetPool("test", base::nullopt, "test", base::nullopt, base::nullopt);
base::nullopt);
EXPECT_TRUE(pool->IsThrottlingEnabled()); EXPECT_TRUE(pool->IsThrottlingEnabled());
pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1); pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
...@@ -651,9 +614,8 @@ TEST_F(TaskQueueThrottlerTest, EnableAndDisableTimeBudgetPool) { ...@@ -651,9 +614,8 @@ TEST_F(TaskQueueThrottlerTest, EnableAndDisableTimeBudgetPool) {
TEST_F(TaskQueueThrottlerTest, ImmediateTasksTimeBudgetThrottling) { TEST_F(TaskQueueThrottlerTest, ImmediateTasksTimeBudgetThrottling) {
std::vector<base::TimeTicks> run_times; std::vector<base::TimeTicks> run_times;
TaskQueueThrottler::TimeBudgetPool* pool = CPUTimeBudgetPool* pool = task_queue_throttler_->CreateCPUTimeBudgetPool(
task_queue_throttler_->CreateTimeBudgetPool("test", base::nullopt, "test", base::nullopt, base::nullopt);
base::nullopt);
pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1); pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
pool->AddQueue(base::TimeTicks(), timer_queue_.get()); pool->AddQueue(base::TimeTicks(), timer_queue_.get());
...@@ -676,7 +638,7 @@ TEST_F(TaskQueueThrottlerTest, ImmediateTasksTimeBudgetThrottling) { ...@@ -676,7 +638,7 @@ TEST_F(TaskQueueThrottlerTest, ImmediateTasksTimeBudgetThrottling) {
pool->RemoveQueue(clock_->NowTicks(), timer_queue_.get()); pool->RemoveQueue(clock_->NowTicks(), timer_queue_.get());
run_times.clear(); run_times.clear();
// Queue was removed from TimeBudgetPool, only timer alignment should be // Queue was removed from CPUTimeBudgetPool, only timer alignment should be
// active now. // active now.
timer_queue_->PostTask( timer_queue_->PostTask(
FROM_HERE, base::Bind(&ExpensiveTestTask, &run_times, clock_.get())); FROM_HERE, base::Bind(&ExpensiveTestTask, &run_times, clock_.get()));
...@@ -700,9 +662,8 @@ TEST_F(TaskQueueThrottlerTest, TwoQueuesTimeBudgetThrottling) { ...@@ -700,9 +662,8 @@ TEST_F(TaskQueueThrottlerTest, TwoQueuesTimeBudgetThrottling) {
scoped_refptr<TaskQueue> second_queue = scoped_refptr<TaskQueue> second_queue =
scheduler_->NewTimerTaskRunner(TaskQueue::QueueType::TEST); scheduler_->NewTimerTaskRunner(TaskQueue::QueueType::TEST);
TaskQueueThrottler::TimeBudgetPool* pool = CPUTimeBudgetPool* pool = task_queue_throttler_->CreateCPUTimeBudgetPool(
task_queue_throttler_->CreateTimeBudgetPool("test", base::nullopt, "test", base::nullopt, base::nullopt);
base::nullopt);
pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1); pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
pool->AddQueue(base::TimeTicks(), timer_queue_.get()); pool->AddQueue(base::TimeTicks(), timer_queue_.get());
...@@ -735,9 +696,8 @@ TEST_F(TaskQueueThrottlerTest, DisabledTimeBudgetDoesNotAffectThrottledQueues) { ...@@ -735,9 +696,8 @@ TEST_F(TaskQueueThrottlerTest, DisabledTimeBudgetDoesNotAffectThrottledQueues) {
std::vector<base::TimeTicks> run_times; std::vector<base::TimeTicks> run_times;
LazyNow lazy_now(clock_.get()); LazyNow lazy_now(clock_.get());
TaskQueueThrottler::TimeBudgetPool* pool = CPUTimeBudgetPool* pool = task_queue_throttler_->CreateCPUTimeBudgetPool(
task_queue_throttler_->CreateTimeBudgetPool("test", base::nullopt, "test", base::nullopt, base::nullopt);
base::nullopt);
pool->SetTimeBudgetRecoveryRate(lazy_now.Now(), 0.1); pool->SetTimeBudgetRecoveryRate(lazy_now.Now(), 0.1);
pool->DisableThrottling(&lazy_now); pool->DisableThrottling(&lazy_now);
...@@ -764,9 +724,8 @@ TEST_F(TaskQueueThrottlerTest, ...@@ -764,9 +724,8 @@ TEST_F(TaskQueueThrottlerTest,
TimeBudgetThrottlingDoesNotAffectUnthrottledQueues) { TimeBudgetThrottlingDoesNotAffectUnthrottledQueues) {
std::vector<base::TimeTicks> run_times; std::vector<base::TimeTicks> run_times;
TaskQueueThrottler::TimeBudgetPool* pool = CPUTimeBudgetPool* pool = task_queue_throttler_->CreateCPUTimeBudgetPool(
task_queue_throttler_->CreateTimeBudgetPool("test", base::nullopt, "test", base::nullopt, base::nullopt);
base::nullopt);
pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1); pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
LazyNow lazy_now(clock_.get()); LazyNow lazy_now(clock_.get());
...@@ -792,9 +751,8 @@ TEST_F(TaskQueueThrottlerTest, ...@@ -792,9 +751,8 @@ TEST_F(TaskQueueThrottlerTest,
TEST_F(TaskQueueThrottlerTest, MaxThrottlingDuration) { TEST_F(TaskQueueThrottlerTest, MaxThrottlingDuration) {
std::vector<base::TimeTicks> run_times; std::vector<base::TimeTicks> run_times;
TaskQueueThrottler::TimeBudgetPool* pool = CPUTimeBudgetPool* pool = task_queue_throttler_->CreateCPUTimeBudgetPool(
task_queue_throttler_->CreateTimeBudgetPool( "test", base::nullopt, base::TimeDelta::FromMinutes(1));
"test", base::nullopt, base::TimeDelta::FromMinutes(1));
pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.001); pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.001);
pool->AddQueue(base::TimeTicks(), timer_queue_.get()); pool->AddQueue(base::TimeTicks(), timer_queue_.get());
...@@ -893,9 +851,8 @@ TEST_F(TaskQueueThrottlerTest, ReportThrottling) { ...@@ -893,9 +851,8 @@ TEST_F(TaskQueueThrottlerTest, ReportThrottling) {
std::vector<base::TimeTicks> run_times; std::vector<base::TimeTicks> run_times;
std::vector<base::TimeDelta> reported_throttling_times; std::vector<base::TimeDelta> reported_throttling_times;
TaskQueueThrottler::TimeBudgetPool* pool = CPUTimeBudgetPool* pool = task_queue_throttler_->CreateCPUTimeBudgetPool(
task_queue_throttler_->CreateTimeBudgetPool("test", base::nullopt, "test", base::nullopt, base::nullopt);
base::nullopt);
pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1); pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
pool->AddQueue(base::TimeTicks(), timer_queue_.get()); pool->AddQueue(base::TimeTicks(), timer_queue_.get());
...@@ -934,9 +891,8 @@ TEST_F(TaskQueueThrottlerTest, ReportThrottling) { ...@@ -934,9 +891,8 @@ TEST_F(TaskQueueThrottlerTest, ReportThrottling) {
TEST_F(TaskQueueThrottlerTest, GrantAdditionalBudget) { TEST_F(TaskQueueThrottlerTest, GrantAdditionalBudget) {
std::vector<base::TimeTicks> run_times; std::vector<base::TimeTicks> run_times;
TaskQueueThrottler::TimeBudgetPool* pool = CPUTimeBudgetPool* pool = task_queue_throttler_->CreateCPUTimeBudgetPool(
task_queue_throttler_->CreateTimeBudgetPool("test", base::nullopt, "test", base::nullopt, base::nullopt);
base::nullopt);
pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1); pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
pool->AddQueue(base::TimeTicks(), timer_queue_.get()); pool->AddQueue(base::TimeTicks(), timer_queue_.get());
...@@ -975,9 +931,8 @@ TEST_F(TaskQueueThrottlerTest, EnableAndDisableThrottlingAndTimeBudgets) { ...@@ -975,9 +931,8 @@ TEST_F(TaskQueueThrottlerTest, EnableAndDisableThrottlingAndTimeBudgets) {
task_queue_throttler_->DisableThrottling(); task_queue_throttler_->DisableThrottling();
TaskQueueThrottler::TimeBudgetPool* pool = CPUTimeBudgetPool* pool = task_queue_throttler_->CreateCPUTimeBudgetPool(
task_queue_throttler_->CreateTimeBudgetPool("test", base::nullopt, "test", base::nullopt, base::nullopt);
base::nullopt);
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get()); task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
LazyNow lazy_now(clock_.get()); LazyNow lazy_now(clock_.get());
...@@ -1008,9 +963,8 @@ TEST_F(TaskQueueThrottlerTest, AddQueueToBudgetPoolWhenThrottlingDisabled) { ...@@ -1008,9 +963,8 @@ TEST_F(TaskQueueThrottlerTest, AddQueueToBudgetPoolWhenThrottlingDisabled) {
task_queue_throttler_->DisableThrottling(); task_queue_throttler_->DisableThrottling();
TaskQueueThrottler::TimeBudgetPool* pool = CPUTimeBudgetPool* pool = task_queue_throttler_->CreateCPUTimeBudgetPool(
task_queue_throttler_->CreateTimeBudgetPool("test", base::nullopt, "test", base::nullopt, base::nullopt);
base::nullopt);
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get()); task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
mock_task_runner_->RunUntilTime(base::TimeTicks() + mock_task_runner_->RunUntilTime(base::TimeTicks() +
......
...@@ -6,13 +6,14 @@ ...@@ -6,13 +6,14 @@
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/trace_event/blame_context.h" #include "base/trace_event/blame_context.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/scheduler/base/real_time_domain.h" #include "platform/scheduler/base/real_time_domain.h"
#include "platform/scheduler/base/virtual_time_domain.h" #include "platform/scheduler/base/virtual_time_domain.h"
#include "platform/scheduler/child/web_task_runner_impl.h" #include "platform/scheduler/child/web_task_runner_impl.h"
#include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h" #include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h"
#include "platform/scheduler/renderer/budget_pool.h"
#include "platform/scheduler/renderer/renderer_scheduler_impl.h" #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
#include "platform/scheduler/renderer/web_view_scheduler_impl.h" #include "platform/scheduler/renderer/web_view_scheduler_impl.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "public/platform/BlameContext.h" #include "public/platform/BlameContext.h"
#include "public/platform/WebString.h" #include "public/platform/WebString.h"
...@@ -63,7 +64,7 @@ WebFrameSchedulerImpl::~WebFrameSchedulerImpl() { ...@@ -63,7 +64,7 @@ WebFrameSchedulerImpl::~WebFrameSchedulerImpl() {
} }
if (timer_task_queue_) { if (timer_task_queue_) {
RemoveTimerQueueFromBackgroundTimeBudgetPool(); RemoveTimerQueueFromBackgroundCPUTimeBudgetPool();
timer_task_queue_->UnregisterTaskQueue(); timer_task_queue_->UnregisterTaskQueue();
timer_task_queue_->SetBlameContext(nullptr); timer_task_queue_->SetBlameContext(nullptr);
} }
...@@ -82,20 +83,20 @@ WebFrameSchedulerImpl::~WebFrameSchedulerImpl() { ...@@ -82,20 +83,20 @@ WebFrameSchedulerImpl::~WebFrameSchedulerImpl() {
} }
void WebFrameSchedulerImpl::DetachFromWebViewScheduler() { void WebFrameSchedulerImpl::DetachFromWebViewScheduler() {
RemoveTimerQueueFromBackgroundTimeBudgetPool(); RemoveTimerQueueFromBackgroundCPUTimeBudgetPool();
parent_web_view_scheduler_ = nullptr; parent_web_view_scheduler_ = nullptr;
} }
void WebFrameSchedulerImpl::RemoveTimerQueueFromBackgroundTimeBudgetPool() { void WebFrameSchedulerImpl::RemoveTimerQueueFromBackgroundCPUTimeBudgetPool() {
if (!timer_task_queue_) if (!timer_task_queue_)
return; return;
if (!parent_web_view_scheduler_) if (!parent_web_view_scheduler_)
return; return;
TaskQueueThrottler::TimeBudgetPool* time_budget_pool = CPUTimeBudgetPool* time_budget_pool =
parent_web_view_scheduler_->BackgroundTimeBudgetPool(); parent_web_view_scheduler_->BackgroundCPUTimeBudgetPool();
if (!time_budget_pool) if (!time_budget_pool)
return; return;
...@@ -145,8 +146,8 @@ RefPtr<blink::WebTaskRunner> WebFrameSchedulerImpl::timerTaskRunner() { ...@@ -145,8 +146,8 @@ RefPtr<blink::WebTaskRunner> WebFrameSchedulerImpl::timerTaskRunner() {
timer_queue_enabled_voter_ = timer_task_queue_->CreateQueueEnabledVoter(); timer_queue_enabled_voter_ = timer_task_queue_->CreateQueueEnabledVoter();
timer_queue_enabled_voter_->SetQueueEnabled(!frame_suspended_); timer_queue_enabled_voter_->SetQueueEnabled(!frame_suspended_);
TaskQueueThrottler::TimeBudgetPool* time_budget_pool = CPUTimeBudgetPool* time_budget_pool =
parent_web_view_scheduler_->BackgroundTimeBudgetPool(); parent_web_view_scheduler_->BackgroundCPUTimeBudgetPool();
if (time_budget_pool) { if (time_budget_pool) {
time_budget_pool->AddQueue(renderer_scheduler_->tick_clock()->NowTicks(), time_budget_pool->AddQueue(renderer_scheduler_->tick_clock()->NowTicks(),
timer_task_queue_.get()); timer_task_queue_.get());
......
...@@ -72,7 +72,7 @@ class WebFrameSchedulerImpl : public WebFrameScheduler { ...@@ -72,7 +72,7 @@ class WebFrameSchedulerImpl : public WebFrameScheduler {
}; };
void DetachFromWebViewScheduler(); void DetachFromWebViewScheduler();
void RemoveTimerQueueFromBackgroundTimeBudgetPool(); void RemoveTimerQueueFromBackgroundCPUTimeBudgetPool();
void ApplyPolicyToTimerQueue(); void ApplyPolicyToTimerQueue();
bool ShouldThrottleTimers() const; bool ShouldThrottleTimers() const;
void UpdateTimerThrottling(bool was_throttled); void UpdateTimerThrottling(bool was_throttled);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "platform/scheduler/base/virtual_time_domain.h" #include "platform/scheduler/base/virtual_time_domain.h"
#include "platform/scheduler/child/scheduler_tqm_delegate.h" #include "platform/scheduler/child/scheduler_tqm_delegate.h"
#include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h" #include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h"
#include "platform/scheduler/renderer/budget_pool.h"
#include "platform/scheduler/renderer/renderer_scheduler_impl.h" #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
#include "platform/scheduler/renderer/web_frame_scheduler_impl.h" #include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
...@@ -142,7 +143,7 @@ void WebViewSchedulerImpl::setPageVisible(bool page_visible) { ...@@ -142,7 +143,7 @@ void WebViewSchedulerImpl::setPageVisible(bool page_visible) {
std::unique_ptr<WebFrameSchedulerImpl> std::unique_ptr<WebFrameSchedulerImpl>
WebViewSchedulerImpl::createWebFrameSchedulerImpl( WebViewSchedulerImpl::createWebFrameSchedulerImpl(
base::trace_event::BlameContext* blame_context) { base::trace_event::BlameContext* blame_context) {
MaybeInitializeBackgroundTimeBudgetPool(); MaybeInitializeBackgroundCPUTimeBudgetPool();
std::unique_ptr<WebFrameSchedulerImpl> frame_scheduler( std::unique_ptr<WebFrameSchedulerImpl> frame_scheduler(
new WebFrameSchedulerImpl(renderer_scheduler_, this, blame_context)); new WebFrameSchedulerImpl(renderer_scheduler_, this, blame_context));
frame_scheduler->setPageThrottled(should_throttle_frames_); frame_scheduler->setPageThrottled(should_throttle_frames_);
...@@ -298,13 +299,12 @@ void WebViewSchedulerImpl::AsValueInto( ...@@ -298,13 +299,12 @@ void WebViewSchedulerImpl::AsValueInto(
state->EndDictionary(); state->EndDictionary();
} }
TaskQueueThrottler::TimeBudgetPool* CPUTimeBudgetPool* WebViewSchedulerImpl::BackgroundCPUTimeBudgetPool() {
WebViewSchedulerImpl::BackgroundTimeBudgetPool() { MaybeInitializeBackgroundCPUTimeBudgetPool();
MaybeInitializeBackgroundTimeBudgetPool();
return background_time_budget_pool_; return background_time_budget_pool_;
} }
void WebViewSchedulerImpl::MaybeInitializeBackgroundTimeBudgetPool() { void WebViewSchedulerImpl::MaybeInitializeBackgroundCPUTimeBudgetPool() {
if (background_time_budget_pool_) if (background_time_budget_pool_)
return; return;
...@@ -312,7 +312,7 @@ void WebViewSchedulerImpl::MaybeInitializeBackgroundTimeBudgetPool() { ...@@ -312,7 +312,7 @@ void WebViewSchedulerImpl::MaybeInitializeBackgroundTimeBudgetPool() {
return; return;
background_time_budget_pool_ = background_time_budget_pool_ =
renderer_scheduler_->task_queue_throttler()->CreateTimeBudgetPool( renderer_scheduler_->task_queue_throttler()->CreateCPUTimeBudgetPool(
"background", GetMaxBudgetLevel(settings_), "background", GetMaxBudgetLevel(settings_),
GetMaxThrottlingDelay(settings_)); GetMaxThrottlingDelay(settings_));
......
...@@ -27,6 +27,7 @@ namespace blink { ...@@ -27,6 +27,7 @@ namespace blink {
namespace scheduler { namespace scheduler {
class RendererSchedulerImpl; class RendererSchedulerImpl;
class CPUTimeBudgetPool;
class WebFrameSchedulerImpl; class WebFrameSchedulerImpl;
class BLINK_PLATFORM_EXPORT WebViewSchedulerImpl : public WebViewScheduler { class BLINK_PLATFORM_EXPORT WebViewSchedulerImpl : public WebViewScheduler {
...@@ -71,8 +72,8 @@ class BLINK_PLATFORM_EXPORT WebViewSchedulerImpl : public WebViewScheduler { ...@@ -71,8 +72,8 @@ class BLINK_PLATFORM_EXPORT WebViewSchedulerImpl : public WebViewScheduler {
private: private:
friend class WebFrameSchedulerImpl; friend class WebFrameSchedulerImpl;
TaskQueueThrottler::TimeBudgetPool* BackgroundTimeBudgetPool(); CPUTimeBudgetPool* BackgroundCPUTimeBudgetPool();
void MaybeInitializeBackgroundTimeBudgetPool(); void MaybeInitializeBackgroundCPUTimeBudgetPool();
void setAllowVirtualTimeToAdvance(bool allow_virtual_time_to_advance); void setAllowVirtualTimeToAdvance(bool allow_virtual_time_to_advance);
void ApplyVirtualTimePolicy(); void ApplyVirtualTimePolicy();
...@@ -108,8 +109,7 @@ class BLINK_PLATFORM_EXPORT WebViewSchedulerImpl : public WebViewScheduler { ...@@ -108,8 +109,7 @@ class BLINK_PLATFORM_EXPORT WebViewSchedulerImpl : public WebViewScheduler {
bool is_audio_playing_; bool is_audio_playing_;
bool reported_background_throttling_since_navigation_; bool reported_background_throttling_since_navigation_;
bool has_active_connection_; bool has_active_connection_;
TaskQueueThrottler::TimeBudgetPool* CPUTimeBudgetPool* background_time_budget_pool_; // Not owned.
background_time_budget_pool_; // Not owned.
CancelableClosureHolder delayed_background_throttling_enabler_; CancelableClosureHolder delayed_background_throttling_enabler_;
WebViewScheduler::WebViewSchedulerSettings* settings_; // Not owned. WebViewScheduler::WebViewSchedulerSettings* settings_; // Not owned.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment