Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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_EVENT0_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_EVENT0_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;
212 ::perfetto::Tracing::Initialize(perfettoArgs);
213 ::skia::TrackEvent::Register();
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_EVENT0_ALWAYS(cg, n) TRACE_EMPTY(cg, n)
238 #define TRACE_EVENT1(cg, n, a1n, a1v) TRACE_EMPTY(cg, n, a1n, a1v)
239 #define TRACE_EVENT2(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
252namespace 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.
256 inline const char* UnboxPerfettoString(const ::perfetto::DynamicString& str) {
257 return str.value;
258 }
259 inline const char* UnboxPerfettoString(const ::perfetto::StaticString& str) {
260 return str.value;
261 }
262 inline const char* UnboxPerfettoString(const char* str) {
263 return str;
264 }
265
266 constexpr bool StrEndsWithAndLongerThan(const char* str, const char* suffix) {
267 auto strView = std::basic_string_view(str);
268 auto suffixView = std::basic_string_view(suffix);
269 // string_view::ends_with isn't available until C++20
270 return strView.size() > suffixView.size() &&
271 strView.compare(strView.size() - suffixView.size(),
272 std::string_view::npos, suffixView) == 0;
273 }
274}
275
276// Generate a unique variable name with a given prefix.
277// The indirection in this multi-level macro lets __LINE__ expand at the right time/place to get
278// prefix123 instead of prefix__LINE__.
279#define SK_PERFETTO_INTERNAL_CONCAT2(a, b) a##b
280#define SK_PERFETTO_INTERNAL_CONCAT(a, b) SK_PERFETTO_INTERNAL_CONCAT2(a, b)
281#define SK_PERFETTO_UID(prefix) SK_PERFETTO_INTERNAL_CONCAT(prefix, __LINE__)
282
283// Assuming there is an active tracing session, this call will create a trace event if tracing is
284// enabled (with SkAndroidFrameworkTraceUtil::setEnableTracing(true)) or if force_always_trace is
285// true. The event goes through ATrace by default, but can be routed to Perfetto instead by calling
286// SkAndroidFrameworkTraceUtil::setUsePerfettoTrackEvents(true).
287//
288// If force_always_trace = true, then the caller *must* append the ".always" suffix to the provided
289// category. This allows Perfetto tracing sessions to optionally filter to just the "skia.always"
290// category tag. This requirement is enforced at compile time.
291#define TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE(force_always_trace, category, name, ...) \
292 struct SK_PERFETTO_UID(ScopedEvent) { \
293 struct EventFinalizer { \
294 /* The ... parameter slot is an implementation detail. It allows the */ \
295 /* anonymous struct to use aggregate initialization to invoke the */ \
296 /* lambda (which emits the BEGIN event and returns an integer) */ \
297 /* with the proper reference capture for any */ \
298 /* TrackEventArgumentFunction in |__VA_ARGS__|. This is required so */ \
299 /* that the scoped event is exactly ONE line and can't escape the */ \
300 /* scope if used in a single line if statement. */ \
301 EventFinalizer(...) {} \
302 ~EventFinalizer() { \
303 if (force_always_trace || \
304 CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) { \
305 if (SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents()) { \
306 TRACE_EVENT_END(category); \
307 } else { \
308 ATRACE_END(); \
309 } \
310 } \
311 } \
312 \
313 EventFinalizer(const EventFinalizer&) = delete; \
314 EventFinalizer& operator=(const EventFinalizer&) = delete; \
315 \
316 EventFinalizer(EventFinalizer&&) = default; \
317 EventFinalizer& operator=(EventFinalizer&&) = delete; \
318 } finalizer; \
319 } SK_PERFETTO_UID(scoped_event) { \
320 [&]() { \
321 static_assert(!force_always_trace || \
322 ::skia_private::StrEndsWithAndLongerThan(category, ".always"), \
323 "[force_always_trace == true] requires [category] to end in '.always'"); \
324 if (force_always_trace || \
325 CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) { \
326 if (SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents()) { \
327 TRACE_EVENT_BEGIN(category, name, ##__VA_ARGS__); \
328 } else { \
329 ATRACE_BEGIN(::skia_private::UnboxPerfettoString(name)); \
330 } \
331 } \
332 return 0; \
333 }() \
334 }
335
336// Records an event with the current tracing backend, if overall Skia tracing is also enabled.
337#define TRACE_EVENT_ATRACE_OR_PERFETTO(category, name, ...) \
338 TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE( \
339 /* force_always_trace = */ false, category, name, ##__VA_ARGS__)
340
341#define ATRACE_ANDROID_FRAMEWORK(fmt, ...) \
342 char SK_PERFETTO_UID(skTraceStrBuf)[SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE]; \
343 if (SkAndroidFrameworkTraceUtil::getEnableTracing()) { \
344 snprintf(SK_PERFETTO_UID(skTraceStrBuf), SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE, \
345 fmt, ##__VA_ARGS__); \
346 } \
347 TRACE_EVENT0("skia.android", TRACE_STR_COPY(SK_PERFETTO_UID(skTraceStrBuf)))
348
349#define ATRACE_ANDROID_FRAMEWORK_ALWAYS(fmt, ...) \
350 char SK_PERFETTO_UID(skTraceStrBuf)[SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE]; \
351 snprintf(SK_PERFETTO_UID(skTraceStrBuf), SK_ANDROID_FRAMEWORK_ATRACE_BUFFER_SIZE, \
352 fmt, ##__VA_ARGS__); \
353 TRACE_EVENT0_ALWAYS("skia.android", TRACE_STR_COPY(SK_PERFETTO_UID(skTraceStrBuf)))
354
355// Records a pair of begin and end events called "name" for the current scope, with 0, 1 or 2
356// associated arguments. Note that ATrace does not support trace arguments, so they are only
357// recorded when Perfetto is set as the current tracing backend.
358#define TRACE_EVENT0(category_group, name) \
359 TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name)
360// Note: ".always" suffix appended to category_group in TRACE_EVENT0_ALWAYS.
361#define TRACE_EVENT0_ALWAYS(category_group, name) TRACE_EVENT_ATRACE_OR_PERFETTO_FORCEABLE( \
362 /* force_always_trace = */ true, category_group ".always", name)
363#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \
364 TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name, arg1_name, arg1_val)
365#define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \
366 TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
367
368// Records a single event called "name" immediately, with 0, 1 or 2 associated arguments.
369// Note that ATrace does not support trace arguments, so they are only recorded when Perfetto is set
370// as the current tracing backend.
371#define TRACE_EVENT_INSTANT0(category_group, name, scope) \
372 do { TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name); } while(0)
373
374#define TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val) \
375 do { TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name, arg1_name, arg1_val); } while(0)
376
377#define TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val, \
378 arg2_name, arg2_val) \
379 do { TRACE_EVENT_ATRACE_OR_PERFETTO(category_group, name, arg1_name, arg1_val, \
380 arg2_name, arg2_val); } while(0)
381
382// Records the value of a counter called "name" immediately. Value
383// must be representable as a 32 bit integer.
384#define TRACE_COUNTER1(category_group, name, value) \
385 if (CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) { \
386 if (SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents()) { \
387 TRACE_COUNTER(category_group, name, value); \
388 } else { \
389 ATRACE_INT(name, value); \
390 } \
391 }
392
393// Records the values of a multi-parted counter called "name" immediately.
394// In Chrome, this macro produces a stacked bar chart. Perfetto doesn't support
395// that (related: b/242349575), so this just produces two separate counters.
396#define TRACE_COUNTER2(category_group, name, value1_name, value1_val, value2_name, value2_val) \
397 if (CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing())) { \
398 if (SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents()) { \
399 TRACE_COUNTER(category_group, name "-" value1_name, value1_val); \
400 TRACE_COUNTER(category_group, name "-" value2_name, value2_val); \
401 } else { \
402 ATRACE_INT(name "-" value1_name, value1_val); \
403 ATRACE_INT(name "-" value2_name, value2_val); \
404 } \
405 }
406
407// ATrace has no object tracking, and would require a legacy shim for Perfetto (which likely no-ops
408// here). Further, these don't appear to currently be used outside of tests.
409#define TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group, name, id) \
410 TRACE_EMPTY(category_group, name, id)
411#define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group, name, id, snapshot) \
412 TRACE_EMPTY(category_group, name, id, snapshot)
413#define TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group, name, id) \
414 TRACE_EMPTY(category_group, name, id)
415
416// Macro to efficiently determine if a given category group is enabled. Only works with Perfetto.
417// This is only used for some shader text logging that isn't supported in ATrace anyway.
418#define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \
419 if (CC_UNLIKELY(SkAndroidFrameworkTraceUtil::getEnableTracing() && \
420 SkAndroidFrameworkTraceUtil::getUsePerfettoTrackEvents)) { \
421 *ret = TRACE_EVENT_CATEGORY_ENABLED(category_group); \
422 } else { \
423 *ret = false; \
424 }
425
426#else // Route through SkEventTracer (!SK_DISABLE_TRACING && !SK_ANDROID_FRAMEWORK_USE_PERFETTO)
427
428#define ATRACE_ANDROID_FRAMEWORK(fmt, ...) TRACE_EMPTY_FMT(fmt, ##__VA_ARGS__)
429#define ATRACE_ANDROID_FRAMEWORK_ALWAYS(fmt, ...) TRACE_EMPTY_FMT(fmt, ##__VA_ARGS__)
430
431// Records a pair of begin and end events called "name" for the current scope, with 0, 1 or 2
432// associated arguments. If the category is not enabled, then this does nothing.
433#define TRACE_EVENT0(category_group, name) \
434 INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name)
435
436#define TRACE_EVENT0_ALWAYS(category_group, name) \
437 INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name)
438
439#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \
440 INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val)
441
442#define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \
443 INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
444
445// Records a single event called "name" immediately, with 0, 1 or 2 associated arguments. If the
446// category is not enabled, then this does nothing.
447#define TRACE_EVENT_INSTANT0(category_group, name, scope) \
448 INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
449 TRACE_EVENT_FLAG_NONE | scope)
450
451#define TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val) \
452 INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
453 TRACE_EVENT_FLAG_NONE | scope, arg1_name, arg1_val)
454
455#define TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val, \
456 arg2_name, arg2_val) \
457 INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
458 TRACE_EVENT_FLAG_NONE | scope, arg1_name, arg1_val, \
459 arg2_name, arg2_val)
460
461// Records the value of a counter called "name" immediately. Value
462// must be representable as a 32 bit integer.
463#define TRACE_COUNTER1(category_group, name, value) \
464 INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \
465 TRACE_EVENT_FLAG_NONE, "value", \
466 static_cast<int>(value))
467
468// Records the values of a multi-parted counter called "name" immediately.
469// The UI will treat value1 and value2 as parts of a whole, displaying their
470// values as a stacked-bar chart.
471#define TRACE_COUNTER2(category_group, name, value1_name, value1_val, \
472 value2_name, value2_val) \
473 INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \
474 TRACE_EVENT_FLAG_NONE, value1_name, \
475 static_cast<int>(value1_val), value2_name, \
476 static_cast<int>(value2_val))
477
478#define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \
479 INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
480 TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, TRACE_EVENT_FLAG_NONE)
481#define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
482 INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
483 category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
484#define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \
485 INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
486 category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)
487
488#define TRACE_EVENT_ASYNC_END0(category, name, id) \
489 INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
490 category, name, id, TRACE_EVENT_FLAG_NONE)
491#define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
492 INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
493 category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
494#define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \
495 INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
496 category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)
497
498// Macros to track the life time and value of arbitrary client objects.
499#define TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group, name, id) \
500 INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
501 TRACE_EVENT_PHASE_CREATE_OBJECT, category_group, name, id, \
502 TRACE_EVENT_FLAG_NONE)
503
504#define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group, name, id, \
505 snapshot) \
506 INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
507 TRACE_EVENT_PHASE_SNAPSHOT_OBJECT, category_group, name, \
508 id, TRACE_EVENT_FLAG_NONE, "snapshot", snapshot)
509
510#define TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group, name, id) \
511 INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
512 TRACE_EVENT_PHASE_DELETE_OBJECT, category_group, name, id, \
513 TRACE_EVENT_FLAG_NONE)
514
515// Macro to efficiently determine if a given category group is enabled.
516#define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \
517 do { \
518 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
519 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
520 *ret = true; \
521 } else { \
522 *ret = false; \
523 } \
524 } while (0)
525
526#endif
527
528// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT.
529#define TRACE_EVENT_FLAG_NONE (static_cast<unsigned int>(0))
530#define TRACE_EVENT_FLAG_COPY (static_cast<unsigned int>(1 << 0))
531#define TRACE_EVENT_FLAG_HAS_ID (static_cast<unsigned int>(1 << 1))
532#define TRACE_EVENT_FLAG_MANGLE_ID (static_cast<unsigned int>(1 << 2))
533#define TRACE_EVENT_FLAG_SCOPE_OFFSET (static_cast<unsigned int>(1 << 3))
534#define TRACE_EVENT_FLAG_SCOPE_EXTRA (static_cast<unsigned int>(1 << 4))
535#define TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP (static_cast<unsigned int>(1 << 5))
536#define TRACE_EVENT_FLAG_ASYNC_TTS (static_cast<unsigned int>(1 << 6))
537#define TRACE_EVENT_FLAG_BIND_TO_ENCLOSING (static_cast<unsigned int>(1 << 7))
538#define TRACE_EVENT_FLAG_FLOW_IN (static_cast<unsigned int>(1 << 8))
539#define TRACE_EVENT_FLAG_FLOW_OUT (static_cast<unsigned int>(1 << 9))
540#define TRACE_EVENT_FLAG_HAS_CONTEXT_ID (static_cast<unsigned int>(1 << 10))
541
542#define TRACE_EVENT_FLAG_SCOPE_MASK \
543 (static_cast<unsigned int>(TRACE_EVENT_FLAG_SCOPE_OFFSET | \
544 TRACE_EVENT_FLAG_SCOPE_EXTRA))
545
546// Type values for identifying types in the TraceValue union.
547#define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1))
548#define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2))
549#define TRACE_VALUE_TYPE_INT (static_cast<unsigned char>(3))
550#define TRACE_VALUE_TYPE_DOUBLE (static_cast<unsigned char>(4))
551#define TRACE_VALUE_TYPE_POINTER (static_cast<unsigned char>(5))
552#define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6))
553#define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(7))
554#define TRACE_VALUE_TYPE_CONVERTABLE (static_cast<unsigned char>(8))
555
556// Enum reflecting the scope of an INSTANT event. Must fit within TRACE_EVENT_FLAG_SCOPE_MASK.
557#define TRACE_EVENT_SCOPE_GLOBAL (static_cast<unsigned char>(0 << 3))
558#define TRACE_EVENT_SCOPE_PROCESS (static_cast<unsigned char>(1 << 3))
559#define TRACE_EVENT_SCOPE_THREAD (static_cast<unsigned char>(2 << 3))
560
561#define TRACE_EVENT_SCOPE_NAME_GLOBAL ('g')
562#define TRACE_EVENT_SCOPE_NAME_PROCESS ('p')
563#define TRACE_EVENT_SCOPE_NAME_THREAD ('t')
564
565#endif // SkTraceEventCommon_DEFINED
#define SK_PRINTF_LIKE(A, B)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
PERFETTO_DEFINE_CATEGORIES()
uint32_t uint32_t * format