1 /*
2 * Copyright 2011 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 #include "bench/Benchmark.h"
8 #include "include/core/SkRect.h"
9 #include "include/core/SkString.h"
10 #include "include/private/base/SkFloatBits.h"
11 #include "src/base/SkRandom.h"
12
13 class ScalarBench : public Benchmark {
14 SkString fName;
15 public:
ScalarBench(const char name[])16 ScalarBench(const char name[]) {
17 fName.printf("scalar_%s", name);
18 }
19
isSuitableFor(Backend backend)20 bool isSuitableFor(Backend backend) override {
21 return backend == kNonRendering_Backend;
22 }
23
24 virtual void performTest() = 0;
25
26 protected:
mulLoopCount() const27 virtual int mulLoopCount() const { return 1; }
28
onGetName()29 const char* onGetName() override {
30 return fName.c_str();
31 }
32
onDraw(int loops,SkCanvas * canvas)33 void onDraw(int loops, SkCanvas* canvas) override {
34 for (int i = 0; i < loops; i++) {
35 this->performTest();
36 }
37 }
38
39 private:
40 using INHERITED = Benchmark;
41 };
42
43 // having unknown values in our arrays can throw off the timing a lot, perhaps
44 // handling NaN values is a lot slower. Anyway, this is just meant to put
45 // reasonable values in our arrays.
init9(T array[9])46 template <typename T> void init9(T array[9]) {
47 SkRandom rand;
48 for (int i = 0; i < 9; i++) {
49 array[i] = rand.nextSScalar1();
50 }
51 }
52
53 class FloatComparisonBench : public ScalarBench {
54 public:
FloatComparisonBench()55 FloatComparisonBench() : INHERITED("compare_float") {
56 init9(fArray);
57 }
58 protected:
mulLoopCount() const59 int mulLoopCount() const override { return 4; }
performTest()60 void performTest() override {
61 // xoring into a volatile prevents the compiler from optimizing these checks away.
62 [[maybe_unused]] volatile bool junk = false;
63 junk ^= (fArray[6] != 0.0f || fArray[7] != 0.0f || fArray[8] != 1.0f);
64 junk ^= (fArray[2] != 0.0f || fArray[5] != 0.0f);
65 }
66 private:
67 float fArray[9];
68 using INHERITED = ScalarBench;
69 };
70
71 class ForcedIntComparisonBench : public ScalarBench {
72 public:
ForcedIntComparisonBench()73 ForcedIntComparisonBench()
74 : INHERITED("compare_forced_int") {
75 init9(fArray);
76 }
77 protected:
mulLoopCount() const78 int mulLoopCount() const override { return 4; }
performTest()79 void performTest() override {
80 // xoring into a volatile prevents the compiler from optimizing these checks away.
81 [[maybe_unused]] volatile int32_t junk = 0;
82 junk ^= (SkScalarAs2sCompliment(fArray[6]) |
83 SkScalarAs2sCompliment(fArray[7]) |
84 (SkScalarAs2sCompliment(fArray[8]) - kPersp1Int));
85 junk ^= (SkScalarAs2sCompliment(fArray[2]) |
86 SkScalarAs2sCompliment(fArray[5]));
87 }
88 private:
89 static const int32_t kPersp1Int = 0x3f800000;
90 SkScalar fArray[9];
91 using INHERITED = ScalarBench;
92 };
93
94 class IsFiniteScalarBench : public ScalarBench {
95 public:
IsFiniteScalarBench()96 IsFiniteScalarBench() : INHERITED("isfinite") {
97 SkRandom rand;
98 for (size_t i = 0; i < ARRAY_N; ++i) {
99 fArray[i] = rand.nextSScalar1();
100 }
101 }
102 protected:
mulLoopCount() const103 int mulLoopCount() const override { return 1; }
performTest()104 void performTest() override {
105 int sum = 0;
106 for (size_t i = 0; i < ARRAY_N; ++i) {
107 // We pass -fArray[i], so the compiler can't cheat and treat the
108 // value as an int (even though we tell it that it is a float)
109 sum += SkScalarIsFinite(-fArray[i]);
110 }
111 // we do this so the compiler won't optimize our loop away...
112 this->doSomething(fArray, sum);
113 }
114
doSomething(SkScalar array[],int sum)115 virtual void doSomething(SkScalar array[], int sum) {}
116 private:
117 enum {
118 ARRAY_N = 64
119 };
120 SkScalar fArray[ARRAY_N];
121
122 using INHERITED = ScalarBench;
123 };
124
125 ///////////////////////////////////////////////////////////////////////////////
126
127 class RectBoundsBench : public Benchmark {
128 enum {
129 PTS = 100,
130 };
131 SkPoint fPts[PTS];
132
133 public:
RectBoundsBench()134 RectBoundsBench() {
135 SkRandom rand;
136 for (int i = 0; i < PTS; ++i) {
137 fPts[i].fX = rand.nextSScalar1();
138 fPts[i].fY = rand.nextSScalar1();
139 }
140 }
141
isSuitableFor(Backend backend)142 bool isSuitableFor(Backend backend) override {
143 return backend == kNonRendering_Backend;
144 }
145
146 protected:
onGetName()147 const char* onGetName() override {
148 return "rect_bounds";
149 }
150
onDraw(int loops,SkCanvas * canvas)151 void onDraw(int loops, SkCanvas* canvas) override {
152 SkRect r;
153 for (int loop = 0; loop < loops; ++loop) {
154 for (int i = 0; i < 1000; ++i) {
155 r.setBounds(fPts, PTS);
156 }
157 }
158 }
159
160 private:
161 using INHERITED = Benchmark;
162 };
163
164 ///////////////////////////////////////////////////////////////////////////////
165
166 DEF_BENCH( return new FloatComparisonBench(); )
167 DEF_BENCH( return new ForcedIntComparisonBench(); )
168 DEF_BENCH( return new RectBoundsBench(); )
169 DEF_BENCH( return new IsFiniteScalarBench(); )
170