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