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