1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 #include "SkBenchmark.h" 9 #include "SkFloatBits.h" 10 #include "SkRandom.h" 11 #include "SkRect.h" 12 #include "SkString.h" 13 14 class ScalarBench : public SkBenchmark { 15 SkString fName; 16 enum { N = 100000 }; 17 public: 18 ScalarBench(void* param, const char name[]) : INHERITED(param) { 19 fName.printf("scalar_%s", name); 20 fIsRendering = false; 21 } 22 23 virtual void performTest() = 0; 24 25 protected: 26 virtual int mulLoopCount() const { return 1; } 27 28 virtual const char* onGetName() SK_OVERRIDE { 29 return fName.c_str(); 30 } 31 32 virtual void onDraw(SkCanvas* canvas) { 33 int n = SkBENCHLOOP(N * this->mulLoopCount()); 34 for (int i = 0; i < n; i++) { 35 this->performTest(); 36 } 37 } 38 39 private: 40 typedef SkBenchmark INHERITED; 41 }; 42 43 // we want to stop the compiler from eliminating code that it thinks is a no-op 44 // so we have a non-static global we increment, hoping that will convince the 45 // compiler to execute everything 46 int gScalarBench_NonStaticGlobal; 47 48 #define always_do(pred) \ 49 do { \ 50 if (pred) { \ 51 ++gScalarBench_NonStaticGlobal; \ 52 } \ 53 } while (0) 54 55 // having unknown values in our arrays can throw off the timing a lot, perhaps 56 // handling NaN values is a lot slower. Anyway, this guy is just meant to put 57 // reasonable values in our arrays. 58 template <typename T> void init9(T array[9]) { 59 SkRandom rand; 60 for (int i = 0; i < 9; i++) { 61 array[i] = rand.nextSScalar1(); 62 } 63 } 64 65 class FloatComparisonBench : public ScalarBench { 66 public: 67 FloatComparisonBench(void* param) : INHERITED(param, "compare_float") { 68 init9(fArray); 69 } 70 protected: 71 virtual int mulLoopCount() const { return 4; } 72 virtual void performTest() { 73 always_do(fArray[6] != 0.0f || fArray[7] != 0.0f || fArray[8] != 1.0f); 74 always_do(fArray[2] != 0.0f || fArray[5] != 0.0f); 75 } 76 private: 77 float fArray[9]; 78 typedef ScalarBench INHERITED; 79 }; 80 81 class ForcedIntComparisonBench : public ScalarBench { 82 public: 83 ForcedIntComparisonBench(void* param) 84 : INHERITED(param, "compare_forced_int") { 85 init9(fArray); 86 } 87 protected: 88 virtual int mulLoopCount() const { return 4; } 89 virtual void performTest() { 90 always_do(SkScalarAs2sCompliment(fArray[6]) | 91 SkScalarAs2sCompliment(fArray[7]) | 92 (SkScalarAs2sCompliment(fArray[8]) - kPersp1Int)); 93 always_do(SkScalarAs2sCompliment(fArray[2]) | 94 SkScalarAs2sCompliment(fArray[5])); 95 } 96 private: 97 static const int32_t kPersp1Int = 0x3f800000; 98 SkScalar fArray[9]; 99 typedef ScalarBench INHERITED; 100 }; 101 102 class IsFiniteScalarBench : public ScalarBench { 103 public: 104 IsFiniteScalarBench(void* param) : INHERITED(param, "isfinite") { 105 SkRandom rand; 106 for (size_t i = 0; i < ARRAY_N; ++i) { 107 fArray[i] = rand.nextSScalar1(); 108 } 109 } 110 protected: 111 virtual int mulLoopCount() const { return 1; } 112 virtual void performTest() SK_OVERRIDE { 113 int sum = 0; 114 for (size_t i = 0; i < ARRAY_N; ++i) { 115 // We pass -fArray[i], so the compiler can't cheat and treat the 116 // value as an int (even though we tell it that it is a float) 117 sum += SkScalarIsFinite(-fArray[i]); 118 } 119 // we do this so the compiler won't optimize our loop away... 120 this->doSomething(fArray, sum); 121 } 122 123 virtual void doSomething(SkScalar array[], int sum) {} 124 private: 125 enum { 126 ARRAY_N = 64 127 }; 128 SkScalar fArray[ARRAY_N]; 129 130 typedef ScalarBench INHERITED; 131 }; 132 133 /////////////////////////////////////////////////////////////////////////////// 134 135 class RectBoundsBench : public SkBenchmark { 136 enum { 137 PTS = 100, 138 N = SkBENCHLOOP(10000) 139 }; 140 SkPoint fPts[PTS]; 141 142 public: 143 RectBoundsBench(void* param) : INHERITED(param) { 144 SkRandom rand; 145 for (int i = 0; i < PTS; ++i) { 146 fPts[i].fX = rand.nextSScalar1(); 147 fPts[i].fY = rand.nextSScalar1(); 148 } 149 fIsRendering = false; 150 } 151 152 protected: 153 virtual const char* onGetName() SK_OVERRIDE { 154 return "rect_bounds"; 155 } 156 157 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 158 SkRect r; 159 for (int i = 0; i < N; ++i) { 160 r.set(fPts, PTS); 161 } 162 } 163 164 private: 165 typedef SkBenchmark INHERITED; 166 }; 167 168 /////////////////////////////////////////////////////////////////////////////// 169 170 static SkBenchmark* S0(void* p) { return new FloatComparisonBench(p); } 171 static SkBenchmark* S1(void* p) { return new ForcedIntComparisonBench(p); } 172 static SkBenchmark* S2(void* p) { return new RectBoundsBench(p); } 173 static SkBenchmark* S3(void* p) { return new IsFiniteScalarBench(p); } 174 175 static BenchRegistry gReg0(S0); 176 static BenchRegistry gReg1(S1); 177 static BenchRegistry gReg2(S2); 178 static BenchRegistry gReg3(S3); 179