Flutter Engine
The Flutter Engine
SkTraceEventCommon.h
Go to the documentation of this file.
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
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.
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 256
159
160class SkAndroidFrameworkTraceUtil {
161public:
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)
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.
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 // Note: please reach out to skia-android@google.com if you encounter this unexpectedly.
188 SkDebugf("Tracing Skia with Perfetto is not supported in this environment (host build?)");
189 return false;
190#endif // SK_ANDROID_FRAMEWORK_USE_PERFETTO
191 }
192
193 static bool getEnableTracing() {
194 return gEnableAndroidTracing;
195 }
196
197 static bool getUsePerfettoTrackEvents() {
198 return gUsePerfettoTrackEvents;
199 }
200
201private:
202 static bool gEnableAndroidTracing;
203 static bool gUsePerfettoTrackEvents;
204
205#ifdef SK_ANDROID_FRAMEWORK_USE_PERFETTO
206 // Initializes tracing systems, and establishes a connection to the 'traced' daemon.
207 //
208 // Can be called multiple times.
209 static void initPerfetto() {
210 ::perfetto::TracingInitArgs perfettoArgs;
211 perfettoArgs.backends |= perfetto::kSystemBackend;
214 }
215#endif // SK_ANDROID_FRAMEWORK_USE_PERFETTO
216};
217#endif // SK_BUILD_FOR_ANDROID_FRAMEWORK
218
219#ifdef SK_DEBUG
220static void skprintf_like_noop(const char format[], ...) SK_PRINTF_LIKE(1, 2);
221static inline void skprintf_like_noop(const char format[], ...) {}
222template <typename... Args>
223static inline void sk_noop(Args...) {}
224#define TRACE_EMPTY(...) do { sk_noop(__VA_ARGS__); } while (0)
225#define TRACE_EMPTY_FMT(fmt, ...) do { skprintf_like_noop(fmt, ##__VA_ARGS__); } while (0)
226#else
227#define TRACE_EMPTY(...) do {} while (0)
228#define TRACE_EMPTY_FMT(fmt, ...) do {} while (0)
229#endif
230
231#if defined(SK_DISABLE_TRACING) || \
232 (defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) && !defined(SK_ANDROID_FRAMEWORK_USE_PERFETTO))
233
234 #define ATRACE_ANDROID_FRAMEWORK(fmt, ...) TRACE_EMPTY_FMT(fmt, ##__VA_ARGS__)
235 #define ATRACE_ANDROID_FRAMEWORK_ALWAYS(fmt, ...) TRACE_EMPTY_FMT(fmt, ##__VA_ARGS__)
236 #define TRACE_EVENT0(cg, n) TRACE_EMPTY(cg, n)
237 #define TRACE_EVENT1(cg, n, a1n, a1v) TRACE_EMPTY(cg, n, a1n, a1v)
238 #define TRACE_EVENT2(cg, n, a1n, a1v, a2n, a2v) TRACE_EMPTY(cg, n, a1n, a1v, a2n, a2v)
239 #define TRACE_EVENT0_ALWAYS(cg, n) TRACE_EMPTY(cg, n)
240 #define TRACE_EVENT1_ALWAYS(cg, n, a1n, a1v) TRACE_EMPTY(cg, n, a1n, a1v)
241 #define TRACE_EVENT2_ALWAYS(cg, n, a1n, a1v, a2n, a2v) TRACE_EMPTY(cg, n, a1n, a1v, a2n, a2v)
242 #define TRACE_EVENT_INSTANT0(cg, n, scope) TRACE_EMPTY(cg, n, scope)
243 #define TRACE_EVENT_INSTANT1(cg, n, scope, a1n, a1v) TRACE_EMPTY(cg, n, scope, a1n, a1v)
244 #define TRACE_EVENT_INSTANT2(cg, n, scope, a1n, a1v, a2n, a2v) \
245 TRACE_EMPTY(cg, n, scope, a1n, a1v, a2n, a2v)
246 #define TRACE_EVENT_OBJECT_CREATED_WITH_ID(cg, n, id) TRACE_EMPTY(cg, n, id)
247 #define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(cg, n, id, ss) TRACE_EMPTY(cg, n, id, ss)
248 #define TRACE_EVENT_OBJECT_DELETED_WITH_ID(cg, n, id) TRACE_EMPTY(cg, n, id)
249 #define TRACE_COUNTER1(cg, n, value) TRACE_EMPTY(cg, n, value)
250 #define TRACE_COUNTER2(cg, n, v1n, v1v, v2n, v2v) TRACE_EMPTY(cg, n, v1n, v1v, v2n, v2v)
251
252#elif defined(SK_ANDROID_FRAMEWORK_USE_PERFETTO)
253
254namespace skia_private {
255 // ATrace can't accept ::perfetto::DynamicString or ::perfetto::StaticString, so any trace event
256 // names that were wrapped in TRACE_STR_COPY or TRACE_STR_STATIC need to be unboxed back to
257 // char* before being passed to ATrace.
258 inline const char* UnboxPerfettoString(const ::perfetto::DynamicString& str) {
259 return str.value;
260 }
261 inline const char* UnboxPerfettoString(const ::perfetto::StaticString& str) {
262 return str.value;
263 }
264 inline const char* UnboxPerfettoString(const char* str) {
265 return str;
266 }
267
268 // WrapTraceArgInStdString serves a similar purpose to UnboxPerfettoString, but also accepts
269 // numeric values that are often used as trace arguments. This necessitates always wrapping the
270 // argument in a new std::string, instead of just passing along/unboxing an existing C-style
271 // string. This comes at a slight cost, and should only be used for trace slice arguments but
272 // not slice names, where UnboxPerfettoString should be used instead.
273 template<typename T>
274 inline std::string WrapTraceArgInStdString(const T numeric) {
275 return std::to_string(numeric);
276 }
277 inline std::string WrapTraceArgInStdString(const ::perfetto::DynamicString& str) {
278 return std::string(str.value);
279 }
280 inline std::string WrapTraceArgInStdString(const ::perfetto::StaticString& str) {
281 return std::string(str.value);
282 }
283 inline std::string WrapTraceArgInStdString(const char* str) {
284 return std::string(str);
285 }
286
287 constexpr bool StrEndsWithAndLongerThan(const char* str, const char* suffix) {
288 auto strView = std::basic_string_view(str);
289 auto suffixView = std::basic_string_view(suffix);
290 // string_view::ends_with isn't available until C++20
291 return strView.size() > suffixView.size() &&
292 strView.compare(strView.size() - suffixView.size(),
293 std::string_view::npos, suffixView) == 0;
294 }
295}
296
297// Generate a unique variable name with a given prefix.
298// The indirection in this multi-level macro lets __LINE__ expand at the right time/place to get
299// prefix123 instead of prefix__LINE__.
300#define SK_PERFETTO_INTERNAL_CONCAT2(a, b) a##b
301#define SK_PERFETTO_INTERNAL_CONCAT(a, b) SK_PERFETTO_INTERNAL_CONCAT2(a, b)
302#define SK_PERFETTO_UID(prefix) SK_PERFETTO_INTERNAL_CONCAT(prefix, __LINE__)
303
304// Used by SK_INTERNAL_ATRACE_ARGS_BEGIN and SK_INTERNAL_ATRACE_ARGS_END to select which overloaded
305// macro to use depending on how many __VA_ARGS__ are present. The number of __VA_ARGS__ piped in
306// from this macro caller's parent caller determines which macro name given by the caller ends up in
307// the macro_name slot here. See usage for nuance.
308#define SK_INTERNAL_GET_ATRACE_ARGS_MACRO(_0, _1a, _1b, _2a, _2b, macro_name, ...) macro_name
309
310#define SK_INTERNAL_ATRACE_ARGS_BEGIN_0(name) \
311 ATRACE_BEGIN(::skia_private::UnboxPerfettoString(name));
312
313#define SK_INTERNAL_ATRACE_ARGS_BEGIN_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(::skia_private::UnboxPerfettoString(name)); \
321 ATRACE_BEGIN(SK_PERFETTO_UID(skTraceStrBuf1));
322
323#define SK_INTERNAL_ATRACE_ARGS_BEGIN_2( \
324 name, arg1_name, arg1_val, arg2_name, arg2_val, ...) \
325 char SK_PERFETTO_UID(skTraceStrBuf1)[SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE]; \
326 char SK_PERFETTO_UID(skTraceStrBuf2)[SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE]; \
327 snprintf(SK_PERFETTO_UID(skTraceStrBuf1), \
328 SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE, \
329 "^(%s: %s)", \
330 ::skia_private::UnboxPerfettoString(arg1_name), \
331 ::skia_private::WrapTraceArgInStdString(arg1_val).c_str()); \
332 snprintf(SK_PERFETTO_UID(skTraceStrBuf2), \
333 SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE, \
334 "^(%s: %s)", \
335 ::skia_private::UnboxPerfettoString(arg2_name), \
336 ::skia_private::WrapTraceArgInStdString(arg2_val).c_str()); \
337 ATRACE_BEGIN(::skia_private::UnboxPerfettoString(name)); \
338 ATRACE_BEGIN(SK_PERFETTO_UID(skTraceStrBuf1)); \
339 ATRACE_BEGIN(SK_PERFETTO_UID(skTraceStrBuf2));
340
341// Will map to either the 0, 1, or 2 argument variant of this macro, which will trigger an
342// ATRACE_BEGIN event for the slice name, and one for each argument <name, value> pair. The caller
343// must ensure each of these 1-3 slices are properly terminated with 1-3 matching ATRACE_END events.
344#define SK_INTERNAL_ATRACE_ARGS_BEGIN(slice_name, ...) \
345 SK_INTERNAL_GET_ATRACE_ARGS_MACRO(0, \
346 ##__VA_ARGS__, \
347 SK_INTERNAL_ATRACE_ARGS_BEGIN_2, \
348 0, \
349 SK_INTERNAL_ATRACE_ARGS_BEGIN_1, \
350 0, \
351 SK_INTERNAL_ATRACE_ARGS_BEGIN_0) \
352 (slice_name, ##__VA_ARGS__)
353
354#define SK_INTERNAL_ATRACE_ARGS_END_2(arg1_name, arg1_val, arg2_name, arg2_val, ...) \
355 ATRACE_END(); \
356 ATRACE_END(); \
357 ATRACE_END();
358
359#define SK_INTERNAL_ATRACE_ARGS_END_1(arg1_name, arg1_val) \
360 ATRACE_END(); \
361 ATRACE_END();
362
363#define SK_INTERNAL_ATRACE_ARGS_END_0() \
364 ATRACE_END();
365
366// Will map to either the 0, 1, or 2 argument variant of this macro, which will trigger an
367// ATRACE_END event for the slice name, and one for each argument <name, value> pair. The caller
368// must ensure each of these 1-3 slices already existed from 1-3 matching ATRACE_BEGIN events.
369#define SK_INTERNAL_ATRACE_ARGS_END(...) \
370 SK_INTERNAL_GET_ATRACE_ARGS_MACRO(0, \
371 ##__VA_ARGS__, \
372 SK_INTERNAL_ATRACE_ARGS_END_2, \
373 0, \
374 SK_INTERNAL_ATRACE_ARGS_END_1, \
375 0, \
376 SK_INTERNAL_ATRACE_ARGS_END_0) \
377 (__VA_ARGS__)
378
379// Assuming there is an active tracing session, this call will create a trace event if tracing is
380// enabled (with SkAndroidFrameworkTraceUtil::setEnableTracing(true)) or if force_always_trace is
381// true. The event goes through ATrace by default, but can be routed to Perfetto instead by calling
382// SkAndroidFrameworkTraceUtil::setUsePerfettoTrackEvents(true).
383//
384// If ATrace is used, then additional sub-events will be created for each trace event argument
385// <name, value> pair (up to a max of two argument pairs). If Perfetto is used, then any arguments
386// will be associated with a single event.
387//
388// If force_always_trace = true, then the caller *must* append the ".always" suffix to the provided
389// category. This allows Perfetto tracing sessions to optionally filter to just the "skia.always"
390// category tag. This requirement is enforced at compile time.
391#define TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE(force_always_trace, category, name, ...) \
392 struct SK_PERFETTO_UID(ScopedEvent) { \
393 struct EventFinalizer { \
394 /* The ... parameter slot is an implementation detail. It allows the */ \
395 /* anonymous struct to use aggregate initialization to invoke the */ \
396 /* lambda (which emits the BEGIN event and returns an integer) */ \
397 /* with the proper reference capture for any */ \
398 /* TrackEventArgumentFunction in |__VA_ARGS__|. This is required so */ \
399 /* that the scoped event is exactly ONE line and can't escape the */ \
400 /* scope if used in a single line if statement. */ \
401 EventFinalizer(...) {} \
402 ~EventFinalizer() { \
403 if (force_always_trace || \
404 CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) { \
405 if (SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents()) { \
406 TRACE_EVENT_END(category); \
407 } else { \
408 SK_INTERNAL_ATRACE_ARGS_END(__VA_ARGS__); \
409 } \
410 } \
411 } \
412 \
413 EventFinalizer(const EventFinalizer&) = delete; \
414 EventFinalizer& operator=(const EventFinalizer&) = delete; \
415 \
416 EventFinalizer(EventFinalizer&&) = default; \
417 EventFinalizer& operator=(EventFinalizer&&) = delete; \
418 } finalizer; \
419 } SK_PERFETTO_UID(scoped_event) { \
420 [&]() { \
421 static_assert(!force_always_trace || \
422 ::skia_private::StrEndsWithAndLongerThan(category, ".always"), \
423 "[force_always_trace == true] requires [category] to end in '.always'"); \
424 if (force_always_trace || \
425 CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) { \
426 if (SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents()) { \
427 TRACE_EVENT_BEGIN(category, name, ##__VA_ARGS__); \
428 } else { \
429 SK_INTERNAL_ATRACE_ARGS_BEGIN(name, ##__VA_ARGS__); \
430 } \
431 } \
432 return 0; \
433 }() \
434 }
435
436// Records an event with the current tracing backend if overall tracing is enabled, and Skia's
437// "broad" tracing is enabled with SkAndroidFrameworkTraceUtil::setEnableTracing(true).
438#define TRACE_EVENT_ATRACE_OR_PERFETTO(category, name, ...) \
439 TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE( \
440 /* force_always_trace = */ false, category, name, ##__VA_ARGS__)
441
442// Traces a formatted string if overall tracing is enabled, and Skia's "broad" tracing is enabled
443// with SkAndroidFrameworkTraceUtil::setEnableTracing(true).
444// No-op outside of Android framework builds.
445// WARNING: this macro expands to a multi-line statement, and must not be used in a single line
446// control statement!
447#define ATRACE_ANDROID_FRAMEWORK(fmt, ...) \
448 char SK_PERFETTO_UID(skTraceStrBuf)[SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE]; \
449 if (SkAndroidFrameworkTraceUtil::getEnableTracing()) { \
450 snprintf(SK_PERFETTO_UID(skTraceStrBuf), SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE, \
451 fmt, ##__VA_ARGS__); \
452 } \
453 TRACE_EVENT0("skia.android", TRACE_STR_COPY(SK_PERFETTO_UID(skTraceStrBuf)))
454
455// Traces a formatted string as long as overall tracing is enabled, even if Skia's "broad" tracing
456// is disabled.
457// No-op outside of Android framework builds.
458// WARNING: this macro expands to a multi-line statement, and must not be used in a single line
459// control statement!
460#define ATRACE_ANDROID_FRAMEWORK_ALWAYS(fmt, ...) \
461 char SK_PERFETTO_UID(skTraceStrBuf)[SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE]; \
462 snprintf(SK_PERFETTO_UID(skTraceStrBuf), SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE, \
463 fmt, ##__VA_ARGS__); \
464 TRACE_EVENT0_ALWAYS("skia.android", TRACE_STR_COPY(SK_PERFETTO_UID(skTraceStrBuf)))
465
466// Records a pair of begin and end events called "name" (with 0-2 associated arguments) for the
467// current scope as long as overall tracing is enabled, and Skia's "broad" tracing is enabled with
468// SkAndroidFrameworkTraceUtil::setEnableTracing(true).
469// Note that ATrace does not natively support trace arguments, so arguments are recorded as separate
470// sub-events when ATrace is set as the current tracing backend. The Perfetto tracing backend
471// associates any arguments with a single event / slice.
472#define TRACE_EVENT0(category_group, name) \
473 TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name)
474#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \
475 TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name, arg1_name, arg1_val)
476#define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \
477 TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
478
479// Records a pair of begin and end events called "name" (with 0-2 associated arguments) for the
480// current scope as long as overall tracing is enabled, even if Skia's "broad" tracing is disabled.
481// Note that ATrace does not natively support trace arguments, so arguments are recorded as separate
482// sub-events when ATrace is set as the current tracing backend. The Perfetto tracing backend
483// associates any arguments with a single event / slice.
484// Note: the ".always" suffix is appended to category_group in _ALWAYS trace event macro variants.
485#define TRACE_EVENT0_ALWAYS(category_group, name) \
486 TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE( \
487 /* force_always_trace = */ true, category_group ".always", name)
488#define TRACE_EVENT1_ALWAYS(category_group, name, arg1_name, arg1_val) \
489 TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE( \
490 /* force_always_trace = */ true, category_group ".always", name, arg1_name, arg1_val)
491#define TRACE_EVENT2_ALWAYS(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \
492 TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE(/* force_always_trace = */ true, \
493 category_group ".always", \
494 name, \
495 arg1_name, \
496 arg1_val, \
497 arg2_name, \
498 arg2_val)
499
500// Records a single event called "name" immediately, with 0, 1 or 2 associated arguments.
501// Note that ATrace does not support trace arguments, so they are only recorded when Perfetto is set
502// as the current tracing backend.
503#define TRACE_EVENT_INSTANT0(category_group, name, scope) \
504 do { TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name); } while(0)
505
506#define TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val) \
507 do { TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name, arg1_name, arg1_val); } while(0)
508
509#define TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val, \
510 arg2_name, arg2_val) \
511 do { TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name, arg1_name, arg1_val, \
512 arg2_name, arg2_val); } while(0)
513
514// Records the value of a counter called "name" immediately. Value
515// must be representable as a 32 bit integer.
516#define TRACE_COUNTER1(category_group, name, value) \
517 if (CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) { \
518 if (SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents()) { \
519 TRACE_COUNTER(category_group, name, value); \
520 } else { \
521 ATRACE_INT(name, value); \
522 } \
523 }
524
525// Records the values of a multi-parted counter called "name" immediately.
526// In Chrome, this macro produces a stacked bar chart. Perfetto doesn't support
527// that (related: b/242349575), so this just produces two separate counters.
528#define TRACE_COUNTER2(category_group, name, value1_name, value1_val, value2_name, value2_val) \
529 if (CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) { \
530 if (SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents()) { \
531 TRACE_COUNTER(category_group, name "-" value1_name, value1_val); \
532 TRACE_COUNTER(category_group, name "-" value2_name, value2_val); \
533 } else { \
534 ATRACE_INT(name "-" value1_name, value1_val); \
535 ATRACE_INT(name "-" value2_name, value2_val); \
536 } \
537 }
538
539// ATrace has no object tracking, and would require a legacy shim for Perfetto (which likely no-ops
540// here). Further, these don't appear to currently be used outside of tests.
541#define TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group, name, id) \
542 TRACE_EMPTY(category_group, name, id)
543#define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group, name, id, snapshot) \
544 TRACE_EMPTY(category_group, name, id, snapshot)
545#define TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group, name, id) \
546 TRACE_EMPTY(category_group, name, id)
547
548// Macro to efficiently determine if a given category group is enabled. Only works with Perfetto.
549// This is only used for some shader text logging that isn't supported in ATrace anyway.
550#define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \
551 if (CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing() && \
552 SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents)) { \
553 *ret = TRACE_EVENT_CATEGORY_ENABLED(category_group); \
554 } else { \
555 *ret = false; \
556 }
557
558#else // Route through SkEventTracer (!SK_DISABLE_TRACING && !SK_ANDROID_FRAMEWORK_USE_PERFETTO)
559
560#define ATRACE_ANDROID_FRAMEWORK(fmt, ...) TRACE_EMPTY_FMT(fmt, ##__VA_ARGS__)
561#define ATRACE_ANDROID_FRAMEWORK_ALWAYS(fmt, ...) TRACE_EMPTY_FMT(fmt, ##__VA_ARGS__)
562
563// Records a pair of begin and end events called "name" for the current scope, with 0, 1 or 2
564// associated arguments. If the category is not enabled, then this does nothing.
565#define TRACE_EVENT0(category_group, name) \
566 INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name)
567
568#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \
569 INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val)
570
571#define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \
572 INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
573
574#define TRACE_EVENT0_ALWAYS(category_group, name) \
575 INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name)
576
577#define TRACE_EVENT1_ALWAYS(category_group, name, arg1_name, arg1_val) \
578 INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val)
579
580#define TRACE_EVENT2_ALWAYS(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \
581 INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
582
583// Records a single event called "name" immediately, with 0, 1 or 2 associated arguments. If the
584// category is not enabled, then this does nothing.
585#define TRACE_EVENT_INSTANT0(category_group, name, scope) \
586 INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
587 TRACE_EVENT_FLAG_NONE | scope)
588
589#define TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val) \
590 INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
591 TRACE_EVENT_FLAG_NONE | scope, arg1_name, arg1_val)
592
593#define TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val, \
594 arg2_name, arg2_val) \
595 INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
596 TRACE_EVENT_FLAG_NONE | scope, arg1_name, arg1_val, \
597 arg2_name, arg2_val)
598
599// Records the value of a counter called "name" immediately. Value
600// must be representable as a 32 bit integer.
601#define TRACE_COUNTER1(category_group, name, value) \
602 INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \
603 TRACE_EVENT_FLAG_NONE, "value", \
604 static_cast<int>(value))
605
606// Records the values of a multi-parted counter called "name" immediately.
607// The UI will treat value1 and value2 as parts of a whole, displaying their
608// values as a stacked-bar chart.
609#define TRACE_COUNTER2(category_group, name, value1_name, value1_val, \
610 value2_name, value2_val) \
611 INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \
612 TRACE_EVENT_FLAG_NONE, value1_name, \
613 static_cast<int>(value1_val), value2_name, \
614 static_cast<int>(value2_val))
615
616#define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \
617 INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
618 TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, TRACE_EVENT_FLAG_NONE)
619#define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
620 INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
621 category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
622#define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \
623 INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
624 category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)
625
626#define TRACE_EVENT_ASYNC_END0(category, name, id) \
627 INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
628 category, name, id, TRACE_EVENT_FLAG_NONE)
629#define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
630 INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
631 category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
632#define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \
633 INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
634 category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)
635
636// Macros to track the life time and value of arbitrary client objects.
637#define TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group, name, id) \
638 INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
639 TRACE_EVENT_PHASE_CREATE_OBJECT, category_group, name, id, \
640 TRACE_EVENT_FLAG_NONE)
641
642#define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group, name, id, \
643 snapshot) \
644 INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
645 TRACE_EVENT_PHASE_SNAPSHOT_OBJECT, category_group, name, \
646 id, TRACE_EVENT_FLAG_NONE, "snapshot", snapshot)
647
648#define TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group, name, id) \
649 INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
650 TRACE_EVENT_PHASE_DELETE_OBJECT, category_group, name, id, \
651 TRACE_EVENT_FLAG_NONE)
652
653// Macro to efficiently determine if a given category group is enabled.
654#define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \
655 do { \
656 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
657 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
658 *ret = true; \
659 } else { \
660 *ret = false; \
661 } \
662 } while (0)
663
664#endif
665
666// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT.
667#define TRACE_EVENT_FLAG_NONE (static_cast<unsigned int>(0))
668#define TRACE_EVENT_FLAG_COPY (static_cast<unsigned int>(1 << 0))
669#define TRACE_EVENT_FLAG_HAS_ID (static_cast<unsigned int>(1 << 1))
670#define TRACE_EVENT_FLAG_MANGLE_ID (static_cast<unsigned int>(1 << 2))
671#define TRACE_EVENT_FLAG_SCOPE_OFFSET (static_cast<unsigned int>(1 << 3))
672#define TRACE_EVENT_FLAG_SCOPE_EXTRA (static_cast<unsigned int>(1 << 4))
673#define TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP (static_cast<unsigned int>(1 << 5))
674#define TRACE_EVENT_FLAG_ASYNC_TTS (static_cast<unsigned int>(1 << 6))
675#define TRACE_EVENT_FLAG_BIND_TO_ENCLOSING (static_cast<unsigned int>(1 << 7))
676#define TRACE_EVENT_FLAG_FLOW_IN (static_cast<unsigned int>(1 << 8))
677#define TRACE_EVENT_FLAG_FLOW_OUT (static_cast<unsigned int>(1 << 9))
678#define TRACE_EVENT_FLAG_HAS_CONTEXT_ID (static_cast<unsigned int>(1 << 10))
679
680#define TRACE_EVENT_FLAG_SCOPE_MASK \
681 (static_cast<unsigned int>(TRACE_EVENT_FLAG_SCOPE_OFFSET | \
682 TRACE_EVENT_FLAG_SCOPE_EXTRA))
683
684// Type values for identifying types in the TraceValue union.
685#define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1))
686#define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2))
687#define TRACE_VALUE_TYPE_INT (static_cast<unsigned char>(3))
688#define TRACE_VALUE_TYPE_DOUBLE (static_cast<unsigned char>(4))
689#define TRACE_VALUE_TYPE_POINTER (static_cast<unsigned char>(5))
690#define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6))
691#define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(7))
692#define TRACE_VALUE_TYPE_CONVERTABLE (static_cast<unsigned char>(8))
693
694// Enum reflecting the scope of an INSTANT event. Must fit within TRACE_EVENT_FLAG_SCOPE_MASK.
695#define TRACE_EVENT_SCOPE_GLOBAL (static_cast<unsigned char>(0 << 3))
696#define TRACE_EVENT_SCOPE_PROCESS (static_cast<unsigned char>(1 << 3))
697#define TRACE_EVENT_SCOPE_THREAD (static_cast<unsigned char>(2 << 3))
698
699#define TRACE_EVENT_SCOPE_NAME_GLOBAL ('g')
700#define TRACE_EVENT_SCOPE_NAME_PROCESS ('p')
701#define TRACE_EVENT_SCOPE_NAME_THREAD ('t')
702
703#endif // SkTraceEventCommon_DEFINED
#define SK_PRINTF_LIKE(A, B)
Definition: SkAttributes.h:52
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
PERFETTO_DEFINE_CATEGORIES()
uint32_t uint32_t * format
void Initialize(zx::channel directory_request, std::optional< zx::eventpair > view_ref)
Initializes Dart bindings for the Fuchsia application model.
Definition: fuchsia.cc:103
static SkString to_string(int n)
Definition: nanobench.cpp:119
#define T
Definition: precompiler.cc:65