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 |