Commit b7555076 authored by gab's avatar gab Committed by Commit bot

Add a task_scheduler tracing category which will record an extra event per task.

That event will contain ExecutionMode/SequenceToken and TaskPriority.

It would be better to tack an optional extra arg to the main task event but
tracing doesn't currently allow this (http://crbug.com/652692).

BUG=649084

Review-Url: https://codereview.chromium.org/2392903002
Cr-Commit-Position: refs/heads/master@{#423681}
parent db9e1827
...@@ -37,6 +37,10 @@ bool SequenceToken::IsValid() const { ...@@ -37,6 +37,10 @@ bool SequenceToken::IsValid() const {
return token_ != kInvalidSequenceToken; return token_ != kInvalidSequenceToken;
} }
int SequenceToken::ToInternalValue() const {
return token_;
}
SequenceToken SequenceToken::Create() { SequenceToken SequenceToken::Create() {
return SequenceToken(g_sequence_token_generator.GetNext()); return SequenceToken(g_sequence_token_generator.GetNext());
} }
......
...@@ -29,6 +29,10 @@ class BASE_EXPORT SequenceToken { ...@@ -29,6 +29,10 @@ class BASE_EXPORT SequenceToken {
// Returns true if this is a valid SequenceToken. // Returns true if this is a valid SequenceToken.
bool IsValid() const; bool IsValid() const;
// Returns the integer uniquely representing this SequenceToken. This method
// should only be used for tracing and debugging.
int ToInternalValue() const;
// Returns a valid SequenceToken which isn't equal to any previously returned // Returns a valid SequenceToken which isn't equal to any previously returned
// SequenceToken. // SequenceToken.
static SequenceToken Create(); static SequenceToken Create();
......
...@@ -62,6 +62,14 @@ TEST(SequenceTokenTest, GetForCurrentThread) { ...@@ -62,6 +62,14 @@ TEST(SequenceTokenTest, GetForCurrentThread) {
EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid()); EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid());
} }
TEST(SequenceTokenTest, ToInternalValue) {
const SequenceToken token1 = SequenceToken::Create();
const SequenceToken token2 = SequenceToken::Create();
// Confirm that internal values are unique.
EXPECT_NE(token1.ToInternalValue(), token2.ToInternalValue());
}
// Expect a default-constructed TaskToken to be invalid and not equal to // Expect a default-constructed TaskToken to be invalid and not equal to
// another invalid TaskToken. // another invalid TaskToken.
TEST(TaskTokenTest, InvalidDefaultConstructed) { TEST(TaskTokenTest, InvalidDefaultConstructed) {
......
...@@ -8,7 +8,9 @@ ...@@ -8,7 +8,9 @@
#include "base/callback.h" #include "base/callback.h"
#include "base/debug/task_annotator.h" #include "base/debug/task_annotator.h"
#include "base/json/json_writer.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/sequence_token.h" #include "base/sequence_token.h"
#include "base/synchronization/condition_variable.h" #include "base/synchronization/condition_variable.h"
...@@ -16,12 +18,49 @@ ...@@ -16,12 +18,49 @@
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "base/values.h"
namespace base { namespace base {
namespace internal { namespace internal {
namespace { namespace {
// An immutable copy of a scheduler task's info required by tracing.
class TaskTracingInfo : public trace_event::ConvertableToTraceFormat {
public:
TaskTracingInfo(const TaskTraits& task_traits,
ExecutionMode execution_mode,
const SequenceToken& sequence_token)
: task_traits_(task_traits),
execution_mode_(execution_mode),
sequence_token_(sequence_token) {}
// trace_event::ConvertableToTraceFormat implementation.
void AppendAsTraceFormat(std::string* out) const override;
private:
const TaskTraits task_traits_;
const ExecutionMode execution_mode_;
const SequenceToken sequence_token_;
DISALLOW_COPY_AND_ASSIGN(TaskTracingInfo);
};
void TaskTracingInfo::AppendAsTraceFormat(std::string* out) const {
DictionaryValue dict;
dict.SetString("task_priority",
base::TaskPriorityToString(task_traits_.priority()));
dict.SetString("execution_mode",
base::ExecutionModeToString(execution_mode_));
if (execution_mode_ != ExecutionMode::PARALLEL)
dict.SetInteger("sequence_token", sequence_token_.ToInternalValue());
std::string tmp;
JSONWriter::Write(dict, &tmp);
out->append(tmp);
}
const char kQueueFunctionName[] = "base::PostTask"; const char kQueueFunctionName[] = "base::PostTask";
// This name conveys that a Task is run by the task scheduler without revealing // This name conveys that a Task is run by the task scheduler without revealing
...@@ -203,6 +242,18 @@ bool TaskTracker::RunTask(const Task* task, ...@@ -203,6 +242,18 @@ bool TaskTracker::RunTask(const Task* task,
TRACE_TASK_EXECUTION(kRunFunctionName, *task); TRACE_TASK_EXECUTION(kRunFunctionName, *task);
const ExecutionMode execution_mode =
task->single_thread_task_runner_ref
? ExecutionMode::SINGLE_THREADED
: (task->sequenced_task_runner_ref ? ExecutionMode::SEQUENCED
: ExecutionMode::PARALLEL);
// TODO(gab): In a better world this would be tacked on as an extra arg
// to the trace event generated above. This is not possible however until
// http://crbug.com/652692 is resolved.
TRACE_EVENT1("task_scheduler", "TaskTracker::RunTask", "task_info",
MakeUnique<TaskTracingInfo>(task->traits, execution_mode,
sequence_token));
debug::TaskAnnotator task_annotator; debug::TaskAnnotator task_annotator;
task_annotator.RunTask(kQueueFunctionName, *task); task_annotator.RunTask(kQueueFunctionName, *task);
} }
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include <ostream> #include <ostream>
#include "base/logging.h"
namespace base { namespace base {
// Do not rely on defaults hard-coded below beyond the guarantees described in // Do not rely on defaults hard-coded below beyond the guarantees described in
...@@ -36,34 +38,60 @@ TaskTraits& TaskTraits::WithShutdownBehavior( ...@@ -36,34 +38,60 @@ TaskTraits& TaskTraits::WithShutdownBehavior(
return *this; return *this;
} }
std::ostream& operator<<(std::ostream& os, const TaskPriority& task_priority) { const char* TaskPriorityToString(TaskPriority task_priority) {
switch (task_priority) { switch (task_priority) {
case TaskPriority::BACKGROUND: case TaskPriority::BACKGROUND:
os << "BACKGROUND"; return "BACKGROUND";
break;
case TaskPriority::USER_VISIBLE: case TaskPriority::USER_VISIBLE:
os << "USER_VISIBLE"; return "USER_VISIBLE";
break;
case TaskPriority::USER_BLOCKING: case TaskPriority::USER_BLOCKING:
os << "USER_BLOCKING"; return "USER_BLOCKING";
break;
} }
return os; NOTREACHED();
return "";
} }
std::ostream& operator<<(std::ostream& os, const char* TaskShutdownBehaviorToString(
const TaskShutdownBehavior& shutdown_behavior) { TaskShutdownBehavior shutdown_behavior) {
switch (shutdown_behavior) { switch (shutdown_behavior) {
case TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN: case TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN:
os << "CONTINUE_ON_SHUTDOWN"; return "CONTINUE_ON_SHUTDOWN";
break;
case TaskShutdownBehavior::SKIP_ON_SHUTDOWN: case TaskShutdownBehavior::SKIP_ON_SHUTDOWN:
os << "SKIP_ON_SHUTDOWN"; return "SKIP_ON_SHUTDOWN";
break;
case TaskShutdownBehavior::BLOCK_SHUTDOWN: case TaskShutdownBehavior::BLOCK_SHUTDOWN:
os << "BLOCK_SHUTDOWN"; return "BLOCK_SHUTDOWN";
break;
} }
NOTREACHED();
return "";
}
const char* ExecutionModeToString(ExecutionMode execution_mode) {
switch (execution_mode) {
case ExecutionMode::PARALLEL:
return "PARALLEL";
case ExecutionMode::SEQUENCED:
return "SEQUENCED";
case ExecutionMode::SINGLE_THREADED:
return "SINGLE_THREADED";
}
NOTREACHED();
return "";
}
std::ostream& operator<<(std::ostream& os, const TaskPriority& task_priority) {
os << TaskPriorityToString(task_priority);
return os;
}
std::ostream& operator<<(std::ostream& os,
const TaskShutdownBehavior& shutdown_behavior) {
os << TaskShutdownBehaviorToString(shutdown_behavior);
return os;
}
std::ostream& operator<<(std::ostream& os,
const ExecutionMode& execution_mode) {
os << ExecutionModeToString(execution_mode);
return os; return os;
} }
......
...@@ -126,14 +126,22 @@ enum class ExecutionMode { ...@@ -126,14 +126,22 @@ enum class ExecutionMode {
SINGLE_THREADED, SINGLE_THREADED,
}; };
// Stream operators so TaskPriority and TaskShutdownBehavior can be used in // Returns string literals for the enums defined in this file. These methods
// DCHECK statements. // should only be used for tracing and debugging.
BASE_EXPORT const char* TaskPriorityToString(TaskPriority task_priority);
BASE_EXPORT const char* TaskShutdownBehaviorToString(
TaskShutdownBehavior task_priority);
BASE_EXPORT const char* ExecutionModeToString(ExecutionMode task_priority);
// Stream operators so that the enums defined in this file can be used in
// DCHECK and EXPECT statements.
BASE_EXPORT std::ostream& operator<<(std::ostream& os, BASE_EXPORT std::ostream& operator<<(std::ostream& os,
const TaskPriority& shutdown_behavior); const TaskPriority& shutdown_behavior);
BASE_EXPORT std::ostream& operator<<( BASE_EXPORT std::ostream& operator<<(
std::ostream& os, std::ostream& os,
const TaskShutdownBehavior& shutdown_behavior); const TaskShutdownBehavior& shutdown_behavior);
BASE_EXPORT std::ostream& operator<<(std::ostream& os,
const ExecutionMode& execution_mode);
} // namespace base } // namespace base
......
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