xref: /aosp_15_r20/external/skia/tests/TracingTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2017 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorType.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTraceEvent.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "tools/flags/CommandLineFlags.h"
16*c8dee2aaSAndroid Build Coastguard Worker 
17*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
18*c8dee2aaSAndroid Build Coastguard Worker 
19*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_bool(slowTracingTest, false,
20*c8dee2aaSAndroid Build Coastguard Worker                    "Artificially slow down tracing test to produce nicer JSON");
21*c8dee2aaSAndroid Build Coastguard Worker 
22*c8dee2aaSAndroid Build Coastguard Worker namespace {
23*c8dee2aaSAndroid Build Coastguard Worker 
24*c8dee2aaSAndroid Build Coastguard Worker /**
25*c8dee2aaSAndroid Build Coastguard Worker  * Helper types for demonstrating usage of TRACE_EVENT_OBJECT_XXX macros.
26*c8dee2aaSAndroid Build Coastguard Worker  */
27*c8dee2aaSAndroid Build Coastguard Worker struct TracingShape {
TracingShape__anon41afd2390111::TracingShape28*c8dee2aaSAndroid Build Coastguard Worker     TracingShape() {
29*c8dee2aaSAndroid Build Coastguard Worker         TRACE_EVENT_OBJECT_CREATED_WITH_ID("skia.objects", this->typeName(), this);
30*c8dee2aaSAndroid Build Coastguard Worker     }
~TracingShape__anon41afd2390111::TracingShape31*c8dee2aaSAndroid Build Coastguard Worker     virtual ~TracingShape() {
32*c8dee2aaSAndroid Build Coastguard Worker         TRACE_EVENT_OBJECT_DELETED_WITH_ID("skia.objects", this->typeName(), this);
33*c8dee2aaSAndroid Build Coastguard Worker     }
traceSnapshot__anon41afd2390111::TracingShape34*c8dee2aaSAndroid Build Coastguard Worker     void traceSnapshot() {
35*c8dee2aaSAndroid Build Coastguard Worker         // The state of an object can be specified at any point with the OBJECT_SNAPSHOT macro.
36*c8dee2aaSAndroid Build Coastguard Worker         // This takes the "name" (actually the type name), the ID of the object (typically a
37*c8dee2aaSAndroid Build Coastguard Worker         // pointer), and a single (unnnamed) argument, which is the "snapshot" of that object.
38*c8dee2aaSAndroid Build Coastguard Worker         //
39*c8dee2aaSAndroid Build Coastguard Worker         // Tracing viewer requires that all object macros use the same name and id for creation,
40*c8dee2aaSAndroid Build Coastguard Worker         // deletion, and snapshots. However: It's convenient to put creation and deletion in the
41*c8dee2aaSAndroid Build Coastguard Worker         // base-class constructor/destructor where the actual type name isn't known yet. That's
42*c8dee2aaSAndroid Build Coastguard Worker         // what we're doing here. The JSON for snapshots can therefore include the actual type
43*c8dee2aaSAndroid Build Coastguard Worker         // name, and a special tag that refers to the type name originally used at creation time.
44*c8dee2aaSAndroid Build Coastguard Worker         // Skia's JSON tracer handles this automatically, so SNAPSHOT macros can simply use the
45*c8dee2aaSAndroid Build Coastguard Worker         // derived type name, and the JSON will be formatted correctly to link the events.
46*c8dee2aaSAndroid Build Coastguard Worker         TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID("skia.objects", this->typeName(), this,
47*c8dee2aaSAndroid Build Coastguard Worker                                             TRACE_STR_COPY(this->toString().c_str()));
48*c8dee2aaSAndroid Build Coastguard Worker     }
49*c8dee2aaSAndroid Build Coastguard Worker 
typeName__anon41afd2390111::TracingShape50*c8dee2aaSAndroid Build Coastguard Worker     virtual const char* typeName() { return "TracingShape"; }
toString__anon41afd2390111::TracingShape51*c8dee2aaSAndroid Build Coastguard Worker     virtual SkString toString() { return SkString("Shape()"); }
52*c8dee2aaSAndroid Build Coastguard Worker };
53*c8dee2aaSAndroid Build Coastguard Worker 
54*c8dee2aaSAndroid Build Coastguard Worker struct TracingCircle : public TracingShape {
TracingCircle__anon41afd2390111::TracingCircle55*c8dee2aaSAndroid Build Coastguard Worker     TracingCircle(SkPoint center, SkScalar radius) : fCenter(center), fRadius(radius) {}
typeName__anon41afd2390111::TracingCircle56*c8dee2aaSAndroid Build Coastguard Worker     const char* typeName() override { return "TracingCircle"; }
toString__anon41afd2390111::TracingCircle57*c8dee2aaSAndroid Build Coastguard Worker     SkString toString() override {
58*c8dee2aaSAndroid Build Coastguard Worker         return SkStringPrintf("Circle(%f, %f, %f)", fCenter.fX, fCenter.fY, fRadius);
59*c8dee2aaSAndroid Build Coastguard Worker     }
60*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_ANDROID_FRAMEWORK_USE_PERFETTO)
WriteIntoTrace__anon41afd2390111::TracingCircle61*c8dee2aaSAndroid Build Coastguard Worker     void WriteIntoTrace(::perfetto::TracedValue context) {
62*c8dee2aaSAndroid Build Coastguard Worker         std::move(context).WriteString(toString().c_str());
63*c8dee2aaSAndroid Build Coastguard Worker     }
64*c8dee2aaSAndroid Build Coastguard Worker #endif
65*c8dee2aaSAndroid Build Coastguard Worker 
66*c8dee2aaSAndroid Build Coastguard Worker     SkPoint fCenter;
67*c8dee2aaSAndroid Build Coastguard Worker     SkScalar fRadius;
68*c8dee2aaSAndroid Build Coastguard Worker };
69*c8dee2aaSAndroid Build Coastguard Worker 
70*c8dee2aaSAndroid Build Coastguard Worker struct TracingRect : public TracingShape {
TracingRect__anon41afd2390111::TracingRect71*c8dee2aaSAndroid Build Coastguard Worker     TracingRect(SkRect rect) : fRect(rect) {}
typeName__anon41afd2390111::TracingRect72*c8dee2aaSAndroid Build Coastguard Worker     const char* typeName() override { return "TracingRect"; }
toString__anon41afd2390111::TracingRect73*c8dee2aaSAndroid Build Coastguard Worker     SkString toString() override {
74*c8dee2aaSAndroid Build Coastguard Worker         return SkStringPrintf("Rect(%f, %f, %f, %f)",
75*c8dee2aaSAndroid Build Coastguard Worker                               fRect.fLeft, fRect.fTop, fRect.fRight, fRect.fBottom);
76*c8dee2aaSAndroid Build Coastguard Worker     }
77*c8dee2aaSAndroid Build Coastguard Worker 
78*c8dee2aaSAndroid Build Coastguard Worker     SkRect fRect;
79*c8dee2aaSAndroid Build Coastguard Worker };
80*c8dee2aaSAndroid Build Coastguard Worker 
81*c8dee2aaSAndroid Build Coastguard Worker }  // namespace
82*c8dee2aaSAndroid Build Coastguard Worker 
83*c8dee2aaSAndroid Build Coastguard Worker static SkScalar gTracingTestWorkSink = 1.0f;
84*c8dee2aaSAndroid Build Coastguard Worker 
do_work(int howMuchWork)85*c8dee2aaSAndroid Build Coastguard Worker static void do_work(int howMuchWork) {
86*c8dee2aaSAndroid Build Coastguard Worker     // Do busy work so the trace marker durations are large enough to be readable in trace viewer
87*c8dee2aaSAndroid Build Coastguard Worker     if (FLAGS_slowTracingTest) {
88*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < howMuchWork * 100; ++i) {
89*c8dee2aaSAndroid Build Coastguard Worker             gTracingTestWorkSink += SkScalarSin(i);
90*c8dee2aaSAndroid Build Coastguard Worker         }
91*c8dee2aaSAndroid Build Coastguard Worker     }
92*c8dee2aaSAndroid Build Coastguard Worker }
93*c8dee2aaSAndroid Build Coastguard Worker 
test_trace_simple()94*c8dee2aaSAndroid Build Coastguard Worker static void test_trace_simple() {
95*c8dee2aaSAndroid Build Coastguard Worker     // Simple event that lasts until the end of the current scope. TRACE_FUNC is an easy way
96*c8dee2aaSAndroid Build Coastguard Worker     // to insert the current function name.
97*c8dee2aaSAndroid Build Coastguard Worker     TRACE_EVENT0("skia", TRACE_FUNC);
98*c8dee2aaSAndroid Build Coastguard Worker 
99*c8dee2aaSAndroid Build Coastguard Worker     {
100*c8dee2aaSAndroid Build Coastguard Worker         // There are versions of the macro that take 1 or 2 named arguments. The arguments
101*c8dee2aaSAndroid Build Coastguard Worker         // can be any simple type. Strings need to be static/literal - we just copy pointers.
102*c8dee2aaSAndroid Build Coastguard Worker         // Argument names & values are shown when the event is selected in the viewer.
103*c8dee2aaSAndroid Build Coastguard Worker         TRACE_EVENT1("skia", "Nested work",
104*c8dee2aaSAndroid Build Coastguard Worker                      "isBGRA", kN32_SkColorType == kBGRA_8888_SkColorType);
105*c8dee2aaSAndroid Build Coastguard Worker         do_work(500);
106*c8dee2aaSAndroid Build Coastguard Worker     }
107*c8dee2aaSAndroid Build Coastguard Worker 
108*c8dee2aaSAndroid Build Coastguard Worker     {
109*c8dee2aaSAndroid Build Coastguard Worker         // If you must copy a string as an argument value, use the TRACE_STR_COPY macro.
110*c8dee2aaSAndroid Build Coastguard Worker         // This will instruct the tracing system (if one is active) to make a copy.
111*c8dee2aaSAndroid Build Coastguard Worker         SkString message = SkStringPrintf("%s %s", "Hello", "World");
112*c8dee2aaSAndroid Build Coastguard Worker         TRACE_EVENT1("skia", "Dynamic String", "message", TRACE_STR_COPY(message.c_str()));
113*c8dee2aaSAndroid Build Coastguard Worker         do_work(500);
114*c8dee2aaSAndroid Build Coastguard Worker     }
115*c8dee2aaSAndroid Build Coastguard Worker }
116*c8dee2aaSAndroid Build Coastguard Worker 
test_trace_counters()117*c8dee2aaSAndroid Build Coastguard Worker static void test_trace_counters() {
118*c8dee2aaSAndroid Build Coastguard Worker     TRACE_EVENT0("skia", TRACE_FUNC);
119*c8dee2aaSAndroid Build Coastguard Worker 
120*c8dee2aaSAndroid Build Coastguard Worker     {
121*c8dee2aaSAndroid Build Coastguard Worker         TRACE_EVENT0("skia", "Single Counter");
122*c8dee2aaSAndroid Build Coastguard Worker 
123*c8dee2aaSAndroid Build Coastguard Worker         // Counter macros allow recording a named value (which must be a 32-bit integer).
124*c8dee2aaSAndroid Build Coastguard Worker         // The value will be graphed in the viewer.
125*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < 180; ++i) {
126*c8dee2aaSAndroid Build Coastguard Worker             SkScalar rad = SkDegreesToRadians(SkIntToScalar(i));
127*c8dee2aaSAndroid Build Coastguard Worker             TRACE_COUNTER1("skia", "sin", SkScalarSin(rad) * 1000.0f + 1000.0f);
128*c8dee2aaSAndroid Build Coastguard Worker             do_work(10);
129*c8dee2aaSAndroid Build Coastguard Worker         }
130*c8dee2aaSAndroid Build Coastguard Worker     }
131*c8dee2aaSAndroid Build Coastguard Worker 
132*c8dee2aaSAndroid Build Coastguard Worker     {
133*c8dee2aaSAndroid Build Coastguard Worker         TRACE_EVENT0("skia", "Independent Counters");
134*c8dee2aaSAndroid Build Coastguard Worker 
135*c8dee2aaSAndroid Build Coastguard Worker         // Recording multiple counters with separate COUNTER1 macros will make separate graphs.
136*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < 180; ++i) {
137*c8dee2aaSAndroid Build Coastguard Worker             SkScalar rad = SkDegreesToRadians(SkIntToScalar(i));
138*c8dee2aaSAndroid Build Coastguard Worker             TRACE_COUNTER1("skia", "sin", SkScalarSin(rad) * 1000.0f + 1000.0f);
139*c8dee2aaSAndroid Build Coastguard Worker             TRACE_COUNTER1("skia", "cos", SkScalarCos(rad) * 1000.0f + 1000.0f);
140*c8dee2aaSAndroid Build Coastguard Worker             do_work(10);
141*c8dee2aaSAndroid Build Coastguard Worker         }
142*c8dee2aaSAndroid Build Coastguard Worker     }
143*c8dee2aaSAndroid Build Coastguard Worker 
144*c8dee2aaSAndroid Build Coastguard Worker     {
145*c8dee2aaSAndroid Build Coastguard Worker         TRACE_EVENT0("skia", "Stacked Counters");
146*c8dee2aaSAndroid Build Coastguard Worker 
147*c8dee2aaSAndroid Build Coastguard Worker         // Two counters can be recorded together with COUNTER2. They will be graphed together,
148*c8dee2aaSAndroid Build Coastguard Worker         // as a stacked bar graph. The combined graph needs a name, as does each data series.
149*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < 180; ++i) {
150*c8dee2aaSAndroid Build Coastguard Worker             SkScalar rad = SkDegreesToRadians(SkIntToScalar(i));
151*c8dee2aaSAndroid Build Coastguard Worker             TRACE_COUNTER2("skia", "trig",
152*c8dee2aaSAndroid Build Coastguard Worker                            "sin", SkScalarSin(rad) * 1000.0f + 1000.0f,
153*c8dee2aaSAndroid Build Coastguard Worker                            "cos", SkScalarCos(rad) * 1000.0f + 1000.0f);
154*c8dee2aaSAndroid Build Coastguard Worker             do_work(10);
155*c8dee2aaSAndroid Build Coastguard Worker         }
156*c8dee2aaSAndroid Build Coastguard Worker     }
157*c8dee2aaSAndroid Build Coastguard Worker }
158*c8dee2aaSAndroid Build Coastguard Worker 
test_trace_objects()159*c8dee2aaSAndroid Build Coastguard Worker static void test_trace_objects() {
160*c8dee2aaSAndroid Build Coastguard Worker     TRACE_EVENT0("skia", TRACE_FUNC);
161*c8dee2aaSAndroid Build Coastguard Worker 
162*c8dee2aaSAndroid Build Coastguard Worker     // Objects can be tracked through time with the TRACE_EVENT_OBJECT_ macros.
163*c8dee2aaSAndroid Build Coastguard Worker     // The macros in use (and their idiosyncracies) are commented in the TracingShape class above.
164*c8dee2aaSAndroid Build Coastguard Worker 
165*c8dee2aaSAndroid Build Coastguard Worker     TracingCircle* circle = new TracingCircle(SkPoint::Make(20, 20), 15);
166*c8dee2aaSAndroid Build Coastguard Worker     circle->traceSnapshot();
167*c8dee2aaSAndroid Build Coastguard Worker     do_work(100);
168*c8dee2aaSAndroid Build Coastguard Worker 
169*c8dee2aaSAndroid Build Coastguard Worker     // Make another object. Objects with the same base type are shown in the same row in the viewer.
170*c8dee2aaSAndroid Build Coastguard Worker     TracingRect* rect = new TracingRect(SkRect::MakeWH(100, 50));
171*c8dee2aaSAndroid Build Coastguard Worker     rect->traceSnapshot();
172*c8dee2aaSAndroid Build Coastguard Worker     do_work(100);
173*c8dee2aaSAndroid Build Coastguard Worker 
174*c8dee2aaSAndroid Build Coastguard Worker     // We can create multiple snapshots of objects to reflect their state over time.
175*c8dee2aaSAndroid Build Coastguard Worker     circle->fCenter.offset(10, 10);
176*c8dee2aaSAndroid Build Coastguard Worker     circle->traceSnapshot();
177*c8dee2aaSAndroid Build Coastguard Worker 
178*c8dee2aaSAndroid Build Coastguard Worker     {
179*c8dee2aaSAndroid Build Coastguard Worker         // Other events (duration or instant) can refer directly to objects. For Skia's JSON
180*c8dee2aaSAndroid Build Coastguard Worker         // tracer, having an argument whose name starts with '#' will trigger the creation of JSON
181*c8dee2aaSAndroid Build Coastguard Worker         // that links the event to the object (with a direct link to the most recent snapshot).
182*c8dee2aaSAndroid Build Coastguard Worker         TRACE_EVENT1("skia", "Processing Shape", "#shape", circle);
183*c8dee2aaSAndroid Build Coastguard Worker         do_work(100);
184*c8dee2aaSAndroid Build Coastguard Worker     }
185*c8dee2aaSAndroid Build Coastguard Worker 
186*c8dee2aaSAndroid Build Coastguard Worker     delete circle;
187*c8dee2aaSAndroid Build Coastguard Worker     delete rect;
188*c8dee2aaSAndroid Build Coastguard Worker }
189*c8dee2aaSAndroid Build Coastguard Worker 
DEF_TEST(Tracing,reporter)190*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Tracing, reporter) {
191*c8dee2aaSAndroid Build Coastguard Worker     test_trace_simple();
192*c8dee2aaSAndroid Build Coastguard Worker     test_trace_counters();
193*c8dee2aaSAndroid Build Coastguard Worker     test_trace_objects();
194*c8dee2aaSAndroid Build Coastguard Worker }
195