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 // --- Temporary Perfetto migration shim preamble ---
61 // Tracing in the Android framework, and tracing with Perfetto, are both in a partially migrated
62 // state (but fully functional).
63 //
64 // See go/skia-perfetto
65 //
66 // For Android framework:
67 // ---
68 // 1. If SK_ANDROID_FRAMEWORK_USE_PERFETTO is not defined, then all tracing macros map to no-ops.
69 // This is only relevant to host-mode builds, where ATrace isn't supported anyway, and tracing with
70 // Perfetto seems unnecessary. Note that SkAndroidFrameworkTraceUtil is still defined (assuming
71 // SK_BUILD_FOR_ANDROID_FRAMEWORK is defined) to support HWUI referencing it in host-mode builds.
72 //
73 // 2. If SK_ANDROID_FRAMEWORK_USE_PERFETTO *is* defined, then the tracing backend can be switched
74 // between ATrace and Perfetto at runtime. This is currently *only* supported in Android framework.
75 // SkAndroidFrameworkTraceUtil::setEnableTracing(bool) will still control broad tracing overall, but
76 // SkAndroidFrameworkTraceUtil::setUsePerfettoTrackEvents(bool) will now determine whether that
77 // tracing is done with ATrace (default/false) or Perfetto (true).
78 //
79 // Note: if setUsePerfettoTrackEvents(true) is called, then Perfetto will remain initialized until
80 // the process ends. This means some minimal state overhead will remain even after subseqently
81 // switching the process back to ATrace, but individual trace events will be correctly routed to
82 // whichever system is active in the moment. However, trace events which have begun but have not yet
83 // ended when a switch occurs will likely be corrupted. Thus, it's best to minimize the frequency of
84 // switching backend tracing systems at runtime.
85 //
86 // For Perfetto outside of Android framework (e.g. tools):
87 // ---
88 // SK_USE_PERFETTO (mutually exclusive with SK_ANDROID_FRAMEWORK_USE_PERFETTO) can be used to unlock
89 // SkPerfettoTrace, which can be used for in-process tracing via the standard Skia tracing flow of
90 // SkEventTracer::SetInstance(...). This is enabled in tools with the `--trace perfetto` argument.
91 // See https://skia.org/docs/dev/tools/tracing/#tracing-with-perfetto for more on SK_USE_PERFETTO.
92
93 #ifdef SK_ANDROID_FRAMEWORK_USE_PERFETTO
94
95 // PERFETTO_TRACK_EVENT_NAMESPACE must be defined before including Perfetto. This allows Skia to
96 // maintain separate "track event" category storage, etc. from codebases linked into the same
97 // executable, and avoid symbol duplication errors.
98 //
99 // NOTE: A side-effect of this is we must use skia::TrackEvent instead of perfetto::TrackEvent.
100 #define PERFETTO_TRACK_EVENT_NAMESPACE skia
101 #include <perfetto/tracing.h>
102
103 #include <cutils/trace.h>
104 #include <stdarg.h>
105 #include <string_view>
106
107 // WARNING: this list must be kept up to date with every category we use for tracing!
108 //
109 // When adding a new category it's likely best to add both "new_category" and "new_category.always",
110 // though not strictly required. "new_category.always" is used internally when "new_category" is
111 // given to TRACE_EVENTx_ALWAYS macros, which are used for core events that should always show up in
112 // traces for the Android framework. Adding both to begin with will likely reduce churn if/when
113 // "new_category" is used across both normal tracing macros and _ALWAYS variants in the future, but
114 // it's not a strict requirement.
115 //
116 // See stages section of go/skia-perfetto for timeline of when this should improve.
117 //
118 // TODO(b/262718654): make this compilation failure happen sooner than the Skia -> Android roll.
119 //
120 // Currently kept entirely separate from SkPerfettoTrace for simplicity, which uses dynamic
121 // categories and doesn't need these static category definitions.
122 PERFETTO_DEFINE_CATEGORIES(
123 perfetto::Category("GM"),
124 perfetto::Category("skia"),
125 perfetto::Category("skia.android"),
126 perfetto::Category("skia.gpu"),
127 perfetto::Category("skia.gpu.cache"),
128 perfetto::Category("skia.objects"),
129 perfetto::Category("skia.shaders"),
130 perfetto::Category("skottie"),
131 perfetto::Category("test"),
132 perfetto::Category("test_cpu"),
133 perfetto::Category("test_ganesh"),
134 perfetto::Category("test_graphite"),
135 // ".always" variants are currently required for any category used in TRACE_EVENTx_ALWAYS.
136 perfetto::Category("GM.always").SetTags("skia.always"),
137 perfetto::Category("skia.always").SetTags("skia.always"),
138 perfetto::Category("skia.android.always").SetTags("skia.always"),
139 perfetto::Category("skia.gpu.always").SetTags("skia.always"),
140 perfetto::Category("skia.gpu.cache.always").SetTags("skia.always"),
141 perfetto::Category("skia.objects.always").SetTags("skia.always"),
142 perfetto::Category("skia.shaders.always").SetTags("skia.always"),
143 perfetto::Category("skottie.always").SetTags("skia.always"),
144 perfetto::Category("test.always").SetTags("skia.always"),
145 perfetto::Category("test_cpu.always").SetTags("skia.always"),
146 perfetto::Category("test_ganesh.always").SetTags("skia.always"),
147 perfetto::Category("test_graphite.always").SetTags("skia.always"),
148 );
149
150 #endif // SK_ANDROID_FRAMEWORK_USE_PERFETTO
151
152 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
153
154 #ifdef SK_DISABLE_TRACING
155 #error SK_DISABLE_TRACING and SK_BUILD_FOR_ANDROID_FRAMEWORK are mutually exclusive.
156 #endif // SK_DISABLE_TRACING [&& SK_BUILD_FOR_ANDROID_FRAMEWORK]
157
158 #define SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE 512
159
160 class SkAndroidFrameworkTraceUtil {
161 public:
162 SkAndroidFrameworkTraceUtil() = delete;
163
164 // Controls whether broad tracing is enabled. Warning: not thread-safe!
165 //
166 // Some key trace events may still be recorded when this is disabled, if a relevant tracing
167 // session is active.
168 //
169 // ATrace is used by default, but can be replaced with Perfetto by calling
170 // setUsePerfettoTrackEvents(true)
setEnableTracing(bool enableAndroidTracing)171 static void setEnableTracing(bool enableAndroidTracing) {
172 gEnableAndroidTracing = enableAndroidTracing;
173 }
174
175 // Controls whether tracing uses Perfetto instead of ATrace. Warning: not thread-safe!
176 //
177 // Returns true if Skia was built with Perfetto, false otherwise.
setUsePerfettoTrackEvents(bool usePerfettoTrackEvents)178 static bool setUsePerfettoTrackEvents(bool usePerfettoTrackEvents) {
179 #ifdef SK_ANDROID_FRAMEWORK_USE_PERFETTO
180 // Ensure Perfetto is initialized if it wasn't already the preferred tracing backend.
181 if (!gUsePerfettoTrackEvents && usePerfettoTrackEvents) {
182 initPerfetto();
183 }
184 gUsePerfettoTrackEvents = usePerfettoTrackEvents;
185 return true;
186 #else // !SK_ANDROID_FRAMEWORK_USE_PERFETTO
187 return false;
188 #endif // SK_ANDROID_FRAMEWORK_USE_PERFETTO
189 }
190
getEnableTracing()191 static bool getEnableTracing() {
192 return gEnableAndroidTracing;
193 }
194
getUsePerfettoTrackEvents()195 static bool getUsePerfettoTrackEvents() {
196 return gUsePerfettoTrackEvents;
197 }
198
199 private:
200 static bool gEnableAndroidTracing;
201 static bool gUsePerfettoTrackEvents;
202
203 #ifdef SK_ANDROID_FRAMEWORK_USE_PERFETTO
204 // Initializes tracing systems, and establishes a connection to the 'traced' daemon.
205 //
206 // Can be called multiple times.
initPerfetto()207 static void initPerfetto() {
208 ::perfetto::TracingInitArgs perfettoArgs;
209 perfettoArgs.backends |= perfetto::kSystemBackend;
210 ::perfetto::Tracing::Initialize(perfettoArgs);
211 ::skia::TrackEvent::Register();
212 }
213 #endif // SK_ANDROID_FRAMEWORK_USE_PERFETTO
214 };
215 #endif // SK_BUILD_FOR_ANDROID_FRAMEWORK
216
217 #ifdef SK_DEBUG
218 static void skprintf_like_noop(const char format[], ...) SK_PRINTF_LIKE(1, 2);
skprintf_like_noop(const char format[],...)219 static inline void skprintf_like_noop(const char format[], ...) {}
220 template <typename... Args>
sk_noop(Args...)221 static inline void sk_noop(Args...) {}
222 #define TRACE_EMPTY(...) do { sk_noop(__VA_ARGS__); } while (0)
223 #define TRACE_EMPTY_FMT(fmt, ...) do { skprintf_like_noop(fmt, ##__VA_ARGS__); } while (0)
224 #else
225 #define TRACE_EMPTY(...) do {} while (0)
226 #define TRACE_EMPTY_FMT(fmt, ...) do {} while (0)
227 #endif
228
229 #if defined(SK_DISABLE_TRACING) || \
230 (defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) && !defined(SK_ANDROID_FRAMEWORK_USE_PERFETTO))
231
232 #define ATRACE_ANDROID_FRAMEWORK(fmt, ...) TRACE_EMPTY_FMT(fmt, ##__VA_ARGS__)
233 #define ATRACE_ANDROID_FRAMEWORK_ALWAYS(fmt, ...) TRACE_EMPTY_FMT(fmt, ##__VA_ARGS__)
234 #define TRACE_EVENT0(cg, n) TRACE_EMPTY(cg, n)
235 #define TRACE_EVENT1(cg, n, a1n, a1v) TRACE_EMPTY(cg, n, a1n, a1v)
236 #define TRACE_EVENT2(cg, n, a1n, a1v, a2n, a2v) TRACE_EMPTY(cg, n, a1n, a1v, a2n, a2v)
237 #define TRACE_EVENT0_ALWAYS(cg, n) TRACE_EMPTY(cg, n)
238 #define TRACE_EVENT1_ALWAYS(cg, n, a1n, a1v) TRACE_EMPTY(cg, n, a1n, a1v)
239 #define TRACE_EVENT2_ALWAYS(cg, n, a1n, a1v, a2n, a2v) TRACE_EMPTY(cg, n, a1n, a1v, a2n, a2v)
240 #define TRACE_EVENT_INSTANT0(cg, n, scope) TRACE_EMPTY(cg, n, scope)
241 #define TRACE_EVENT_INSTANT1(cg, n, scope, a1n, a1v) TRACE_EMPTY(cg, n, scope, a1n, a1v)
242 #define TRACE_EVENT_INSTANT2(cg, n, scope, a1n, a1v, a2n, a2v) \
243 TRACE_EMPTY(cg, n, scope, a1n, a1v, a2n, a2v)
244 #define TRACE_EVENT_OBJECT_CREATED_WITH_ID(cg, n, id) TRACE_EMPTY(cg, n, id)
245 #define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(cg, n, id, ss) TRACE_EMPTY(cg, n, id, ss)
246 #define TRACE_EVENT_OBJECT_DELETED_WITH_ID(cg, n, id) TRACE_EMPTY(cg, n, id)
247 #define TRACE_COUNTER1(cg, n, value) TRACE_EMPTY(cg, n, value)
248 #define TRACE_COUNTER2(cg, n, v1n, v1v, v2n, v2v) TRACE_EMPTY(cg, n, v1n, v1v, v2n, v2v)
249
250 #elif defined(SK_ANDROID_FRAMEWORK_USE_PERFETTO)
251
252 namespace skia_private {
253 // ATrace can't accept ::perfetto::DynamicString or ::perfetto::StaticString, so any trace event
254 // names that were wrapped in TRACE_STR_COPY or TRACE_STR_STATIC need to be unboxed back to
255 // char* before being passed to ATrace.
UnboxPerfettoString(const::perfetto::DynamicString & str)256 inline const char* UnboxPerfettoString(const ::perfetto::DynamicString& str) {
257 return str.value;
258 }
UnboxPerfettoString(const::perfetto::StaticString & str)259 inline const char* UnboxPerfettoString(const ::perfetto::StaticString& str) {
260 return str.value;
261 }
UnboxPerfettoString(const char * str)262 inline const char* UnboxPerfettoString(const char* str) {
263 return str;
264 }
265
266 // WrapTraceArgInStdString serves a similar purpose to UnboxPerfettoString, but also accepts
267 // numeric values that are often used as trace arguments. This necessitates always wrapping the
268 // argument in a new std::string, instead of just passing along/unboxing an existing C-style
269 // string. This comes at a slight cost, and should only be used for trace slice arguments but
270 // not slice names, where UnboxPerfettoString should be used instead.
271 template<typename T>
WrapTraceArgInStdString(const T numeric)272 inline std::string WrapTraceArgInStdString(const T numeric) {
273 return std::to_string(numeric);
274 }
WrapTraceArgInStdString(const::perfetto::DynamicString & str)275 inline std::string WrapTraceArgInStdString(const ::perfetto::DynamicString& str) {
276 return std::string(str.value);
277 }
WrapTraceArgInStdString(const::perfetto::StaticString & str)278 inline std::string WrapTraceArgInStdString(const ::perfetto::StaticString& str) {
279 return std::string(str.value);
280 }
WrapTraceArgInStdString(const char * str)281 inline std::string WrapTraceArgInStdString(const char* str) {
282 return std::string(str);
283 }
284
StrEndsWithAndLongerThan(const char * str,const char * suffix)285 constexpr bool StrEndsWithAndLongerThan(const char* str, const char* suffix) {
286 auto strView = std::basic_string_view(str);
287 auto suffixView = std::basic_string_view(suffix);
288 // string_view::ends_with isn't available until C++20
289 return strView.size() > suffixView.size() &&
290 strView.compare(strView.size() - suffixView.size(),
291 std::string_view::npos, suffixView) == 0;
292 }
293 }
294
295 // Generate a unique variable name with a given prefix.
296 // The indirection in this multi-level macro lets __LINE__ expand at the right time/place to get
297 // prefix123 instead of prefix__LINE__.
298 #define SK_PERFETTO_INTERNAL_CONCAT2(a, b) a##b
299 #define SK_PERFETTO_INTERNAL_CONCAT(a, b) SK_PERFETTO_INTERNAL_CONCAT2(a, b)
300 #define SK_PERFETTO_UID(prefix) SK_PERFETTO_INTERNAL_CONCAT(prefix, __LINE__)
301
302 // Used by SK_INTERNAL_ATRACE_ARGS_BEGIN and SK_INTERNAL_ATRACE_ARGS_END to select which overloaded
303 // macro to use depending on how many __VA_ARGS__ are present. The number of __VA_ARGS__ piped in
304 // from this macro caller's parent caller determines which macro name given by the caller ends up in
305 // the macro_name slot here. See usage for nuance.
306 #define SK_INTERNAL_GET_ATRACE_ARGS_MACRO(_0, _1a, _1b, _2a, _2b, macro_name, ...) macro_name
307
308 // WARNING: must always be guarded by an outer call to CC_UNLIKELY(ATRACE_ENABLED())
309 #define SK_INTERNAL_ATRACE_ARGS_BEGIN_DANGEROUS_0(name) \
310 atrace_begin_body(::skia_private::UnboxPerfettoString(name));
311
312 // WARNING: must always be guarded by an outer call to CC_UNLIKELY(ATRACE_ENABLED())
313 #define SK_INTERNAL_ATRACE_ARGS_BEGIN_DANGEROUS_1(name, arg1_name, arg1_val) \
314 char SK_PERFETTO_UID(skTraceStrBuf1)[SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE]; \
315 snprintf(SK_PERFETTO_UID(skTraceStrBuf1), \
316 SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE, \
317 "^(%s: %s)", \
318 ::skia_private::UnboxPerfettoString(arg1_name), \
319 ::skia_private::WrapTraceArgInStdString(arg1_val).c_str()); \
320 atrace_begin_body(::skia_private::UnboxPerfettoString(name)); \
321 atrace_begin_body(SK_PERFETTO_UID(skTraceStrBuf1));
322
323 // WARNING: must always be guarded by an outer call to CC_UNLIKELY(ATRACE_ENABLED())
324 #define SK_INTERNAL_ATRACE_ARGS_BEGIN_DANGEROUS_2( \
325 name, arg1_name, arg1_val, arg2_name, arg2_val, ...) \
326 char SK_PERFETTO_UID(skTraceStrBuf1)[SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE]; \
327 char SK_PERFETTO_UID(skTraceStrBuf2)[SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE]; \
328 snprintf(SK_PERFETTO_UID(skTraceStrBuf1), \
329 SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE, \
330 "^(%s: %s)", \
331 ::skia_private::UnboxPerfettoString(arg1_name), \
332 ::skia_private::WrapTraceArgInStdString(arg1_val).c_str()); \
333 snprintf(SK_PERFETTO_UID(skTraceStrBuf2), \
334 SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE, \
335 "^(%s: %s)", \
336 ::skia_private::UnboxPerfettoString(arg2_name), \
337 ::skia_private::WrapTraceArgInStdString(arg2_val).c_str()); \
338 atrace_begin_body(::skia_private::UnboxPerfettoString(name)); \
339 atrace_begin_body(SK_PERFETTO_UID(skTraceStrBuf1)); \
340 atrace_begin_body(SK_PERFETTO_UID(skTraceStrBuf2));
341
342 // Will map to either the 0, 1, or 2 argument variant of this macro, which will trigger an
343 // ATRACE_BEGIN event for the slice name, and one for each argument <name, value> pair. The caller
344 // must ensure each of these 1-3 slices are properly terminated with 1-3 matching ATRACE_END events.
345 //
346 // Note: ATRACE_ENABLED() is checked here to allow the actual implmenting macros to avoid redundant
347 // checks within each of their calls to the standard ATRACE_BEGIN() macro, as checking
348 // ATRACE_ENABLED() can be non-trivial. But more importantly, if tracing isn't enabled then we
349 // should avoid the string formatting work required for how we hack "arguments" into separate ATrace
350 // slices.
351 #define SK_INTERNAL_ATRACE_ARGS_BEGIN(slice_name, ...) \
352 if (CC_UNLIKELY(ATRACE_ENABLED())) { \
353 SK_INTERNAL_GET_ATRACE_ARGS_MACRO(0, \
354 ##__VA_ARGS__, \
355 SK_INTERNAL_ATRACE_ARGS_BEGIN_DANGEROUS_2, \
356 0, \
357 SK_INTERNAL_ATRACE_ARGS_BEGIN_DANGEROUS_1, \
358 0, \
359 SK_INTERNAL_ATRACE_ARGS_BEGIN_DANGEROUS_0) \
360 (slice_name, ##__VA_ARGS__); \
361 }
362
363 // WARNING: must always be guarded by an outer call to CC_UNLIKELY(ATRACE_ENABLED())
364 #define SK_INTERNAL_ATRACE_ARGS_END_DANGEROUS_2(arg1_name, arg1_val, arg2_name, arg2_val, ...) \
365 atrace_end_body(); \
366 atrace_end_body(); \
367 atrace_end_body();
368
369 // WARNING: must always be guarded by an outer call to CC_UNLIKELY(ATRACE_ENABLED())
370 #define SK_INTERNAL_ATRACE_ARGS_END_DANGEROUS_1(arg1_name, arg1_val) \
371 atrace_end_body(); \
372 atrace_end_body();
373
374 // WARNING: must always be guarded by an outer call to CC_UNLIKELY(ATRACE_ENABLED())
375 #define SK_INTERNAL_ATRACE_ARGS_END_DANGEROUS_0() \
376 atrace_end_body();
377
378 // Will map to either the 0, 1, or 2 argument variant of this macro, which will trigger an
379 // ATRACE_END event for the slice name, and one for each argument <name, value> pair. The caller
380 // must ensure each of these 1-3 slices already existed from 1-3 matching ATRACE_BEGIN events.
381 //
382 // Note: ATRACE_ENABLED() is checked here to allow the actual implmenting macros to avoid redundant
383 // checks within each of their calls to the standard ATRACE_END() macro, as checking
384 // ATRACE_ENABLED() can be non-trivial.
385 #define SK_INTERNAL_ATRACE_ARGS_END(...) \
386 if (CC_UNLIKELY(ATRACE_ENABLED())) { \
387 SK_INTERNAL_GET_ATRACE_ARGS_MACRO(0, \
388 ##__VA_ARGS__, \
389 SK_INTERNAL_ATRACE_ARGS_END_DANGEROUS_2, \
390 0, \
391 SK_INTERNAL_ATRACE_ARGS_END_DANGEROUS_1, \
392 0, \
393 SK_INTERNAL_ATRACE_ARGS_END_DANGEROUS_0) \
394 (__VA_ARGS__); \
395 }
396
397 // Assuming there is an active tracing session, this call will create a trace event if tracing is
398 // enabled (with SkAndroidFrameworkTraceUtil::setEnableTracing(true)) or if force_always_trace is
399 // true. The event goes through ATrace by default, but can be routed to Perfetto instead by calling
400 // SkAndroidFrameworkTraceUtil::setUsePerfettoTrackEvents(true).
401 //
402 // If ATrace is used, then additional sub-events will be created for each trace event argument
403 // <name, value> pair (up to a max of two argument pairs). If Perfetto is used, then any arguments
404 // will be associated with a single event. In either case, trace arguments will only be evaluated if
405 // the event will actually be recorded in the underlying tracing system (i.e. if an applicable
406 // tracing session is active.)
407 //
408 // If force_always_trace = true, then the caller *must* append the ".always" suffix to the provided
409 // category. This allows Perfetto tracing sessions to optionally filter to just the "skia.always"
410 // category tag. This requirement is enforced at compile time.
411 #define TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE(force_always_trace, category, name, ...) \
412 struct SK_PERFETTO_UID(ScopedEvent) { \
413 struct EventFinalizer { \
414 /* The ... parameter slot is an implementation detail. It allows the */ \
415 /* anonymous struct to use aggregate initialization to invoke the */ \
416 /* lambda (which emits the BEGIN event and returns an integer) */ \
417 /* with the proper reference capture for any */ \
418 /* TrackEventArgumentFunction in |__VA_ARGS__|. This is required so */ \
419 /* that the scoped event is exactly ONE line and can't escape the */ \
420 /* scope if used in a single line if statement. */ \
421 EventFinalizer(...) {} \
422 ~EventFinalizer() { \
423 if (force_always_trace || \
424 CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) { \
425 if (SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents()) { \
426 TRACE_EVENT_END(category); \
427 } else { \
428 SK_INTERNAL_ATRACE_ARGS_END(__VA_ARGS__); \
429 } \
430 } \
431 } \
432 \
433 EventFinalizer(const EventFinalizer&) = delete; \
434 EventFinalizer& operator=(const EventFinalizer&) = delete; \
435 \
436 EventFinalizer(EventFinalizer&&) = default; \
437 EventFinalizer& operator=(EventFinalizer&&) = delete; \
438 } finalizer; \
439 } SK_PERFETTO_UID(scoped_event) { \
440 [&]() { \
441 static_assert(!force_always_trace || \
442 ::skia_private::StrEndsWithAndLongerThan(category, ".always"), \
443 "[force_always_trace == true] requires [category] to end in '.always'"); \
444 if (force_always_trace || \
445 CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) { \
446 if (SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents()) { \
447 TRACE_EVENT_BEGIN(category, name, ##__VA_ARGS__); \
448 } else { \
449 SK_INTERNAL_ATRACE_ARGS_BEGIN(name, ##__VA_ARGS__); \
450 } \
451 } \
452 return 0; \
453 }() \
454 }
455
456 // Records an event with the current tracing backend if overall tracing is enabled, and Skia's
457 // "broad" tracing is enabled with SkAndroidFrameworkTraceUtil::setEnableTracing(true).
458 #define TRACE_EVENT_ATRACE_OR_PERFETTO(category, name, ...) \
459 TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE( \
460 /* force_always_trace = */ false, category, name, ##__VA_ARGS__)
461
462 // Traces a formatted string if overall tracing is enabled, and Skia's "broad" tracing is enabled
463 // with SkAndroidFrameworkTraceUtil::setEnableTracing(true).
464 // No-op outside of Android framework builds.
465 // WARNING: this macro expands to a multi-line statement, and must not be used in a single line
466 // control statement!
467 #define ATRACE_ANDROID_FRAMEWORK(fmt, ...) \
468 char SK_PERFETTO_UID(skTraceStrBuf)[SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE]; \
469 if (SkAndroidFrameworkTraceUtil::getEnableTracing()) { \
470 snprintf(SK_PERFETTO_UID(skTraceStrBuf), SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE, \
471 fmt, ##__VA_ARGS__); \
472 } \
473 TRACE_EVENT0("skia.android", TRACE_STR_COPY(SK_PERFETTO_UID(skTraceStrBuf)))
474
475 // Traces a formatted string as long as overall tracing is enabled, even if Skia's "broad" tracing
476 // is disabled.
477 // No-op outside of Android framework builds.
478 // WARNING: this macro expands to a multi-line statement, and must not be used in a single line
479 // control statement!
480 #define ATRACE_ANDROID_FRAMEWORK_ALWAYS(fmt, ...) \
481 char SK_PERFETTO_UID(skTraceStrBuf)[SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE]; \
482 snprintf(SK_PERFETTO_UID(skTraceStrBuf), SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE, \
483 fmt, ##__VA_ARGS__); \
484 TRACE_EVENT0_ALWAYS("skia.android", TRACE_STR_COPY(SK_PERFETTO_UID(skTraceStrBuf)))
485
486 // Records a pair of begin and end events called "name" (with 0-2 associated arguments) for the
487 // current scope as long as overall tracing is enabled, and Skia's "broad" tracing is enabled with
488 // SkAndroidFrameworkTraceUtil::setEnableTracing(true).
489 // Note that ATrace does not natively support trace arguments, so arguments are recorded as separate
490 // sub-events when ATrace is set as the current tracing backend. The Perfetto tracing backend
491 // associates any arguments with a single event / slice.
492 #define TRACE_EVENT0(category_group, name) \
493 TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name)
494 #define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \
495 TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name, arg1_name, arg1_val)
496 #define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \
497 TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
498
499 // Records a pair of begin and end events called "name" (with 0-2 associated arguments) for the
500 // current scope as long as overall tracing is enabled, even if Skia's "broad" tracing is disabled.
501 // Note that ATrace does not natively support trace arguments, so arguments are recorded as separate
502 // sub-events when ATrace is set as the current tracing backend. The Perfetto tracing backend
503 // associates any arguments with a single event / slice.
504 // Note: the ".always" suffix is appended to category_group in _ALWAYS trace event macro variants.
505 #define TRACE_EVENT0_ALWAYS(category_group, name) \
506 TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE( \
507 /* force_always_trace = */ true, category_group ".always", name)
508 #define TRACE_EVENT1_ALWAYS(category_group, name, arg1_name, arg1_val) \
509 TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE( \
510 /* force_always_trace = */ true, category_group ".always", name, arg1_name, arg1_val)
511 #define TRACE_EVENT2_ALWAYS(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \
512 TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE(/* force_always_trace = */ true, \
513 category_group ".always", \
514 name, \
515 arg1_name, \
516 arg1_val, \
517 arg2_name, \
518 arg2_val)
519
520 // Records a single event called "name" immediately, with 0, 1 or 2 associated arguments.
521 // Note that ATrace does not support trace arguments, so they are only recorded when Perfetto is set
522 // as the current tracing backend.
523 #define TRACE_EVENT_INSTANT0(category_group, name, scope) \
524 do { TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name); } while(0)
525
526 #define TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val) \
527 do { TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name, arg1_name, arg1_val); } while(0)
528
529 #define TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val, \
530 arg2_name, arg2_val) \
531 do { TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name, arg1_name, arg1_val, \
532 arg2_name, arg2_val); } while(0)
533
534 // Records the value of a counter called "name" immediately. Value
535 // must be representable as a 32 bit integer.
536 #define TRACE_COUNTER1(category_group, name, value) \
537 if (CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) { \
538 if (SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents()) { \
539 TRACE_COUNTER(category_group, name, value); \
540 } else { \
541 ATRACE_INT(name, value); \
542 } \
543 }
544
545 // Records the values of a multi-parted counter called "name" immediately.
546 // In Chrome, this macro produces a stacked bar chart. Perfetto doesn't support
547 // that (related: b/242349575), so this just produces two separate counters.
548 #define TRACE_COUNTER2(category_group, name, value1_name, value1_val, value2_name, value2_val) \
549 if (CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) { \
550 if (SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents()) { \
551 TRACE_COUNTER(category_group, name "-" value1_name, value1_val); \
552 TRACE_COUNTER(category_group, name "-" value2_name, value2_val); \
553 } else { \
554 ATRACE_INT(name "-" value1_name, value1_val); \
555 ATRACE_INT(name "-" value2_name, value2_val); \
556 } \
557 }
558
559 // ATrace has no object tracking, and would require a legacy shim for Perfetto (which likely no-ops
560 // here). Further, these don't appear to currently be used outside of tests.
561 #define TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group, name, id) \
562 TRACE_EMPTY(category_group, name, id)
563 #define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group, name, id, snapshot) \
564 TRACE_EMPTY(category_group, name, id, snapshot)
565 #define TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group, name, id) \
566 TRACE_EMPTY(category_group, name, id)
567
568 // Macro to efficiently determine if a given category group is enabled. Only works with Perfetto.
569 // This is only used for some shader text logging that isn't supported in ATrace anyway.
570 #define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \
571 if (CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing() && \
572 SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents)) { \
573 *ret = TRACE_EVENT_CATEGORY_ENABLED(category_group); \
574 } else { \
575 *ret = false; \
576 }
577
578 #else // Route through SkEventTracer (!SK_DISABLE_TRACING && !SK_ANDROID_FRAMEWORK_USE_PERFETTO)
579
580 #define ATRACE_ANDROID_FRAMEWORK(fmt, ...) TRACE_EMPTY_FMT(fmt, ##__VA_ARGS__)
581 #define ATRACE_ANDROID_FRAMEWORK_ALWAYS(fmt, ...) TRACE_EMPTY_FMT(fmt, ##__VA_ARGS__)
582
583 // Records a pair of begin and end events called "name" for the current scope, with 0, 1 or 2
584 // associated arguments. If the category is not enabled, then this does nothing.
585 #define TRACE_EVENT0(category_group, name) \
586 INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name)
587
588 #define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \
589 INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val)
590
591 #define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \
592 INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
593
594 #define TRACE_EVENT0_ALWAYS(category_group, name) \
595 INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name)
596
597 #define TRACE_EVENT1_ALWAYS(category_group, name, arg1_name, arg1_val) \
598 INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val)
599
600 #define TRACE_EVENT2_ALWAYS(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \
601 INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
602
603 // Records a single event called "name" immediately, with 0, 1 or 2 associated arguments. If the
604 // category is not enabled, then this does nothing.
605 #define TRACE_EVENT_INSTANT0(category_group, name, scope) \
606 INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
607 TRACE_EVENT_FLAG_NONE | scope)
608
609 #define TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val) \
610 INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
611 TRACE_EVENT_FLAG_NONE | scope, arg1_name, arg1_val)
612
613 #define TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val, \
614 arg2_name, arg2_val) \
615 INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
616 TRACE_EVENT_FLAG_NONE | scope, arg1_name, arg1_val, \
617 arg2_name, arg2_val)
618
619 // Records the value of a counter called "name" immediately. Value
620 // must be representable as a 32 bit integer.
621 #define TRACE_COUNTER1(category_group, name, value) \
622 INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \
623 TRACE_EVENT_FLAG_NONE, "value", \
624 static_cast<int>(value))
625
626 // Records the values of a multi-parted counter called "name" immediately.
627 // The UI will treat value1 and value2 as parts of a whole, displaying their
628 // values as a stacked-bar chart.
629 #define TRACE_COUNTER2(category_group, name, value1_name, value1_val, \
630 value2_name, value2_val) \
631 INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \
632 TRACE_EVENT_FLAG_NONE, value1_name, \
633 static_cast<int>(value1_val), value2_name, \
634 static_cast<int>(value2_val))
635
636 #define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \
637 INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
638 TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, TRACE_EVENT_FLAG_NONE)
639 #define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
640 INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
641 category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
642 #define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \
643 INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
644 category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)
645
646 #define TRACE_EVENT_ASYNC_END0(category, name, id) \
647 INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
648 category, name, id, TRACE_EVENT_FLAG_NONE)
649 #define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
650 INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
651 category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
652 #define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \
653 INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
654 category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)
655
656 // Macros to track the life time and value of arbitrary client objects.
657 #define TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group, name, id) \
658 INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
659 TRACE_EVENT_PHASE_CREATE_OBJECT, category_group, name, id, \
660 TRACE_EVENT_FLAG_NONE)
661
662 #define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group, name, id, \
663 snapshot) \
664 INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
665 TRACE_EVENT_PHASE_SNAPSHOT_OBJECT, category_group, name, \
666 id, TRACE_EVENT_FLAG_NONE, "snapshot", snapshot)
667
668 #define TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group, name, id) \
669 INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
670 TRACE_EVENT_PHASE_DELETE_OBJECT, category_group, name, id, \
671 TRACE_EVENT_FLAG_NONE)
672
673 // Macro to efficiently determine if a given category group is enabled.
674 #define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \
675 do { \
676 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
677 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
678 *ret = true; \
679 } else { \
680 *ret = false; \
681 } \
682 } while (0)
683
684 #endif
685
686 // Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT.
687 #define TRACE_EVENT_FLAG_NONE (static_cast<unsigned int>(0))
688 #define TRACE_EVENT_FLAG_COPY (static_cast<unsigned int>(1 << 0))
689 #define TRACE_EVENT_FLAG_HAS_ID (static_cast<unsigned int>(1 << 1))
690 #define TRACE_EVENT_FLAG_MANGLE_ID (static_cast<unsigned int>(1 << 2))
691 #define TRACE_EVENT_FLAG_SCOPE_OFFSET (static_cast<unsigned int>(1 << 3))
692 #define TRACE_EVENT_FLAG_SCOPE_EXTRA (static_cast<unsigned int>(1 << 4))
693 #define TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP (static_cast<unsigned int>(1 << 5))
694 #define TRACE_EVENT_FLAG_ASYNC_TTS (static_cast<unsigned int>(1 << 6))
695 #define TRACE_EVENT_FLAG_BIND_TO_ENCLOSING (static_cast<unsigned int>(1 << 7))
696 #define TRACE_EVENT_FLAG_FLOW_IN (static_cast<unsigned int>(1 << 8))
697 #define TRACE_EVENT_FLAG_FLOW_OUT (static_cast<unsigned int>(1 << 9))
698 #define TRACE_EVENT_FLAG_HAS_CONTEXT_ID (static_cast<unsigned int>(1 << 10))
699
700 #define TRACE_EVENT_FLAG_SCOPE_MASK \
701 (static_cast<unsigned int>(TRACE_EVENT_FLAG_SCOPE_OFFSET | \
702 TRACE_EVENT_FLAG_SCOPE_EXTRA))
703
704 // Type values for identifying types in the TraceValue union.
705 #define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1))
706 #define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2))
707 #define TRACE_VALUE_TYPE_INT (static_cast<unsigned char>(3))
708 #define TRACE_VALUE_TYPE_DOUBLE (static_cast<unsigned char>(4))
709 #define TRACE_VALUE_TYPE_POINTER (static_cast<unsigned char>(5))
710 #define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6))
711 #define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(7))
712 #define TRACE_VALUE_TYPE_CONVERTABLE (static_cast<unsigned char>(8))
713
714 // Enum reflecting the scope of an INSTANT event. Must fit within TRACE_EVENT_FLAG_SCOPE_MASK.
715 #define TRACE_EVENT_SCOPE_GLOBAL (static_cast<unsigned char>(0 << 3))
716 #define TRACE_EVENT_SCOPE_PROCESS (static_cast<unsigned char>(1 << 3))
717 #define TRACE_EVENT_SCOPE_THREAD (static_cast<unsigned char>(2 << 3))
718
719 #define TRACE_EVENT_SCOPE_NAME_GLOBAL ('g')
720 #define TRACE_EVENT_SCOPE_NAME_PROCESS ('p')
721 #define TRACE_EVENT_SCOPE_NAME_THREAD ('t')
722
723 #endif // SkTraceEventCommon_DEFINED
724