diff options
author | skyostil@chromium.org <skyostil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-14 14:26:09 +0000 |
---|---|---|
committer | skyostil@chromium.org <skyostil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-14 14:26:09 +0000 |
commit | 9a4af4bd37cb20677a8467d631b75efe539affa2 (patch) | |
tree | 430bcbd7768c81729886c1d0aac679c68e3a0802 /base/debug | |
parent | 5c93635407fe77c765e98e8018971ca94d1ab4e2 (diff) | |
download | chromium_src-9a4af4bd37cb20677a8467d631b75efe539affa2.zip chromium_src-9a4af4bd37cb20677a8467d631b75efe539affa2.tar.gz chromium_src-9a4af4bd37cb20677a8467d631b75efe539affa2.tar.bz2 |
base: Factor task debug annotations out of MessageLoop
The MessageLoop has some code for adding debug annotations such as trace
flows and memory usage tags to posted tasks. Since we want to use these
annotations more generally for tasks that are scheduled outside the base
message loop, this patch factors it out into a standalone class.
TEST=TaskAnnotatorTest
BUG=391005
Review URL: https://codereview.chromium.org/455833004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@289560 0039d316-1c4b-4281-b951-d872f2087c98
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 |