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 {
return token_ != kInvalidSequenceToken;
}
int SequenceToken::ToInternalValue() const {
return token_;
}
SequenceToken SequenceToken::Create() {
return SequenceToken(g_sequence_token_generator.GetNext());
}
......
......@@ -29,6 +29,10 @@ class BASE_EXPORT SequenceToken {
// Returns true if this is a valid SequenceToken.
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
// SequenceToken.
static SequenceToken Create();
......
......@@ -62,6 +62,14 @@ TEST(SequenceTokenTest, GetForCurrentThread) {
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
// another invalid TaskToken.
TEST(TaskTokenTest, InvalidDefaultConstructed) {
......
......@@ -8,7 +8,9 @@
#include "base/callback.h"
#include "base/debug/task_annotator.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/sequence_token.h"
#include "base/synchronization/condition_variable.h"
......@@ -16,12 +18,49 @@
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "base/values.h"
namespace base {
namespace internal {
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";
// This name conveys that a Task is run by the task scheduler without revealing
......@@ -203,6 +242,18 @@ bool TaskTracker::RunTask(const Task* 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;
task_annotator.RunTask(kQueueFunctionName, *task);
}
......
......@@ -8,6 +8,8 @@
#include <ostream>
#include "base/logging.h"
namespace base {
// Do not rely on defaults hard-coded below beyond the guarantees described in
......@@ -36,34 +38,60 @@ TaskTraits& TaskTraits::WithShutdownBehavior(
return *this;
}
std::ostream& operator<<(std::ostream& os, const TaskPriority& task_priority) {
const char* TaskPriorityToString(TaskPriority task_priority) {
switch (task_priority) {
case TaskPriority::BACKGROUND:
os << "BACKGROUND";
break;
return "BACKGROUND";
case TaskPriority::USER_VISIBLE:
os << "USER_VISIBLE";
break;
return "USER_VISIBLE";
case TaskPriority::USER_BLOCKING:
os << "USER_BLOCKING";
break;
return "USER_BLOCKING";
}
return os;
NOTREACHED();
return "";
}
std::ostream& operator<<(std::ostream& os,
const TaskShutdownBehavior& shutdown_behavior) {
const char* TaskShutdownBehaviorToString(
TaskShutdownBehavior shutdown_behavior) {
switch (shutdown_behavior) {
case TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN:
os << "CONTINUE_ON_SHUTDOWN";
break;
return "CONTINUE_ON_SHUTDOWN";
case TaskShutdownBehavior::SKIP_ON_SHUTDOWN:
os << "SKIP_ON_SHUTDOWN";
break;
return "SKIP_ON_SHUTDOWN";
case TaskShutdownBehavior::BLOCK_SHUTDOWN:
os << "BLOCK_SHUTDOWN";
break;
return "BLOCK_SHUTDOWN";
}
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;
}
......
......@@ -126,14 +126,22 @@ enum class ExecutionMode {
SINGLE_THREADED,
};
// Stream operators so TaskPriority and TaskShutdownBehavior can be used in
// DCHECK statements.
// Returns string literals for the enums defined in this file. These methods
// 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,
const TaskPriority& shutdown_behavior);
BASE_EXPORT std::ostream& operator<<(
std::ostream& os,
const TaskShutdownBehavior& shutdown_behavior);
BASE_EXPORT std::ostream& operator<<(std::ostream& os,
const ExecutionMode& execution_mode);
} // 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