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 14class ScalarBench : public SkBenchmark { 15 SkString fName; 16 enum { N = 100000 }; 17public: 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 25protected: 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 39private: 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 46int 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. 58template <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 65class FloatComparisonBench : public ScalarBench { 66public: 67 FloatComparisonBench(void* param) : INHERITED(param, "compare_float") { 68 init9(fArray); 69 } 70protected: 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 } 76private: 77 float fArray[9]; 78 typedef ScalarBench INHERITED; 79}; 80 81class ForcedIntComparisonBench : public ScalarBench { 82public: 83 ForcedIntComparisonBench(void* param) 84 : INHERITED(param, "compare_forced_int") { 85 init9(fArray); 86 } 87protected: 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 } 96private: 97 static const int32_t kPersp1Int = 0x3f800000; 98 SkScalar fArray[9]; 99 typedef ScalarBench INHERITED; 100}; 101 102class IsFiniteScalarBench : public ScalarBench { 103public: 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 } 110protected: 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) {} 124private: 125 enum { 126 ARRAY_N = 64 127 }; 128 SkScalar fArray[ARRAY_N]; 129 130 typedef ScalarBench INHERITED; 131}; 132 133/////////////////////////////////////////////////////////////////////////////// 134 135class RectBoundsBench : public SkBenchmark { 136 enum { 137 PTS = 100, 138 N = SkBENCHLOOP(10000) 139 }; 140 SkPoint fPts[PTS]; 141 142public: 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 152protected: 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 164private: 165 typedef SkBenchmark INHERITED; 166}; 167 168/////////////////////////////////////////////////////////////////////////////// 169 170static SkBenchmark* S0(void* p) { return new FloatComparisonBench(p); } 171static SkBenchmark* S1(void* p) { return new ForcedIntComparisonBench(p); } 172static SkBenchmark* S2(void* p) { return new RectBoundsBench(p); } 173static SkBenchmark* S3(void* p) { return new IsFiniteScalarBench(p); } 174 175static BenchRegistry gReg0(S0); 176static BenchRegistry gReg1(S1); 177static BenchRegistry gReg2(S2); 178static BenchRegistry gReg3(S3); 179