diff options
Diffstat (limited to 'base/debug')
-rw-r--r-- | base/debug/task_annotator.cc | 74 | ||||
-rw-r--r-- | base/debug/task_annotator.h | 46 | ||||
-rw-r--r-- | base/debug/task_annotator_unittest.cc | 33 |
3 files changed, 153 insertions, 0 deletions
diff --git a/base/debug/task_annotator.cc b/base/debug/task_annotator.cc new file mode 100644 index 0000000..c6576c8 --- /dev/null +++ b/base/debug/task_annotator.cc @@ -0,0 +1,74 @@ +// Copyright 2014 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 "base/debug/task_annotator.h" + +#include "base/debug/alias.h" +#include "base/debug/trace_event.h" +#include "base/pending_task.h" +#include "base/tracked_objects.h" + +namespace base { +namespace debug { + +TaskAnnotator::TaskAnnotator() { +} + +TaskAnnotator::~TaskAnnotator() { +} + +void TaskAnnotator::DidQueueTask(const char* queue_function, + const PendingTask& pending_task) { + TRACE_EVENT_FLOW_BEGIN0(TRACE_DISABLED_BY_DEFAULT("toplevel.flow"), + queue_function, + TRACE_ID_MANGLE(GetTaskTraceID(pending_task))); +} + +void TaskAnnotator::RunTask(const char* queue_function, + const char* run_function, + const PendingTask& pending_task) { + tracked_objects::TrackedTime start_time = + tracked_objects::ThreadData::NowForStartOfRun(pending_task.birth_tally); + tracked_objects::Duration queue_duration = + start_time - pending_task.EffectiveTimePosted(); + + TRACE_EVENT_FLOW_END1(TRACE_DISABLED_BY_DEFAULT("toplevel.flow"), + queue_function, + TRACE_ID_MANGLE(GetTaskTraceID(pending_task)), + "queue_duration", + queue_duration.InMilliseconds()); + + // When tracing memory for posted tasks it's more valuable to attribute the + // memory allocations to the source function than generically to the task + // runner. + TRACE_EVENT_WITH_MEMORY_TAG2( + "toplevel", + run_function, + pending_task.posted_from.function_name(), // Name for memory tracking. + "src_file", + pending_task.posted_from.file_name(), + "src_func", + pending_task.posted_from.function_name()); + + // Before running the task, store the program counter where it was posted + // and deliberately alias it to ensure it is on the stack if the task + // crashes. Be careful not to assume that the variable itself will have the + // expected value when displayed by the optimizer in an optimized build. + // Look at a memory dump of the stack. + const void* program_counter = pending_task.posted_from.program_counter(); + debug::Alias(&program_counter); + + pending_task.task.Run(); + + tracked_objects::ThreadData::TallyRunOnNamedThreadIfTracking( + pending_task, start_time, tracked_objects::ThreadData::NowForEndOfRun()); +} + +uint64 TaskAnnotator::GetTaskTraceID(const PendingTask& task) const { + return (static_cast<uint64>(task.sequence_num) << 32) | + ((static_cast<uint64>(reinterpret_cast<intptr_t>(this)) << 32) >> 32); +} + +} // namespace debug +} // namespace base diff --git a/base/debug/task_annotator.h b/base/debug/task_annotator.h new file mode 100644 index 0000000..aa5f17b --- /dev/null +++ b/base/debug/task_annotator.h @@ -0,0 +1,46 @@ +// Copyright 2014 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 BASE_DEBUG_TASK_ANNOTATOR_H_ +#define BASE_DEBUG_TASK_ANNOTATOR_H_ + +#include "base/base_export.h" +#include "base/basictypes.h" + +namespace base { +struct PendingTask; +namespace debug { + +// Implements common debug annotations for posted tasks. This includes data +// such as task origins, queueing durations and memory usage. +class BASE_EXPORT TaskAnnotator { + public: + TaskAnnotator(); + ~TaskAnnotator(); + + // Called to indicate that a task has been queued to run in the future. + // |queue_function| is used as the trace flow event name. + void DidQueueTask(const char* queue_function, + const PendingTask& pending_task); + + // Run a previously queued task. |queue_function| should match what was + // passed into |DidQueueTask| for this task. |run_function| is used as the + // name for the trace event that surrounds the task's execution. + void RunTask(const char* queue_function, + const char* run_function, + const PendingTask& pending_task); + + private: + // Creates a process-wide unique ID to represent this task in trace events. + // This will be mangled with a Process ID hash to reduce the likelyhood of + // colliding with TaskAnnotator pointers on other processes. + uint64 GetTaskTraceID(const PendingTask& task) const; + + DISALLOW_COPY_AND_ASSIGN(TaskAnnotator); +}; + +} // namespace debug +} // namespace base + +#endif // BASE_DEBUG_TASK_ANNOTATOR_H_ diff --git a/base/debug/task_annotator_unittest.cc b/base/debug/task_annotator_unittest.cc new file mode 100644 index 0000000..ddffc21 --- /dev/null +++ b/base/debug/task_annotator_unittest.cc @@ -0,0 +1,33 @@ +// Copyright 2014 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 "base/debug/task_annotator.h" +#include "base/bind.h" +#include "base/pending_task.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { +namespace debug { +namespace { + +void TestTask(int* result) { + *result = 123; +} + +} // namespace + +TEST(TaskAnnotatorTest, QueueAndRunTask) { + int result = 0; + PendingTask pending_task(FROM_HERE, Bind(&TestTask, &result)); + + TaskAnnotator annotator; + annotator.DidQueueTask("TaskAnnotatorTest::Queue", pending_task); + EXPECT_EQ(0, result); + annotator.RunTask( + "TaskAnnotatorTest::Queue", "TaskAnnotatorTest::Run", pending_task); + EXPECT_EQ(123, result); +} + +} // namespace debug +} // namespace base |