Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(356)

Side by Side Diff: base/debug/blame_context.h

Issue 1447563002: Implement frame attribution (FrameBlamer) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Cleanup. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef BASE_DEBUG_BLAME_CONTEXT_H_
6 #define BASE_DEBUG_BLAME_CONTEXT_H_
7
8 #include <inttypes.h>
9
10 #include "base/macros.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/trace_event/trace_event.h"
13 #include "base/trace_event/trace_event_argument.h"
14
15 namespace base {
16 namespace debug {
17
18 // A blame context represents a logical unit to which we want to attribute
19 // different costs (CPU, network usage, memory, etc.). An example of a blame
20 // context is an <iframe> element on a web page. Different subsystems can
21 // "enter" and "leave" blame contexts to indicate that they are doing work which
22 // should be accounted against this blame context.
23 //
24 // Each blame context can optionally have a parent blame context, forming a
25 // blame context tree. When work is attributed to a particular blame context, it
26 // is considered to count against all of that context's children too. This is
27 // useful when work cannot be exactly attributed into a more specific context.
28 // For example, Javascript garbage collection generally needs to inspect all
29 // objects on a page instead looking at each <iframe> individually. In this case
30 // the work should be attributed to a blame context which is the parent of all
31 // <iframe> blame contexts.
32
33 // Abstract blame context base class which can be used for attributing work.
34 class BlameContextBase {
35 public:
36 // Indicate that the current thread is now doing work which should count
37 // against this blame context.
38 virtual void Enter() = 0;
39
40 // Leave and stop doing work for a previously entered blame context. If
41 // another blame context of the same type was entered prior to this one, it
42 // becomes the active blame context for this thread again.
43 virtual void Leave() = 0;
44
45 protected:
46 BlameContextBase() {}
47 virtual ~BlameContextBase() {}
48
49 DISALLOW_COPY_AND_ASSIGN(BlameContextBase);
50 };
51
52 // A concrete instance of a blame context which emits blame context trace
53 // events. |category| is the tracing category this context belongs to and |name|
54 // identifies the type of the blame context. |scope| defines the name space for
55 // the |id| parameter (identical ids in different scopes are considered separate
56 // blame context objects). Each string parameter must be a pointer to a constant
57 // string with application lifetime.
58 //
59 // Note that the blame context is templatized to work around a trace event
60 // limitation which prohibits a single trace event macro instantiation to be
61 // used with more than one trace category.
62 // TODO(skyostil): De-templatize this class.
63 template <const char* category, const char* name, const char* scope>
64 class BlameContext : public BlameContextBase,
65 public trace_event::TraceLog::EnabledStateObserver {
66 public:
67 // Construct a blame context with the given |id| belonging to the |scope|
68 // namespace. The blame context will not have a parent.
69 explicit BlameContext(int64_t id)
70 : id_(id), parent_id_(0), parent_scope_(nullptr) {
71 Initialize();
72 }
73
74 // Construct a blame context with the given |id| belonging to the |scope|
75 // namespace. |parent_context| identifies the parent for this blame context.
76 // It must belong to the same blame context tree as this context, i.e., |name|
77 // must equal |parent_name|.
78 template <const char* parent_category,
79 const char* parent_name,
80 const char* parent_scope>
81 BlameContext(int64_t id,
82 const BlameContext<parent_category, parent_name, parent_scope>&
83 parent_context)
84 : id_(id), parent_id_(parent_context.id()), parent_scope_(parent_scope) {
85 DCHECK(!strcmp(name, parent_name))
86 << "parent blame context must be of the same type";
87 Initialize();
88 }
89
90 // BlameContextBase implementation:
91 void Enter() override {
92 TRACE_EVENT_ENTER_CONTEXT(category, name, TRACE_ID_WITH_SCOPE(scope, id_));
93 }
94
95 void Leave() override {
96 TRACE_EVENT_LEAVE_CONTEXT(category, name, TRACE_ID_WITH_SCOPE(scope, id_));
97 }
98
99 // Record a snapshot of the blame context. This is normally only needed if a
100 // blame context subclass defines custom properties (see AsValueInto) and one
101 // or more of the properties have changed.
102 void TakeSnapshot() {
103 bool is_tracing = false;
104 TRACE_EVENT_CATEGORY_GROUP_ENABLED(category, &is_tracing);
105 if (!is_tracing)
106 return;
107 scoped_ptr<trace_event::TracedValue> snapshot(new trace_event::TracedValue);
108 AsValueInto(snapshot.get());
109 scoped_ptr<trace_event::ConvertableToTraceFormat> snapshot_data(
110 std::move(snapshot));
111 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category, name,
112 TRACE_ID_WITH_SCOPE(scope, id_),
113 std::move(snapshot_data));
114 }
115
116 int64_t id() const { return id_; }
117
118 // trace_event::TraceLog::EnabledStateObserver implementation:
119 void OnTraceLogEnabled() override { TakeSnapshot(); }
120
121 void OnTraceLogDisabled() override {}
122
123 protected:
124 virtual ~BlameContext() {
125 TRACE_EVENT_OBJECT_DELETED_WITH_ID(category, name,
126 TRACE_ID_WITH_SCOPE(scope, id_));
127 trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
128 }
129
130 // Serialize the properties of this blame context into |state|. Subclasses can
131 // override this method to record additional properties (e.g, the URL for an
132 // <iframe> blame context). Note that an overriden implementation must still
133 // call this base method.
134 virtual void AsValueInto(trace_event::TracedValue* state) {
135 if (!parent_id_)
136 return;
137 state->BeginDictionary("parent");
138 state->SetString("id_ref", StringPrintf("0x%" PRIx64, parent_id_));
139 state->SetString("scope", parent_scope_);
140 state->EndDictionary();
141 }
142
143 private:
144 void Initialize() {
145 TRACE_EVENT_OBJECT_CREATED_WITH_ID(category, name,
146 TRACE_ID_WITH_SCOPE(scope, id_));
147 trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this);
148 }
149
150 const int64_t id_;
151 const int64_t parent_id_;
152 const char* parent_scope_;
153
154 DISALLOW_COPY_AND_ASSIGN(BlameContext);
155 };
156
157 } // namespace debug
158 } // namespace base
159
160 #endif // BASE_DEBUG_BLAME_CONTEXT_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698