skia2/tests/TracingTest.cpp
Mike Klein 84836b799a moar static flags
Like any normal variable, flags can be made file-scoped static,
and like any normal variable, mostly they should be if they can.

This CL converts most flags to be static, if only so that the
ones that do cross files stand out more clearly, and so that
there's more examples of static flags through the codebase for
people to ape.

Change-Id: Ibb5ddd7aa09fce073d0996ac3ef0487b078b7d79
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/202800
Commit-Queue: Mike Klein <mtklein@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Auto-Submit: Mike Klein <mtklein@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
2019-03-21 17:07:13 +00:00

191 lines
6.9 KiB
C++

/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "CommandLineFlags.h"
#include "SkImageInfo.h"
#include "SkLeanWindows.h"
#include "SkPoint.h"
#include "SkRect.h"
#include "SkTraceEvent.h"
#include "Test.h"
static DEFINE_bool(slowTracingTest, false,
"Artificially slow down tracing test to produce nicer JSON");
namespace {
/**
* Helper types for demonstrating usage of TRACE_EVENT_OBJECT_XXX macros.
*/
struct TracingShape {
TracingShape() {
TRACE_EVENT_OBJECT_CREATED_WITH_ID("skia.objects", this->typeName(), this);
}
virtual ~TracingShape() {
TRACE_EVENT_OBJECT_DELETED_WITH_ID("skia.objects", this->typeName(), this);
}
void traceSnapshot() {
// The state of an object can be specified at any point with the OBJECT_SNAPSHOT macro.
// This takes the "name" (actually the type name), the ID of the object (typically a
// pointer), and a single (unnnamed) argument, which is the "snapshot" of that object.
//
// Tracing viewer requires that all object macros use the same name and id for creation,
// deletion, and snapshots. However: It's convenient to put creation and deletion in the
// base-class constructor/destructor where the actual type name isn't known yet. That's
// what we're doing here. The JSON for snapshots can therefore include the actual type
// name, and a special tag that refers to the type name originally used at creation time.
// Skia's JSON tracer handles this automatically, so SNAPSHOT macros can simply use the
// derived type name, and the JSON will be formatted correctly to link the events.
TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID("skia.objects", this->typeName(), this,
TRACE_STR_COPY(this->toString().c_str()));
}
virtual const char* typeName() { return "TracingShape"; }
virtual SkString toString() { return SkString("Shape()"); }
};
struct TracingCircle : public TracingShape {
TracingCircle(SkPoint center, SkScalar radius) : fCenter(center), fRadius(radius) {}
const char* typeName() override { return "TracingCircle"; }
SkString toString() override {
return SkStringPrintf("Circle(%f, %f, %f)", fCenter.fX, fCenter.fY, fRadius);
}
SkPoint fCenter;
SkScalar fRadius;
};
struct TracingRect : public TracingShape {
TracingRect(SkRect rect) : fRect(rect) {}
const char* typeName() override { return "TracingRect"; }
SkString toString() override {
return SkStringPrintf("Rect(%f, %f, %f, %f)",
fRect.fLeft, fRect.fTop, fRect.fRight, fRect.fBottom);
}
SkRect fRect;
};
}
static SkScalar gTracingTestWorkSink = 1.0f;
static void do_work(int howMuchWork) {
// Do busy work so the trace marker durations are large enough to be readable in trace viewer
if (FLAGS_slowTracingTest) {
for (int i = 0; i < howMuchWork * 100; ++i) {
gTracingTestWorkSink += SkScalarSin(i);
}
}
}
static void test_trace_simple() {
// Simple event that lasts until the end of the current scope. TRACE_FUNC is an easy way
// to insert the current function name.
TRACE_EVENT0("skia", TRACE_FUNC);
{
// There are versions of the macro that take 1 or 2 named arguments. The arguments
// can be any simple type. Strings need to be static/literal - we just copy pointers.
// Argument names & values are shown when the event is selected in the viewer.
TRACE_EVENT1("skia", "Nested work",
"isBGRA", kN32_SkColorType == kBGRA_8888_SkColorType);
do_work(500);
}
{
// If you must copy a string as an argument value, use the TRACE_STR_COPY macro.
// This will instruct the tracing system (if one is active) to make a copy.
SkString message = SkStringPrintf("%s %s", "Hello", "World");
TRACE_EVENT1("skia", "Dynamic String", "message", TRACE_STR_COPY(message.c_str()));
do_work(500);
}
}
static void test_trace_counters() {
TRACE_EVENT0("skia", TRACE_FUNC);
{
TRACE_EVENT0("skia", "Single Counter");
// Counter macros allow recording a named value (which must be a 32-bit integer).
// The value will be graphed in the viewer.
for (int i = 0; i < 180; ++i) {
SkScalar rad = SkDegreesToRadians(SkIntToScalar(i));
TRACE_COUNTER1("skia", "sin", SkScalarSin(rad) * 1000.0f + 1000.0f);
do_work(10);
}
}
{
TRACE_EVENT0("skia", "Independent Counters");
// Recording multiple counters with separate COUNTER1 macros will make separate graphs.
for (int i = 0; i < 180; ++i) {
SkScalar rad = SkDegreesToRadians(SkIntToScalar(i));
SkScalar cos;
SkScalar sin = SkScalarSinCos(rad, &cos);
TRACE_COUNTER1("skia", "sin", sin * 1000.0f + 1000.0f);
TRACE_COUNTER1("skia", "cos", cos * 1000.0f + 1000.0f);
do_work(10);
}
}
{
TRACE_EVENT0("skia", "Stacked Counters");
// Two counters can be recorded together with COUNTER2. They will be graphed together,
// as a stacked bar graph. The combined graph needs a name, as does each data series.
for (int i = 0; i < 180; ++i) {
SkScalar rad = SkDegreesToRadians(SkIntToScalar(i));
SkScalar cos;
SkScalar sin = SkScalarSinCos(rad, &cos);
TRACE_COUNTER2("skia", "trig",
"sin", sin * 1000.0f + 1000.0f,
"cos", cos * 1000.0f + 1000.0f);
do_work(10);
}
}
}
static void test_trace_objects() {
TRACE_EVENT0("skia", TRACE_FUNC);
// Objects can be tracked through time with the TRACE_EVENT_OBJECT_ macros.
// The macros in use (and their idiosyncracies) are commented in the TracingShape class above.
TracingCircle* circle = new TracingCircle(SkPoint::Make(20, 20), 15);
circle->traceSnapshot();
do_work(100);
// Make another object. Objects with the same base type are shown in the same row in the viewer.
TracingRect* rect = new TracingRect(SkRect::MakeWH(100, 50));
rect->traceSnapshot();
do_work(100);
// We can create multiple snapshots of objects to reflect their state over time.
circle->fCenter.offset(10, 10);
circle->traceSnapshot();
{
// Other events (duration or instant) can refer directly to objects. For Skia's JSON
// tracer, having an argument whose name starts with '#' will trigger the creation of JSON
// that links the event to the object (with a direct link to the most recent snapshot).
TRACE_EVENT1("skia", "Processing Shape", "#shape", circle);
do_work(100);
}
delete circle;
delete rect;
}
DEF_TEST(Tracing, reporter) {
test_trace_simple();
test_trace_counters();
test_trace_objects();
}