Home | History | Annotate | Download | only in bench
      1 #include "SkBenchmark.h"
      2 #include "SkMatrix.h"
      3 #include "SkRandom.h"
      4 #include "SkString.h"
      5 
      6 class MatrixBench : public SkBenchmark {
      7     SkString    fName;
      8     enum { N = 100000 };
      9 public:
     10     MatrixBench(void* param, const char name[]) : INHERITED(param) {
     11         fName.printf("matrix_%s", name);
     12     }
     13 
     14     virtual void performTest() = 0;
     15 
     16 protected:
     17     virtual int mulLoopCount() const { return 1; }
     18 
     19     virtual const char* onGetName() {
     20         return fName.c_str();
     21     }
     22 
     23     virtual void onDraw(SkCanvas* canvas) {
     24         int n = N * this->mulLoopCount();
     25         for (int i = 0; i < n; i++) {
     26             this->performTest();
     27         }
     28     }
     29 
     30 private:
     31     typedef SkBenchmark INHERITED;
     32 };
     33 
     34 // we want to stop the compiler from eliminating code that it thinks is a no-op
     35 // so we have a non-static global we increment, hoping that will convince the
     36 // compiler to execute everything
     37 int gMatrixBench_NonStaticGlobal;
     38 
     39 #define always_do(pred)                     \
     40     do {                                    \
     41         if (pred) {                         \
     42             ++gMatrixBench_NonStaticGlobal; \
     43         }                                   \
     44     } while (0)
     45 
     46 class EqualsMatrixBench : public MatrixBench {
     47 public:
     48     EqualsMatrixBench(void* param) : INHERITED(param, "equals") {}
     49 protected:
     50     virtual void performTest() {
     51         SkMatrix m0, m1, m2;
     52 
     53         m0.reset();
     54         m1.reset();
     55         m2.reset();
     56         always_do(m0 == m1);
     57         always_do(m1 == m2);
     58         always_do(m2 == m0);
     59         always_do(m0.getType());
     60         always_do(m1.getType());
     61         always_do(m2.getType());
     62     }
     63 private:
     64     typedef MatrixBench INHERITED;
     65 };
     66 
     67 class ScaleMatrixBench : public MatrixBench {
     68 public:
     69     ScaleMatrixBench(void* param) : INHERITED(param, "scale") {
     70         fSX = fSY = SkFloatToScalar(1.5f);
     71         fM0.reset();
     72         fM1.setScale(fSX, fSY);
     73         fM2.setTranslate(fSX, fSY);
     74     }
     75 protected:
     76     virtual void performTest() {
     77         SkMatrix m;
     78         m = fM0; m.preScale(fSX, fSY);
     79         m = fM1; m.preScale(fSX, fSY);
     80         m = fM2; m.preScale(fSX, fSY);
     81     }
     82 private:
     83     SkMatrix fM0, fM1, fM2;
     84     SkScalar fSX, fSY;
     85     typedef MatrixBench INHERITED;
     86 };
     87 
     88 // having unknown values in our arrays can throw off the timing a lot, perhaps
     89 // handling NaN values is a lot slower. Anyway, this guy is just meant to put
     90 // reasonable values in our arrays.
     91 template <typename T> void init9(T array[9]) {
     92     SkRandom rand;
     93     for (int i = 0; i < 9; i++) {
     94         array[i] = rand.nextSScalar1();
     95     }
     96 }
     97 
     98 // Test the performance of setConcat() non-perspective case:
     99 // using floating point precision only.
    100 class FloatConcatMatrixBench : public MatrixBench {
    101 public:
    102     FloatConcatMatrixBench(void* p) : INHERITED(p, "concat_floatfloat") {
    103         init9(mya);
    104         init9(myb);
    105         init9(myr);
    106     }
    107 protected:
    108     virtual int mulLoopCount() const { return 4; }
    109 
    110     static inline void muladdmul(float a, float b, float c, float d,
    111                                    float* result) {
    112       *result = a * b + c * d;
    113     }
    114     virtual void performTest() {
    115         const float* a = mya;
    116         const float* b = myb;
    117         float* r = myr;
    118         muladdmul(a[0], b[0], a[1], b[3], &r[0]);
    119         muladdmul(a[0], b[1], a[1], b[4], &r[1]);
    120         muladdmul(a[0], b[2], a[1], b[5], &r[2]);
    121         r[2] += a[2];
    122         muladdmul(a[3], b[0], a[4], b[3], &r[3]);
    123         muladdmul(a[3], b[1], a[4], b[4], &r[4]);
    124         muladdmul(a[3], b[2], a[4], b[5], &r[5]);
    125         r[5] += a[5];
    126         r[6] = r[7] = 0.0f;
    127         r[8] = 1.0f;
    128     }
    129 private:
    130     float mya [9];
    131     float myb [9];
    132     float myr [9];
    133     typedef MatrixBench INHERITED;
    134 };
    135 
    136 static inline float SkDoubleToFloat(double x) {
    137     return static_cast<float>(x);
    138 }
    139 
    140 // Test the performance of setConcat() non-perspective case:
    141 // using floating point precision but casting up to float for
    142 // intermediate results during computations.
    143 class FloatDoubleConcatMatrixBench : public MatrixBench {
    144 public:
    145     FloatDoubleConcatMatrixBench(void* p) : INHERITED(p, "concat_floatdouble") {
    146         init9(mya);
    147         init9(myb);
    148         init9(myr);
    149     }
    150 protected:
    151     virtual int mulLoopCount() const { return 4; }
    152 
    153     static inline void muladdmul(float a, float b, float c, float d,
    154                                    float* result) {
    155       *result = SkDoubleToFloat((double)a * b + (double)c * d);
    156     }
    157     virtual void performTest() {
    158         const float* a = mya;
    159         const float* b = myb;
    160         float* r = myr;
    161         muladdmul(a[0], b[0], a[1], b[3], &r[0]);
    162         muladdmul(a[0], b[1], a[1], b[4], &r[1]);
    163         muladdmul(a[0], b[2], a[1], b[5], &r[2]);
    164         r[2] += a[2];
    165         muladdmul(a[3], b[0], a[4], b[3], &r[3]);
    166         muladdmul(a[3], b[1], a[4], b[4], &r[4]);
    167         muladdmul(a[3], b[2], a[4], b[5], &r[5]);
    168         r[5] += a[5];
    169         r[6] = r[7] = 0.0f;
    170         r[8] = 1.0f;
    171     }
    172 private:
    173     float mya [9];
    174     float myb [9];
    175     float myr [9];
    176     typedef MatrixBench INHERITED;
    177 };
    178 
    179 // Test the performance of setConcat() non-perspective case:
    180 // using double precision only.
    181 class DoubleConcatMatrixBench : public MatrixBench {
    182 public:
    183     DoubleConcatMatrixBench(void* p) : INHERITED(p, "concat_double") {
    184         init9(mya);
    185         init9(myb);
    186         init9(myr);
    187     }
    188 protected:
    189     virtual int mulLoopCount() const { return 4; }
    190 
    191     static inline void muladdmul(double a, double b, double c, double d,
    192                                    double* result) {
    193       *result = a * b + c * d;
    194     }
    195     virtual void performTest() {
    196         const double* a = mya;
    197         const double* b = myb;
    198         double* r = myr;
    199         muladdmul(a[0], b[0], a[1], b[3], &r[0]);
    200         muladdmul(a[0], b[1], a[1], b[4], &r[1]);
    201         muladdmul(a[0], b[2], a[1], b[5], &r[2]);
    202         r[2] += a[2];
    203         muladdmul(a[3], b[0], a[4], b[3], &r[3]);
    204         muladdmul(a[3], b[1], a[4], b[4], &r[4]);
    205         muladdmul(a[3], b[2], a[4], b[5], &r[5]);
    206         r[5] += a[5];
    207         r[6] = r[7] = 0.0;
    208         r[8] = 1.0;
    209     }
    210 private:
    211     double mya [9];
    212     double myb [9];
    213     double myr [9];
    214     typedef MatrixBench INHERITED;
    215 };
    216 
    217 #ifdef SK_SCALAR_IS_FLOAT
    218 class ScaleTransMixedMatrixBench : public MatrixBench {
    219  public:
    220     ScaleTransMixedMatrixBench(void* p) : INHERITED(p, "scaletrans_mixed"), fCount (16) {
    221         fMatrix.setAll(fRandom.nextS(), fRandom.nextS(), fRandom.nextS(),
    222                        fRandom.nextS(), fRandom.nextS(), fRandom.nextS(),
    223                        fRandom.nextS(), fRandom.nextS(), fRandom.nextS());
    224         int i;
    225         for (i = 0; i < fCount; i++) {
    226             fSrc[i].fX = fRandom.nextS();
    227             fSrc[i].fY = fRandom.nextS();
    228             fDst[i].fX = fRandom.nextS();
    229             fDst[i].fY = fRandom.nextS();
    230         }
    231     }
    232  protected:
    233     virtual void performTest() {
    234         SkPoint* dst = fDst;
    235         const SkPoint* src = fSrc;
    236         int count = fCount;
    237         float mx = fMatrix[SkMatrix::kMScaleX];
    238         float my = fMatrix[SkMatrix::kMScaleY];
    239         float tx = fMatrix[SkMatrix::kMTransX];
    240         float ty = fMatrix[SkMatrix::kMTransY];
    241         do {
    242             dst->fY = SkScalarMulAdd(src->fY, my, ty);
    243             dst->fX = SkScalarMulAdd(src->fX, mx, tx);
    244             src += 1;
    245             dst += 1;
    246         } while (--count);
    247     }
    248  private:
    249     SkMatrix fMatrix;
    250     SkPoint fSrc [16];
    251     SkPoint fDst [16];
    252     int fCount;
    253     SkRandom fRandom;
    254     typedef MatrixBench INHERITED;
    255 };
    256 
    257 
    258 class ScaleTransDoubleMatrixBench : public MatrixBench {
    259  public:
    260     ScaleTransDoubleMatrixBench(void* p) : INHERITED(p, "scaletrans_double"), fCount (16) {
    261         init9(fMatrix);
    262         int i;
    263         for (i = 0; i < fCount; i++) {
    264             fSrc[i].fX = fRandom.nextS();
    265             fSrc[i].fY = fRandom.nextS();
    266             fDst[i].fX = fRandom.nextS();
    267             fDst[i].fY = fRandom.nextS();
    268         }
    269     }
    270  protected:
    271     virtual void performTest() {
    272         SkPoint* dst = fDst;
    273         const SkPoint* src = fSrc;
    274         int count = fCount;
    275         // As doubles, on Z600 Linux systems this is 2.5x as expensive as mixed mode
    276         float mx = fMatrix[SkMatrix::kMScaleX];
    277         float my = fMatrix[SkMatrix::kMScaleY];
    278         float tx = fMatrix[SkMatrix::kMTransX];
    279         float ty = fMatrix[SkMatrix::kMTransY];
    280         do {
    281             dst->fY = src->fY * my + ty;
    282             dst->fX = src->fX * mx + tx;
    283             src += 1;
    284             dst += 1;
    285         } while (--count);
    286     }
    287  private:
    288     double fMatrix [9];
    289     SkPoint fSrc [16];
    290     SkPoint fDst [16];
    291     int fCount;
    292     SkRandom fRandom;
    293     typedef MatrixBench INHERITED;
    294 };
    295 #endif
    296 
    297 
    298 
    299 
    300 
    301 static SkBenchmark* M0(void* p) { return new EqualsMatrixBench(p); }
    302 static SkBenchmark* M1(void* p) { return new ScaleMatrixBench(p); }
    303 static SkBenchmark* M2(void* p) { return new FloatConcatMatrixBench(p); }
    304 static SkBenchmark* M3(void* p) { return new FloatDoubleConcatMatrixBench(p); }
    305 static SkBenchmark* M4(void* p) { return new DoubleConcatMatrixBench(p); }
    306 
    307 static BenchRegistry gReg0(M0);
    308 static BenchRegistry gReg1(M1);
    309 static BenchRegistry gReg2(M2);
    310 static BenchRegistry gReg3(M3);
    311 static BenchRegistry gReg4(M4);
    312 
    313 #ifdef SK_SCALAR_IS_FLOAT
    314 static SkBenchmark* FlM0(void* p) { return new ScaleTransMixedMatrixBench(p); }
    315 static SkBenchmark* FlM1(void* p) { return new ScaleTransDoubleMatrixBench(p); }
    316 static BenchRegistry gFlReg5(FlM0);
    317 static BenchRegistry gFlReg6(FlM1);
    318 #endif
    319