1 | // Copyright 2015 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 | #ifndef SkTraceEventCommon_DEFINED |
5 | #define SkTraceEventCommon_DEFINED |
6 | |
7 | #include "include/core/SkTypes.h" |
8 | #include "include/utils/SkTraceEventPhase.h" |
9 | |
10 | // Trace events are for tracking application performance and resource usage. |
11 | // Macros are provided to track: |
12 | // Duration of scoped regions |
13 | // Instantaneous events |
14 | // Counters |
15 | // |
16 | // The first two arguments to all TRACE macros are the category and name. Both are strings, and |
17 | // must have application lifetime (statics or literals). The same applies to arg_names, and string |
18 | // argument values. However, you can force a copy of a string argument value with TRACE_STR_COPY: |
19 | // TRACE_EVENT1("category", "name", "arg1", "literal string is only referenced"); |
20 | // TRACE_EVENT1("category", "name", "arg1", TRACE_STR_COPY("string will be copied")); |
21 | // |
22 | // |
23 | // Categories are used to group events, and |
24 | // can be enabled or disabled by the tracing framework. The trace system will automatically add the |
25 | // process id, thread id, and microsecond timestamp to all events. |
26 | // |
27 | // |
28 | // The TRACE_EVENT[0-2] macros trace the duration of entire scopes: |
29 | // void doSomethingCostly() { |
30 | // TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly"); |
31 | // ... |
32 | // } |
33 | // |
34 | // Additional parameters can be associated with an event: |
35 | // void doSomethingCostly2(int howMuch) { |
36 | // TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly", "howMuch", howMuch); |
37 | // ... |
38 | // } |
39 | // |
40 | // |
41 | // Trace event also supports counters, which is a way to track a quantity as it varies over time. |
42 | // Counters are created with the following macro: |
43 | // TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue); |
44 | // |
45 | // Counters are process-specific. The macro itself can be issued from any thread, however. |
46 | // |
47 | // Sometimes, you want to track two counters at once. You can do this with two counter macros: |
48 | // TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]); |
49 | // TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]); |
50 | // Or you can do it with a combined macro: |
51 | // TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter", |
52 | // "bytesPinned", g_myCounterValue[0], |
53 | // "bytesAllocated", g_myCounterValue[1]); |
54 | // The tracing UI will show these counters in a single graph, as a summed area chart. |
55 | |
56 | #if defined(TRACE_EVENT0) |
57 | #error "Another copy of this file has already been included." |
58 | #endif |
59 | |
60 | #define TRACE_EMPTY do {} while (0) |
61 | |
62 | #ifdef SK_DISABLE_TRACING |
63 | |
64 | #define ATRACE_ANDROID_FRAMEWORK(fmt, ...) TRACE_EMPTY |
65 | #define ATRACE_ANDROID_FRAMEWORK_ALWAYS(fmt, ...) TRACE_EMPTY |
66 | #define TRACE_EVENT0(cg, n) TRACE_EMPTY |
67 | #define TRACE_EVENT1(cg, n, a1n, a1v) TRACE_EMPTY |
68 | #define TRACE_EVENT2(cg, n, a1n, a1v, a2n, a2v) TRACE_EMPTY |
69 | #define TRACE_EVENT_INSTANT0(cg, n, scope) TRACE_EMPTY |
70 | #define TRACE_EVENT_INSTANT1(cg, n, scope, a1n, a1v) TRACE_EMPTY |
71 | #define TRACE_EVENT_INSTANT2(cg, n, scope, a1n, a1v, a2n, a2v) TRACE_EMPTY |
72 | #define TRACE_COUNTER1(cg, n, value) TRACE_EMPTY |
73 | #define TRACE_COUNTER2(cg, n, v1n, v1v, v2n, v2v) TRACE_EMPTY |
74 | |
75 | #elif defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) |
76 | |
77 | #include <cutils/trace.h> |
78 | #include <stdarg.h> |
79 | |
80 | class SkAndroidFrameworkTraceUtil { |
81 | public: |
82 | SkAndroidFrameworkTraceUtil(const char* name) { |
83 | if (CC_UNLIKELY(gEnableAndroidTracing)) { |
84 | ATRACE_BEGIN(name); |
85 | } |
86 | } |
87 | SkAndroidFrameworkTraceUtil(bool, const char* fmt, ...) { |
88 | if (CC_LIKELY((!gEnableAndroidTracing) || (!ATRACE_ENABLED()))) return; |
89 | |
90 | const int BUFFER_SIZE = 256; |
91 | va_list ap; |
92 | char buf[BUFFER_SIZE]; |
93 | |
94 | va_start(ap, fmt); |
95 | vsnprintf(buf, BUFFER_SIZE, fmt, ap); |
96 | va_end(ap); |
97 | |
98 | ATRACE_BEGIN(buf); |
99 | } |
100 | ~SkAndroidFrameworkTraceUtil() { |
101 | if (CC_UNLIKELY(gEnableAndroidTracing)) { |
102 | ATRACE_END(); |
103 | } |
104 | } |
105 | |
106 | static void setEnableTracing(bool enableAndroidTracing) { |
107 | gEnableAndroidTracing = enableAndroidTracing; |
108 | } |
109 | |
110 | static bool getEnableTracing() { |
111 | return gEnableAndroidTracing; |
112 | } |
113 | |
114 | private: |
115 | static bool gEnableAndroidTracing; |
116 | }; |
117 | |
118 | class SkAndroidFrameworkTraceUtilAlways { |
119 | public: |
120 | SkAndroidFrameworkTraceUtilAlways(const char* fmt, ...) { |
121 | if (!ATRACE_ENABLED()) return; |
122 | |
123 | const int BUFFER_SIZE = 256; |
124 | va_list ap; |
125 | char buf[BUFFER_SIZE]; |
126 | |
127 | va_start(ap, fmt); |
128 | vsnprintf(buf, BUFFER_SIZE, fmt, ap); |
129 | va_end(ap); |
130 | |
131 | ATRACE_BEGIN(buf); |
132 | } |
133 | ~SkAndroidFrameworkTraceUtilAlways() { |
134 | ATRACE_END(); |
135 | } |
136 | }; |
137 | |
138 | #define ATRACE_ANDROID_FRAMEWORK(fmt, ...) SkAndroidFrameworkTraceUtil __trace(true, fmt, ##__VA_ARGS__) |
139 | #define ATRACE_ANDROID_FRAMEWORK_ALWAYS(fmt, ...) SkAndroidFrameworkTraceUtilAlways __trace_always(fmt, ##__VA_ARGS__) |
140 | |
141 | // Records a pair of begin and end events called "name" for the current scope, with 0, 1 or 2 |
142 | // associated arguments. In the framework, the arguments are ignored. |
143 | #define TRACE_EVENT0(category_group, name) \ |
144 | SkAndroidFrameworkTraceUtil __trace(name) |
145 | #define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \ |
146 | SkAndroidFrameworkTraceUtil __trace(name) |
147 | #define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \ |
148 | SkAndroidFrameworkTraceUtil __trace(name) |
149 | |
150 | // Records a single event called "name" immediately, with 0, 1 or 2 associated arguments. If the |
151 | // category is not enabled, then this does nothing. |
152 | #define TRACE_EVENT_INSTANT0(category_group, name, scope) \ |
153 | do { SkAndroidFrameworkTraceUtil __trace(name); } while(0) |
154 | |
155 | #define TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val) \ |
156 | do { SkAndroidFrameworkTraceUtil __trace(name); } while(0) |
157 | |
158 | #define TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val, \ |
159 | arg2_name, arg2_val) \ |
160 | do { SkAndroidFrameworkTraceUtil __trace(name); } while(0) |
161 | |
162 | // Records the value of a counter called "name" immediately. Value |
163 | // must be representable as a 32 bit integer. |
164 | #define TRACE_COUNTER1(category_group, name, value) \ |
165 | if (CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) { \ |
166 | ATRACE_INT(name, value); \ |
167 | } |
168 | |
169 | // Records the values of a multi-parted counter called "name" immediately. |
170 | // In Chrome, this macro produces a stacked bar chart. ATrace doesn't support |
171 | // that, so this just produces two separate counters. |
172 | #define TRACE_COUNTER2(category_group, name, value1_name, value1_val, value2_name, value2_val) \ |
173 | do { \ |
174 | if (CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) { \ |
175 | ATRACE_INT(name "-" value1_name, value1_val); \ |
176 | ATRACE_INT(name "-" value2_name, value2_val); \ |
177 | } \ |
178 | } while (0) |
179 | |
180 | // ATrace has no object tracking |
181 | #define TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group, name, id) TRACE_EMPTY |
182 | #define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group, name, id, snapshot) TRACE_EMPTY |
183 | #define TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group, name, id) TRACE_EMPTY |
184 | |
185 | // Macro to efficiently determine if a given category group is enabled. |
186 | // This is only used for some shader text logging that isn't supported in ATrace anyway. |
187 | #define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \ |
188 | do { *ret = false; } while (0) |
189 | |
190 | #else // !SK_BUILD_FOR_ANDROID_FRAMEWORK && !SK_DISABLE_TRACING |
191 | |
192 | #define ATRACE_ANDROID_FRAMEWORK(fmt, ...) TRACE_EMPTY |
193 | #define ATRACE_ANDROID_FRAMEWORK_ALWAYS(fmt, ...) TRACE_EMPTY |
194 | |
195 | // Records a pair of begin and end events called "name" for the current scope, with 0, 1 or 2 |
196 | // associated arguments. If the category is not enabled, then this does nothing. |
197 | #define TRACE_EVENT0(category_group, name) \ |
198 | INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name) |
199 | |
200 | #define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \ |
201 | INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val) |
202 | |
203 | #define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \ |
204 | INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) |
205 | |
206 | // Records a single event called "name" immediately, with 0, 1 or 2 associated arguments. If the |
207 | // category is not enabled, then this does nothing. |
208 | #define TRACE_EVENT_INSTANT0(category_group, name, scope) \ |
209 | INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \ |
210 | TRACE_EVENT_FLAG_NONE | scope) |
211 | |
212 | #define TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val) \ |
213 | INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \ |
214 | TRACE_EVENT_FLAG_NONE | scope, arg1_name, arg1_val) |
215 | |
216 | #define TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val, \ |
217 | arg2_name, arg2_val) \ |
218 | INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \ |
219 | TRACE_EVENT_FLAG_NONE | scope, arg1_name, arg1_val, \ |
220 | arg2_name, arg2_val) |
221 | |
222 | // Records the value of a counter called "name" immediately. Value |
223 | // must be representable as a 32 bit integer. |
224 | #define TRACE_COUNTER1(category_group, name, value) \ |
225 | INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \ |
226 | TRACE_EVENT_FLAG_NONE, "value", \ |
227 | static_cast<int>(value)) |
228 | |
229 | // Records the values of a multi-parted counter called "name" immediately. |
230 | // The UI will treat value1 and value2 as parts of a whole, displaying their |
231 | // values as a stacked-bar chart. |
232 | #define TRACE_COUNTER2(category_group, name, value1_name, value1_val, \ |
233 | value2_name, value2_val) \ |
234 | INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \ |
235 | TRACE_EVENT_FLAG_NONE, value1_name, \ |
236 | static_cast<int>(value1_val), value2_name, \ |
237 | static_cast<int>(value2_val)) |
238 | |
239 | #define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \ |
240 | INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ |
241 | TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, TRACE_EVENT_FLAG_NONE) |
242 | #define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \ |
243 | INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ |
244 | category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) |
245 | #define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \ |
246 | INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ |
247 | category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val) |
248 | |
249 | #define TRACE_EVENT_ASYNC_END0(category, name, id) \ |
250 | INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ |
251 | category, name, id, TRACE_EVENT_FLAG_NONE) |
252 | #define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \ |
253 | INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ |
254 | category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) |
255 | #define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \ |
256 | INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ |
257 | category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val) |
258 | |
259 | // Macros to track the life time and value of arbitrary client objects. |
260 | #define TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group, name, id) \ |
261 | INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ |
262 | TRACE_EVENT_PHASE_CREATE_OBJECT, category_group, name, id, \ |
263 | TRACE_EVENT_FLAG_NONE) |
264 | |
265 | #define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group, name, id, \ |
266 | snapshot) \ |
267 | INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ |
268 | TRACE_EVENT_PHASE_SNAPSHOT_OBJECT, category_group, name, \ |
269 | id, TRACE_EVENT_FLAG_NONE, "snapshot", snapshot) |
270 | |
271 | #define TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group, name, id) \ |
272 | INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ |
273 | TRACE_EVENT_PHASE_DELETE_OBJECT, category_group, name, id, \ |
274 | TRACE_EVENT_FLAG_NONE) |
275 | |
276 | // Macro to efficiently determine if a given category group is enabled. |
277 | #define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \ |
278 | do { \ |
279 | INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ |
280 | if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ |
281 | *ret = true; \ |
282 | } else { \ |
283 | *ret = false; \ |
284 | } \ |
285 | } while (0) |
286 | |
287 | #endif |
288 | |
289 | // Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT. |
290 | #define TRACE_EVENT_FLAG_NONE (static_cast<unsigned int>(0)) |
291 | #define TRACE_EVENT_FLAG_COPY (static_cast<unsigned int>(1 << 0)) |
292 | #define TRACE_EVENT_FLAG_HAS_ID (static_cast<unsigned int>(1 << 1)) |
293 | #define TRACE_EVENT_FLAG_MANGLE_ID (static_cast<unsigned int>(1 << 2)) |
294 | #define TRACE_EVENT_FLAG_SCOPE_OFFSET (static_cast<unsigned int>(1 << 3)) |
295 | #define (static_cast<unsigned int>(1 << 4)) |
296 | #define TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP (static_cast<unsigned int>(1 << 5)) |
297 | #define TRACE_EVENT_FLAG_ASYNC_TTS (static_cast<unsigned int>(1 << 6)) |
298 | #define TRACE_EVENT_FLAG_BIND_TO_ENCLOSING (static_cast<unsigned int>(1 << 7)) |
299 | #define TRACE_EVENT_FLAG_FLOW_IN (static_cast<unsigned int>(1 << 8)) |
300 | #define TRACE_EVENT_FLAG_FLOW_OUT (static_cast<unsigned int>(1 << 9)) |
301 | #define TRACE_EVENT_FLAG_HAS_CONTEXT_ID (static_cast<unsigned int>(1 << 10)) |
302 | |
303 | #define TRACE_EVENT_FLAG_SCOPE_MASK \ |
304 | (static_cast<unsigned int>(TRACE_EVENT_FLAG_SCOPE_OFFSET | \ |
305 | TRACE_EVENT_FLAG_SCOPE_EXTRA)) |
306 | |
307 | // Type values for identifying types in the TraceValue union. |
308 | #define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1)) |
309 | #define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2)) |
310 | #define TRACE_VALUE_TYPE_INT (static_cast<unsigned char>(3)) |
311 | #define TRACE_VALUE_TYPE_DOUBLE (static_cast<unsigned char>(4)) |
312 | #define TRACE_VALUE_TYPE_POINTER (static_cast<unsigned char>(5)) |
313 | #define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6)) |
314 | #define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(7)) |
315 | #define TRACE_VALUE_TYPE_CONVERTABLE (static_cast<unsigned char>(8)) |
316 | |
317 | // Enum reflecting the scope of an INSTANT event. Must fit within TRACE_EVENT_FLAG_SCOPE_MASK. |
318 | #define TRACE_EVENT_SCOPE_GLOBAL (static_cast<unsigned char>(0 << 3)) |
319 | #define TRACE_EVENT_SCOPE_PROCESS (static_cast<unsigned char>(1 << 3)) |
320 | #define TRACE_EVENT_SCOPE_THREAD (static_cast<unsigned char>(2 << 3)) |
321 | |
322 | #define TRACE_EVENT_SCOPE_NAME_GLOBAL ('g') |
323 | #define TRACE_EVENT_SCOPE_NAME_PROCESS ('p') |
324 | #define TRACE_EVENT_SCOPE_NAME_THREAD ('t') |
325 | |
326 | #endif // SkTraceEventCommon_DEFINED |
327 | |