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

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

Issue 6862002: Merge gpu_trace_event back into base/debug/trace_event (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: "fix gpu/command_buffer/client/cmd_buffer_helper to new macros" Created 9 years, 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Trace events to track application performance. Events consist of a name 5 // Trace events are for tracking application performance.
6 // a type (BEGIN, END or INSTANT), a tracking id and extra string data.
7 // In addition, the current process id, thread id, a timestamp down to the
8 // microsecond and a file and line number of the calling location.
9 // 6 //
10 // The current implementation logs these events into a log file of the form 7 // Events are issued against categories. Whereas LOG's
11 // trace_<pid>.log where it's designed to be post-processed to generate a 8 // categories are statically defined, TRACE categories are created
12 // trace report. In the future, it may use another mechansim to facilitate 9 // implicitly with a string. For example:
13 // real-time analysis. 10 // TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent")
11 //
12 // Events can be INSTANT, or can be pairs of BEGIN and END:
13 // TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly")
14 // doSomethingCostly()
15 // TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly")
16 //
17 // A common use case is to trace entire function scopes. This
18 // issues a trace BEGIN and END automatically:
19 // void doSomethingCostly() {
20 // TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly");
21 // ...
22 // }
23 //
24 // Additional parameters can be associated with an event:
25 // void doSomethingCostly2(int howMuch) {
26 // TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly",
27 // "howMuch", StringPrintf("%i", howMuch).c_str());
28 // ...
29 // }
30 //
31 // The trace system will automatically add to this information the
32 // current process id, thread id, a timestamp down to the
33 // microsecond, as well as the file and line number of the calling location.
34 //
35 // By default, trace collection is compiled in, but turned off at runtime.
36 // Collecting trace data is the responsibility of the embedding
37 // application. In Chrome's case, navigating to about:gpu will turn on
38 // tracing and display data collected across all active processes.
39 //
40 // On Windows, the TRACE_EVENT output to ETW.
14 41
15 #ifndef BASE_DEBUG_TRACE_EVENT_H_ 42 #ifndef BASE_DEBUG_TRACE_EVENT_H_
16 #define BASE_DEBUG_TRACE_EVENT_H_ 43 #define BASE_DEBUG_TRACE_EVENT_H_
17 #pragma once 44 #pragma once
18 45
19 #include "build/build_config.h" 46 #include "build/build_config.h"
20 47
21 #if defined(OS_WIN)
22 // On Windows we always pull in an alternative implementation
23 // which logs to Event Tracing for Windows.
24 //
25 // Note that the Windows implementation is always enabled, irrespective the
26 // value of the CHROMIUM_ENABLE_TRACE_EVENT define. The Windows implementation
27 // is controlled by Event Tracing for Windows, which will turn tracing on only
28 // if there is someone listening for the events it generates.
29 #include "base/debug/trace_event_win.h"
30 #else // defined(OS_WIN)
31
32 #include <string> 48 #include <string>
33 49
50 #include "base/atomicops.h"
51 #include "base/callback.h"
34 #include "base/memory/scoped_ptr.h" 52 #include "base/memory/scoped_ptr.h"
53 #include "base/memory/scoped_vector.h"
35 #include "base/memory/singleton.h" 54 #include "base/memory/singleton.h"
36 #include "base/synchronization/lock.h"
37 #include "base/time.h" 55 #include "base/time.h"
38 #include "base/timer.h" 56 #include "base/timer.h"
39 57 #include <vector>
40 #ifndef CHROMIUM_ENABLE_TRACE_EVENT 58
41 #define TRACE_EVENT_BEGIN(name, id, extra) ((void) 0) 59 // Older style trace macros with explicit id and extra data
42 #define TRACE_EVENT_END(name, id, extra) ((void) 0) 60 // Only these macros result in publishing data to ETW as currently implemented.
43 #define TRACE_EVENT_INSTANT(name, id, extra) ((void) 0) 61 #define TRACE_EVENT_BEGIN_ETW(name, id, extra) \
44 62 base::debug::TraceLog::GetInstance()->AddTraceEventEtw( \
45 #else // CHROMIUM_ENABLE_TRACE_EVENT 63 base::debug::TRACE_EVENT_PHASE_BEGIN, \
46 // Use the following macros rather than using the TraceLog class directly as the 64 __FILE__, __LINE__, name, reinterpret_cast<const void*>(id), extra);
47 // underlying implementation may change in the future. Here's a sample usage: 65
48 // TRACE_EVENT_BEGIN("v8.run", documentId, scriptLocation); 66 #define TRACE_EVENT_END_ETW(name, id, extra) \
49 // RunScript(script); 67 base::debug::TraceLog::GetInstance()->AddTraceEventEtw( \
50 // TRACE_EVENT_END("v8.run", documentId, scriptLocation); 68 base::debug::TRACE_EVENT_PHASE_END, \
51 69 __FILE__, __LINE__, name, reinterpret_cast<const void*>(id), extra);
52 // Record that an event (of name, id) has begun. All BEGIN events should have 70
53 // corresponding END events with a matching (name, id). 71 #define TRACE_EVENT_INSTANT_ETW(name, id, extra) \
54 #define TRACE_EVENT_BEGIN(name, id, extra) \ 72 base::debug::TraceLog::GetInstance()->AddTraceEventEtw( \
55 base::debug::TraceLog::GetInstance()->Trace( \ 73 base::debug::TRACE_EVENT_PHASE_INSTANT, \
56 name, \ 74 __FILE__, __LINE__, name, reinterpret_cast<const void*>(id), extra);
57 base::debug::TraceLog::EVENT_BEGIN, \ 75
58 reinterpret_cast<const void*>(id), \ 76
59 extra, \ 77 // Implementation detail: trace event macros create temporary variables
60 __FILE__, \ 78 // to keep instrumentation overhead low. These macros give each temporary
61 __LINE__) 79 // variable a unique name based on the line number to prevent name collissions.
62 80 #define TRACE_EVENT_UNIQUE_IDENTIFIER3(a,b) a##b
63 // Record that an event (of name, id) has ended. All END events should have 81 #define TRACE_EVENT_UNIQUE_IDENTIFIER2(a,b) \
64 // corresponding BEGIN events with a matching (name, id). 82 TRACE_EVENT_UNIQUE_IDENTIFIER3(a,b)
65 #define TRACE_EVENT_END(name, id, extra) \ 83 #define TRACE_EVENT_UNIQUE_IDENTIFIER(name_prefix) \
66 base::debug::TraceLog::GetInstance()->Trace( \ 84 TRACE_EVENT_UNIQUE_IDENTIFIER2(name_prefix, __LINE__)
67 name, \ 85
68 base::debug::TraceLog::EVENT_END, \ 86 // Records a pair of begin and end events called "name" for the current
69 reinterpret_cast<const void*>(id), \ 87 // scope, with 0, 1 or 2 associated arguments. If the category is not
70 extra, \ 88 // enabled, then this does nothing.
71 __FILE__, \ 89 #define TRACE_EVENT0(category, name) \
72 __LINE__) 90 TRACE_EVENT1(category, name, NULL, NULL)
73 91 #define TRACE_EVENT1(category, name, arg1name, arg1val) \
74 // Record that an event (of name, id) with no duration has happened. 92 TRACE_EVENT2(category, name, arg1name, arg1val, NULL, NULL)
75 #define TRACE_EVENT_INSTANT(name, id, extra) \ 93 #define TRACE_EVENT2(category, name, arg1name, arg1val, arg2name, arg2val) \
Sigurður Ásgeirsson 2011/04/15 17:41:45 If I'm reading this correctly, these static pointe
scheib 2011/04/27 21:20:10 Done. Categories come from a static pool. A test f
76 base::debug::TraceLog::GetInstance()->Trace( \ 94 static base::debug::TraceCategory* \
77 name, \ 95 TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic) = \
78 base::debug::TraceLog::EVENT_INSTANT, \ 96 base::debug::TraceLog::GetInstance()->GetCategory(category); \
79 reinterpret_cast<const void*>(id), \ 97 if (base::subtle::Acquire_Load(\
80 extra, \ 98 &(TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic))->enabled_)) { \
81 __FILE__, \ 99 base::debug::TraceLog::GetInstance()->AddTraceEvent( \
82 __LINE__) 100 base::debug::TRACE_EVENT_PHASE_BEGIN, \
Sigurður Ásgeirsson 2011/04/15 17:41:45 a unittest to validate arguments are not evaluated
scheib 2011/04/27 21:20:10 Good test, captured in http://crbug.com/80709 can
83 #endif // CHROMIUM_ENABLE_TRACE_EVENT 101 __FILE__, __LINE__, \
102 TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic), \
103 name, \
104 arg1name, arg1val, \
105 arg2name, arg2val); \
106 } \
107 base::debug::internal::TraceEndOnScopeClose __profileScope ## __LINE ( \
108 __FILE__, __LINE__, \
109 TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic), name);
110
111 // Records a single event called "name" immediately, with 0, 1 or 2
112 // associated arguments. If the category is not enabled, then this
113 // does nothing.
114 #define TRACE_EVENT_INSTANT0(category, name) \
115 TRACE_EVENT_INSTANT1(category, name, NULL, NULL)
116 #define TRACE_EVENT_INSTANT1(category, name, arg1name, arg1val) \
117 TRACE_EVENT_INSTANT2(category, name, arg1name, arg1val, NULL, NULL)
118 #define TRACE_EVENT_INSTANT2(category, name, arg1name, arg1val, \
119 arg2name, arg2val) \
120 static base::debug::TraceCategory* \
121 TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic) = \
122 base::debug::TraceLog::GetInstance()->GetCategory(category); \
123 if (base::subtle::Acquire_Load( \
124 &(TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic))->enabled_)) { \
125 base::debug::TraceLog::GetInstance()->AddTraceEvent( \
126 base::debug::TRACE_EVENT_PHASE_INSTANT, \
127 __FILE__, __LINE__, \
128 TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic), \
129 name, \
130 arg1name, arg1val, \
131 arg2name, arg2val); \
132 }
133
134 // Records a single BEGIN event called "name" immediately, with 0, 1 or 2
135 // associated arguments. If the category is not enabled, then this
136 // does nothing.
137 #define TRACE_EVENT_BEGIN0(category, name) \
138 TRACE_EVENT_BEGIN1(category, name, NULL, NULL)
139 #define TRACE_EVENT_BEGIN1(category, name, arg1name, arg1val) \
140 TRACE_EVENT_BEGIN2(category, name, arg1name, arg1val, NULL, NULL)
141 #define TRACE_EVENT_BEGIN2(category, name, arg1name, arg1val, \
142 arg2name, arg2val) \
143 static base::debug::TraceCategory* \
144 TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic) = \
145 base::debug::TraceLog::GetInstance()->GetCategory(category); \
146 if (base::subtle::Acquire_Load( \
147 &(TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic))->enabled_)) { \
148 base::debug::TraceLog::GetInstance()->AddTraceEvent( \
149 base::debug::TRACE_EVENT_PHASE_BEGIN, \
150 __FILE__, __LINE__, \
151 TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic), \
152 name, \
153 arg1name, arg1val, \
154 arg2name, arg2val); \
155 }
156
157 // Records a single END event for "name" immediately. If the category
158 // is not enabled, then this does nothing.
159 #define TRACE_EVENT_END0(category, name) \
160 TRACE_EVENT_END1(category, name, NULL, NULL)
161 #define TRACE_EVENT_END1(category, name, arg1name, arg1val) \
162 TRACE_EVENT_END2(category, name, arg1name, arg1val, NULL, NULL)
163 #define TRACE_EVENT_END2(category, name, arg1name, arg1val, \
164 arg2name, arg2val) \
165 static base::debug::TraceCategory* \
166 TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic) = \
167 base::debug::TraceLog::GetInstance()->GetCategory(category); \
168 if (base::subtle::Acquire_Load( \
169 &(TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic))->enabled_)) { \
170 base::debug::TraceLog::GetInstance()->AddTraceEvent( \
171 base::debug::TRACE_EVENT_PHASE_END, \
172 __FILE__, __LINE__, \
173 TRACE_EVENT_UNIQUE_IDENTIFIER(catstatic), \
174 name, \
175 arg1name, arg1val, \
176 arg2name, arg2val); \
177 }
84 178
85 namespace base { 179 namespace base {
86 180
87 class ProcessMetrics;
88
89 namespace debug { 181 namespace debug {
90 182
183 // Categories allow enabling/disabling of streams of trace events
184 // Don't manipulate the category object directly, as this may lead
185 // to threading issues. Use the TraceLog methods instead.
186 class TraceCategory {
187 public:
188 TraceCategory(const char* name, bool enabled);
189 ~TraceCategory();
190
191 const char* name() const { return name_; }
192
193 // NEVER read these directly, let the macros do it for you
194 volatile base::subtle::Atomic32 enabled_;
Sigurður Ásgeirsson 2011/04/15 17:41:45 maybe wrap this in an inline accessor used by the
scheib 2011/04/27 21:20:10 Removed, it was not needed. Just a volatile bool n
195 protected:
196 const char* name_;
197 };
198
199 #define TRACE_MAX_NUM_ARGS 2
200
201 enum TraceEventPhase {
202 TRACE_EVENT_PHASE_BEGIN,
203 TRACE_EVENT_PHASE_END,
204 TRACE_EVENT_PHASE_INSTANT
205 };
206
207 // Output records are "Events" and can be obtained via the
208 // OutputCallback whenever the logging system decides to flush. This
Sigurður Ásgeirsson 2011/04/15 17:41:45 logging system -> tracing system?
scheib 2011/04/27 21:20:10 Done.
209 // can happen at any time, on any thread, or you can programatically
210 // force it to happen.
211 struct TraceEvent {
212 static void AppendAsJSON(std::string* out,
Sigurður Ásgeirsson 2011/04/15 17:41:45 one line comment for method purpose and/or usage?
scheib 2011/04/27 21:20:10 Done.
213 const std::vector<TraceEvent>& events,
214 size_t start,
215 size_t count);
216 TraceEvent();
217 ~TraceEvent();
218 void AppendAsJSON(std::string* out) const;
219
220
221 unsigned long processId;
Sigurður Ásgeirsson 2011/04/15 17:41:45 nit: process_id, thread_id, arg_names, arg_values
scheib 2011/04/27 21:20:10 Done.
222 unsigned long threadId;
223 TimeTicks timestamp;
224 TraceEventPhase phase;
225 TraceCategory* category;
226 const char* name;
227 const char* argNames[TRACE_MAX_NUM_ARGS];
228 std::string argValues[TRACE_MAX_NUM_ARGS];
229 };
230
231
91 class TraceLog { 232 class TraceLog {
92 public: 233 public:
93 enum EventType {
94 EVENT_BEGIN,
95 EVENT_END,
96 EVENT_INSTANT
97 };
98 234
99 static TraceLog* GetInstance(); 235 static TraceLog* GetInstance();
100 236
101 // Is tracing currently enabled. 237 // Global enable of tracing. Currently enables all categories or not.
102 static bool IsTracing(); 238 // TODO(nduca) Replaced with an Enable/DisableCategory() that
Sigurður Ásgeirsson 2011/04/15 17:41:45 missing colon after TODO, nduca->shceib? Replaced
scheib 2011/04/27 21:20:10 Done.
103 // Start logging trace events. 239 // implicitly controls the global logging state.
Sigurður Ásgeirsson 2011/04/15 17:41:45 control->controls?
scheib 2011/04/27 21:20:10 Done.
104 static bool StartTracing(); 240 void SetEnabled(bool enabled);
105 // Stop logging trace events. 241
106 static void StopTracing(); 242 // When enough events are collected, they are handed (in bulk) to
107 243 // the output callback. If no callback is set, the output will be
108 // Log a trace event of (name, type, id) with the optional extra string. 244 // silently dropped.
Sigurður Ásgeirsson 2011/04/15 17:41:45 Add a note that this takes ownership of the callba
scheib 2011/04/27 21:20:10 Done.
109 void Trace(const std::string& name, 245 typedef Callback1<const std::string& /* json_events */>::Type OutputCallback;
110 EventType type, 246 void SetOutputCallback(OutputCallback* cb);
111 const void* id, 247
112 const std::wstring& extra, 248 // Forwards data collected by a child process to the registered
113 const char* file, 249 // output callback.
Sigurður Ásgeirsson 2011/04/15 17:41:45 nit: one space only after //
scheib 2011/04/27 21:20:10 Done.
114 int line); 250 void AddRemotelyCollectedData(const std::string& json_events);
115 void Trace(const std::string& name, 251
116 EventType type, 252 // Flushes all logged data to the callback.
117 const void* id, 253 void Flush();
118 const std::string& extra, 254
119 const char* file, 255 // Called by TRACE_EVENT* macros, don't call this directly.
120 int line); 256 TraceCategory* GetCategory(const char* name);
257
258 // Called by TRACE_EVENT* macros, don't call this directly.
259 void AddTraceEvent(TraceEventPhase phase,
260 const char* file, int line,
261 TraceCategory* category,
262 const char* name,
263 const char* arg1name, const char* arg1val,
264 const char* arg2name, const char* arg2val);
265 void AddTraceEventEtw(TraceEventPhase phase,
266 const char* file, int line,
267 const char* name,
268 const void* id,
269 const char* extra);
270 void AddTraceEventEtw(TraceEventPhase phase,
271 const char* file, int line,
272 const char* name,
273 const void* id,
274 const std::string& extra) {
275 AddTraceEventEtw(phase, file, line, name, id, extra.c_str());
276 }
121 277
122 private: 278 private:
123 // This allows constructor and destructor to be private and usable only 279 // This allows constructor and destructor to be private and usable only
124 // by the Singleton class. 280 // by the Singleton class.
125 friend struct DefaultSingletonTraits<TraceLog>; 281 friend struct StaticMemorySingletonTraits<TraceLog>;
126 282
127 TraceLog(); 283 TraceLog();
128 ~TraceLog(); 284 ~TraceLog();
129 bool OpenLogFile(); 285 void FlushWithLockAlreadyHeld();
130 void CloseLogFile(); 286
131 bool Start(); 287 // TODO(nduca): switch to per-thread tace buffers to reduce thread
Sigurður Ásgeirsson 2011/04/15 17:41:45 tace->trace?
scheib 2011/04/27 21:20:10 Done.
132 void Stop(); 288 // synchronization.
133 void Heartbeat(); 289 Lock lock_;
134 void Log(const std::string& msg);
135
136 bool enabled_; 290 bool enabled_;
137 FILE* log_file_; 291 ScopedVector<TraceCategory> categories_;
138 base::Lock file_lock_; 292 scoped_ptr<OutputCallback> output_callback_;
139 TimeTicks trace_start_time_; 293 std::vector<TraceEvent> logged_events_;
140 scoped_ptr<base::ProcessMetrics> process_metrics_; 294
141 RepeatingTimer<TraceLog> timer_; 295 DISALLOW_COPY_AND_ASSIGN(TraceLog);
142 }; 296 };
297
298 namespace internal {
299
300 // Used by TRACE_EVENTx macro. Do not use directly.
301 class TraceEndOnScopeClose {
302 public:
303 TraceEndOnScopeClose(const char* file, int line,
304 TraceCategory* category,
305 const char* name)
306 : file_(file)
307 , line_(line)
308 , category_(category)
309 , name_(name) { }
310
311 ~TraceEndOnScopeClose() {
312 if (base::subtle::Acquire_Load(&category_->enabled_))
313 base::debug::TraceLog::GetInstance()->AddTraceEvent(
314 base::debug::TRACE_EVENT_PHASE_END,
315 file_, line_,
316 category_,
317 name_,
318 NULL, NULL, NULL, NULL);
319 }
320
321 private:
322 const char* file_;
323 int line_;
324 TraceCategory* category_;
325 const char* name_;
326 };
327
328 } // namespace internal
143 329
144 } // namespace debug 330 } // namespace debug
145 } // namespace base 331 } // namespace base
146 332
147 #endif // defined(OS_WIN)
148
149 #endif // BASE_DEBUG_TRACE_EVENT_H_ 333 #endif // BASE_DEBUG_TRACE_EVENT_H_
OLDNEW
« no previous file with comments | « base/base.gypi ('k') | base/debug/trace_event.cc » ('j') | base/debug/trace_event.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698