| Index: content/renderer/scheduler/task_queue_manager.cc
|
| diff --git a/content/renderer/scheduler/task_queue_manager.cc b/content/renderer/scheduler/task_queue_manager.cc
|
| index 658aef72060d83e03745f805ab7ac28cbd404f82..ac34e8d1033bb927bb7ea4ff113723e8973577ad 100644
|
| --- a/content/renderer/scheduler/task_queue_manager.cc
|
| +++ b/content/renderer/scheduler/task_queue_manager.cc
|
| @@ -6,6 +6,7 @@
|
|
|
| #include "base/bind.h"
|
| #include "base/debug/trace_event.h"
|
| +#include "base/debug/trace_event_argument.h"
|
| #include "content/renderer/scheduler/task_queue_selector.h"
|
|
|
| namespace content {
|
| @@ -41,17 +42,28 @@ class TaskQueue : public base::SingleThreadTaskRunner {
|
|
|
| base::TaskQueue& work_queue() { return work_queue_; }
|
|
|
| + void set_name(const char* name) { name_ = name; }
|
| +
|
| + void AsValueInto(base::debug::TracedValue* state) const;
|
| +
|
| private:
|
| ~TaskQueue() override;
|
|
|
| void PumpQueueLocked();
|
| void EnqueueTaskLocked(const base::PendingTask& pending_task);
|
|
|
| + void TraceWorkQueueSize() const;
|
| + static void QueueAsValueInto(const base::TaskQueue& queue,
|
| + base::debug::TracedValue* state);
|
| + static void TaskAsValueInto(const base::PendingTask& task,
|
| + base::debug::TracedValue* state);
|
| +
|
| // This lock protects all members except the work queue.
|
| mutable base::Lock lock_;
|
| TaskQueueManager* task_queue_manager_;
|
| base::TaskQueue incoming_queue_;
|
| bool auto_pump_;
|
| + const char* name_;
|
|
|
| base::TaskQueue work_queue_;
|
|
|
| @@ -59,7 +71,9 @@ class TaskQueue : public base::SingleThreadTaskRunner {
|
| };
|
|
|
| TaskQueue::TaskQueue(TaskQueueManager* task_queue_manager)
|
| - : task_queue_manager_(task_queue_manager), auto_pump_(true) {
|
| + : task_queue_manager_(task_queue_manager),
|
| + auto_pump_(true),
|
| + name_(nullptr) {
|
| }
|
|
|
| TaskQueue::~TaskQueue() {
|
| @@ -125,6 +139,7 @@ bool TaskQueue::UpdateWorkQueue() {
|
| if (!auto_pump_ || incoming_queue_.empty())
|
| return false;
|
| work_queue_.Swap(&incoming_queue_);
|
| + TraceWorkQueueSize();
|
| return true;
|
| }
|
| }
|
| @@ -132,9 +147,17 @@ bool TaskQueue::UpdateWorkQueue() {
|
| base::PendingTask TaskQueue::TakeTaskFromWorkQueue() {
|
| base::PendingTask pending_task = work_queue_.front();
|
| work_queue_.pop();
|
| + TraceWorkQueueSize();
|
| return pending_task;
|
| }
|
|
|
| +void TaskQueue::TraceWorkQueueSize() const {
|
| + if (!name_)
|
| + return;
|
| + TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), name_,
|
| + work_queue_.size());
|
| +}
|
| +
|
| void TaskQueue::EnqueueTask(const base::PendingTask& pending_task) {
|
| base::AutoLock lock(lock_);
|
| EnqueueTaskLocked(pending_task);
|
| @@ -174,7 +197,49 @@ void TaskQueue::PumpQueue() {
|
| PumpQueueLocked();
|
| }
|
|
|
| -} // namespace
|
| +void TaskQueue::AsValueInto(base::debug::TracedValue* state) const {
|
| + base::AutoLock lock(lock_);
|
| + state->BeginDictionary();
|
| + if (name_)
|
| + state->SetString("name", name_);
|
| + state->SetBoolean("auto_pump", auto_pump_);
|
| + state->BeginArray("incoming_queue");
|
| + QueueAsValueInto(incoming_queue_, state);
|
| + state->EndArray();
|
| + state->BeginArray("work_queue");
|
| + QueueAsValueInto(work_queue_, state);
|
| + state->EndArray();
|
| + state->EndDictionary();
|
| +}
|
| +
|
| +// static
|
| +void TaskQueue::QueueAsValueInto(const base::TaskQueue& queue,
|
| + base::debug::TracedValue* state) {
|
| + base::TaskQueue queue_copy(queue);
|
| + while (!queue_copy.empty()) {
|
| + TaskAsValueInto(queue_copy.front(), state);
|
| + queue_copy.pop();
|
| + }
|
| +}
|
| +
|
| +// static
|
| +void TaskQueue::TaskAsValueInto(const base::PendingTask& task,
|
| + base::debug::TracedValue* state) {
|
| + state->BeginDictionary();
|
| + state->SetString("posted_from", task.posted_from.ToString());
|
| + state->SetInteger("sequence_num", task.sequence_num);
|
| + state->SetBoolean("nestable", task.nestable);
|
| + state->SetBoolean("is_high_res", task.is_high_res);
|
| + state->SetDouble(
|
| + "time_posted",
|
| + (task.time_posted - base::TimeTicks()).InMicroseconds() / 1000.0L);
|
| + state->SetDouble(
|
| + "delayed_run_time",
|
| + (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L);
|
| + state->EndDictionary();
|
| +}
|
| +
|
| +} // namespace internal
|
|
|
| TaskQueueManager::TaskQueueManager(
|
| size_t task_queue_count,
|
| @@ -184,6 +249,9 @@ TaskQueueManager::TaskQueueManager(
|
| selector_(selector),
|
| weak_factory_(this) {
|
| DCHECK(main_task_runner->RunsTasksOnCurrentThread());
|
| + TRACE_EVENT_OBJECT_CREATED_WITH_ID(
|
| + TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "TaskQueueManager",
|
| + this);
|
|
|
| task_queue_manager_weak_ptr_ = weak_factory_.GetWeakPtr();
|
| for (size_t i = 0; i < task_queue_count; i++) {
|
| @@ -199,6 +267,9 @@ TaskQueueManager::TaskQueueManager(
|
| }
|
|
|
| TaskQueueManager::~TaskQueueManager() {
|
| + TRACE_EVENT_OBJECT_DELETED_WITH_ID(
|
| + TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "TaskQueueManager",
|
| + this);
|
| for (auto& queue : queues_)
|
| queue->WillDeleteTaskQueueManager();
|
| }
|
| @@ -252,12 +323,20 @@ void TaskQueueManager::DoWork() {
|
| return;
|
|
|
| size_t queue_index;
|
| - if (!selector_->SelectWorkQueueToService(&queue_index))
|
| + if (!SelectWorkQueueToService(&queue_index))
|
| return;
|
| PostDoWorkOnMainRunner();
|
| RunTaskFromWorkQueue(queue_index);
|
| }
|
|
|
| +bool TaskQueueManager::SelectWorkQueueToService(size_t* out_queue_index) {
|
| + bool should_run = selector_->SelectWorkQueueToService(out_queue_index);
|
| + TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
|
| + TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "TaskQueueManager", this,
|
| + AsValueWithSelectorResult(should_run, *out_queue_index));
|
| + return should_run;
|
| +}
|
| +
|
| void TaskQueueManager::DidQueueTask(base::PendingTask* pending_task) {
|
| pending_task->sequence_num = task_sequence_num_.GetNext();
|
| task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task);
|
| @@ -291,4 +370,28 @@ bool TaskQueueManager::PostNonNestableDelayedTask(
|
| return main_task_runner_->PostNonNestableDelayedTask(from_here, task, delay);
|
| }
|
|
|
| +void TaskQueueManager::SetQueueName(size_t queue_index, const char* name) {
|
| + main_thread_checker_.CalledOnValidThread();
|
| + internal::TaskQueue* queue = Queue(queue_index);
|
| + queue->set_name(name);
|
| +}
|
| +
|
| +scoped_refptr<base::debug::ConvertableToTraceFormat>
|
| +TaskQueueManager::AsValueWithSelectorResult(bool should_run,
|
| + size_t selected_queue) const {
|
| + main_thread_checker_.CalledOnValidThread();
|
| + scoped_refptr<base::debug::TracedValue> state =
|
| + new base::debug::TracedValue();
|
| + state->BeginArray("queues");
|
| + for (auto& queue : queues_)
|
| + queue->AsValueInto(state.get());
|
| + state->EndArray();
|
| + state->BeginDictionary("selector");
|
| + selector_->AsValueInto(state.get());
|
| + state->EndDictionary();
|
| + if (should_run)
|
| + state->SetInteger("selected_queue", selected_queue);
|
| + return state;
|
| +}
|
| +
|
| } // namespace content
|
|
|