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
80class SkAndroidFrameworkTraceUtil {
81public:
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
114private:
115 static bool gEnableAndroidTracing;
116};
117
118class SkAndroidFrameworkTraceUtilAlways {
119public:
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 TRACE_EVENT_FLAG_SCOPE_EXTRA (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