Home | History | Annotate | Download | only in bench
      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 "Benchmark.h"
      8 #include "SkMatrix.h"
      9 #include "SkMatrixUtils.h"
     10 #include "SkRandom.h"
     11 #include "SkString.h"
     12 
     13 class MatrixBench : public Benchmark {
     14     SkString    fName;
     15 public:
     16     MatrixBench(const char name[])  {
     17         fName.printf("matrix_%s", name);
     18     }
     19 
     20     bool isSuitableFor(Backend backend) override {
     21         return backend == kNonRendering_Backend;
     22     }
     23 
     24     virtual void performTest() = 0;
     25 
     26 protected:
     27     virtual int mulLoopCount() const { return 1; }
     28 
     29     const char* onGetName() override {
     30         return fName.c_str();
     31     }
     32 
     33     void onDraw(int loops, SkCanvas*) override {
     34         for (int i = 0; i < loops; i++) {
     35             this->performTest();
     36         }
     37     }
     38 
     39 private:
     40     typedef Benchmark INHERITED;
     41 };
     42 
     43 
     44 class EqualsMatrixBench : public MatrixBench {
     45 public:
     46     EqualsMatrixBench() : INHERITED("equals") {}
     47 protected:
     48     void performTest() override {
     49         SkMatrix m0, m1, m2;
     50 
     51         m0.reset();
     52         m1.reset();
     53         m2.reset();
     54 
     55         // xor into a volatile prevents these comparisons from being optimized away.
     56         volatile bool junk = false;
     57         junk ^= (m0 == m1);
     58         junk ^= (m1 == m2);
     59         junk ^= (m2 == m0);
     60     }
     61 private:
     62     typedef MatrixBench INHERITED;
     63 };
     64 
     65 class ScaleMatrixBench : public MatrixBench {
     66 public:
     67     ScaleMatrixBench() : INHERITED("scale") {
     68         fSX = fSY = 1.5f;
     69         fM0.reset();
     70         fM1.setScale(fSX, fSY);
     71         fM2.setTranslate(fSX, fSY);
     72     }
     73 protected:
     74     void performTest() override {
     75         SkMatrix m;
     76         m = fM0; m.preScale(fSX, fSY);
     77         m = fM1; m.preScale(fSX, fSY);
     78         m = fM2; m.preScale(fSX, fSY);
     79     }
     80 private:
     81     SkMatrix fM0, fM1, fM2;
     82     SkScalar fSX, fSY;
     83     typedef MatrixBench INHERITED;
     84 };
     85 
     86 // having unknown values in our arrays can throw off the timing a lot, perhaps
     87 // handling NaN values is a lot slower. Anyway, this guy is just meant to put
     88 // reasonable values in our arrays.
     89 template <typename T> void init9(T array[9]) {
     90     SkRandom rand;
     91     for (int i = 0; i < 9; i++) {
     92         array[i] = rand.nextSScalar1();
     93     }
     94 }
     95 
     96 class GetTypeMatrixBench : public MatrixBench {
     97 public:
     98     GetTypeMatrixBench()
     99         : INHERITED("gettype") {
    100         fArray[0] = (float) fRnd.nextS();
    101         fArray[1] = (float) fRnd.nextS();
    102         fArray[2] = (float) fRnd.nextS();
    103         fArray[3] = (float) fRnd.nextS();
    104         fArray[4] = (float) fRnd.nextS();
    105         fArray[5] = (float) fRnd.nextS();
    106         fArray[6] = (float) fRnd.nextS();
    107         fArray[7] = (float) fRnd.nextS();
    108         fArray[8] = (float) fRnd.nextS();
    109     }
    110 protected:
    111     // Putting random generation of the matrix inside performTest()
    112     // would help us avoid anomalous runs, but takes up 25% or
    113     // more of the function time.
    114     void performTest() override {
    115         fMatrix.setAll(fArray[0], fArray[1], fArray[2],
    116                        fArray[3], fArray[4], fArray[5],
    117                        fArray[6], fArray[7], fArray[8]);
    118         // xoring into a volatile prevents the compiler from optimizing these away
    119         volatile int junk = 0;
    120         junk ^= (fMatrix.getType());
    121         fMatrix.dirtyMatrixTypeCache();
    122         junk ^= (fMatrix.getType());
    123         fMatrix.dirtyMatrixTypeCache();
    124         junk ^= (fMatrix.getType());
    125         fMatrix.dirtyMatrixTypeCache();
    126         junk ^= (fMatrix.getType());
    127         fMatrix.dirtyMatrixTypeCache();
    128         junk ^= (fMatrix.getType());
    129         fMatrix.dirtyMatrixTypeCache();
    130         junk ^= (fMatrix.getType());
    131         fMatrix.dirtyMatrixTypeCache();
    132         junk ^= (fMatrix.getType());
    133         fMatrix.dirtyMatrixTypeCache();
    134         junk ^= (fMatrix.getType());
    135     }
    136 private:
    137     SkMatrix fMatrix;
    138     float fArray[9];
    139     SkRandom fRnd;
    140     typedef MatrixBench INHERITED;
    141 };
    142 
    143 class DecomposeMatrixBench : public MatrixBench {
    144 public:
    145     DecomposeMatrixBench() : INHERITED("decompose") {}
    146 
    147 protected:
    148     void onDelayedSetup() override {
    149         for (int i = 0; i < 10; ++i) {
    150             SkScalar rot0 = (fRandom.nextBool()) ? fRandom.nextRangeF(-180, 180) : 0.0f;
    151             SkScalar sx = fRandom.nextRangeF(-3000.f, 3000.f);
    152             SkScalar sy = (fRandom.nextBool()) ? fRandom.nextRangeF(-3000.f, 3000.f) : sx;
    153             SkScalar rot1 = fRandom.nextRangeF(-180, 180);
    154             fMatrix[i].setRotate(rot0);
    155             fMatrix[i].postScale(sx, sy);
    156             fMatrix[i].postRotate(rot1);
    157         }
    158     }
    159     void performTest() override {
    160         SkPoint rotation1, scale, rotation2;
    161         for (int i = 0; i < 10; ++i) {
    162             (void) SkDecomposeUpper2x2(fMatrix[i], &rotation1, &scale, &rotation2);
    163         }
    164     }
    165 private:
    166     SkMatrix fMatrix[10];
    167     SkRandom fRandom;
    168     typedef MatrixBench INHERITED;
    169 };
    170 
    171 class InvertMapRectMatrixBench : public MatrixBench {
    172 public:
    173     InvertMapRectMatrixBench(const char* name, int flags)
    174         : INHERITED(name)
    175         , fFlags(flags) {
    176         fMatrix.reset();
    177         fIteration = 0;
    178         if (flags & kScale_Flag) {
    179             fMatrix.postScale(1.5f, 2.5f);
    180         }
    181         if (flags & kTranslate_Flag) {
    182             fMatrix.postTranslate(1.5f, 2.5f);
    183         }
    184         if (flags & kRotate_Flag) {
    185             fMatrix.postRotate(45.0f);
    186         }
    187         if (flags & kPerspective_Flag) {
    188             fMatrix.setPerspX(1.5f);
    189             fMatrix.setPerspY(2.5f);
    190         }
    191         if (0 == (flags & kUncachedTypeMask_Flag)) {
    192             fMatrix.getType();
    193         }
    194     }
    195     enum Flag {
    196         kScale_Flag             = 0x01,
    197         kTranslate_Flag         = 0x02,
    198         kRotate_Flag            = 0x04,
    199         kPerspective_Flag       = 0x08,
    200         kUncachedTypeMask_Flag  = 0x10,
    201     };
    202 protected:
    203     void performTest() override {
    204         if (fFlags & kUncachedTypeMask_Flag) {
    205             // This will invalidate the typemask without
    206             // changing the matrix.
    207             fMatrix.setPerspX(fMatrix.getPerspX());
    208         }
    209         SkMatrix inv;
    210         bool invertible = fMatrix.invert(&inv);
    211         SkASSERT(invertible);
    212         SkRect transformedRect;
    213         // an arbitrary, small, non-zero rect to transform
    214         SkRect srcRect = SkRect::MakeWH(SkIntToScalar(10), SkIntToScalar(10));
    215         if (invertible) {
    216             inv.mapRect(&transformedRect, srcRect);
    217         }
    218     }
    219 private:
    220     SkMatrix fMatrix;
    221     int fFlags;
    222     unsigned fIteration;
    223     typedef MatrixBench INHERITED;
    224 };
    225 
    226 ///////////////////////////////////////////////////////////////////////////////
    227 
    228 DEF_BENCH( return new EqualsMatrixBench(); )
    229 DEF_BENCH( return new ScaleMatrixBench(); )
    230 DEF_BENCH( return new GetTypeMatrixBench(); )
    231 DEF_BENCH( return new DecomposeMatrixBench(); )
    232 
    233 DEF_BENCH( return new InvertMapRectMatrixBench("invert_maprect_identity", 0); )
    234 
    235 DEF_BENCH(return new InvertMapRectMatrixBench(
    236                                   "invert_maprect_rectstaysrect",
    237                                   InvertMapRectMatrixBench::kScale_Flag |
    238                                   InvertMapRectMatrixBench::kTranslate_Flag); )
    239 
    240 DEF_BENCH(return new InvertMapRectMatrixBench(
    241                                   "invert_maprect_translate",
    242                                   InvertMapRectMatrixBench::kTranslate_Flag); )
    243 
    244 DEF_BENCH(return new InvertMapRectMatrixBench(
    245                                   "invert_maprect_nonpersp",
    246                                   InvertMapRectMatrixBench::kScale_Flag |
    247                                   InvertMapRectMatrixBench::kRotate_Flag |
    248                                   InvertMapRectMatrixBench::kTranslate_Flag); )
    249 
    250 DEF_BENCH( return new InvertMapRectMatrixBench(
    251                                "invert_maprect_persp",
    252                                InvertMapRectMatrixBench::kPerspective_Flag); )
    253 
    254 DEF_BENCH( return new InvertMapRectMatrixBench(
    255                            "invert_maprect_typemask_rectstaysrect",
    256                            InvertMapRectMatrixBench::kUncachedTypeMask_Flag |
    257                            InvertMapRectMatrixBench::kScale_Flag |
    258                            InvertMapRectMatrixBench::kTranslate_Flag); )
    259 
    260 DEF_BENCH( return new InvertMapRectMatrixBench(
    261                            "invert_maprect_typemask_nonpersp",
    262                            InvertMapRectMatrixBench::kUncachedTypeMask_Flag |
    263                            InvertMapRectMatrixBench::kScale_Flag |
    264                            InvertMapRectMatrixBench::kRotate_Flag |
    265                            InvertMapRectMatrixBench::kTranslate_Flag); )
    266 
    267 ///////////////////////////////////////////////////////////////////////////////
    268 
    269 static SkMatrix make_trans() { return SkMatrix::MakeTrans(2, 3); }
    270 static SkMatrix make_scale() { SkMatrix m(make_trans()); m.postScale(1.5f, 0.5f); return m; }
    271 static SkMatrix make_afine() { SkMatrix m(make_trans()); m.postRotate(15); return m; }
    272 
    273 class MapPointsMatrixBench : public MatrixBench {
    274 protected:
    275     SkMatrix fM;
    276     enum {
    277         N = 32
    278     };
    279     SkPoint fSrc[N], fDst[N];
    280 public:
    281     MapPointsMatrixBench(const char name[], const SkMatrix& m)
    282         : MatrixBench(name), fM(m)
    283     {
    284         SkRandom rand;
    285         for (int i = 0; i < N; ++i) {
    286             fSrc[i].set(rand.nextSScalar1(), rand.nextSScalar1());
    287         }
    288     }
    289 
    290     void performTest() override {
    291         for (int i = 0; i < 1000000; ++i) {
    292             fM.mapPoints(fDst, fSrc, N);
    293         }
    294     }
    295 };
    296 DEF_BENCH( return new MapPointsMatrixBench("mappoints_identity", SkMatrix::I()); )
    297 DEF_BENCH( return new MapPointsMatrixBench("mappoints_trans", make_trans()); )
    298 DEF_BENCH( return new MapPointsMatrixBench("mappoints_scale", make_scale()); )
    299 DEF_BENCH( return new MapPointsMatrixBench("mappoints_affine", make_afine()); )
    300 
    301 ///////////////////////////////////////////////////////////////////////////////
    302 
    303 class MapRectMatrixBench : public MatrixBench {
    304     SkMatrix fM;
    305     SkRect   fR;
    306     bool     fScaleTrans;
    307 
    308     enum { MEGA_LOOP = 1000 * 1000 };
    309 public:
    310     MapRectMatrixBench(const char name[], bool scale_trans)
    311         : MatrixBench(name), fScaleTrans(scale_trans)
    312     {
    313         fM.setScale(2, 3);
    314         fM.postTranslate(1, 2);
    315 
    316         fR.set(10, 10, 100, 200);
    317     }
    318 
    319     void performTest() override {
    320         SkRect dst;
    321         if (fScaleTrans) {
    322             for (int i = 0; i < MEGA_LOOP; ++i) {
    323                 fM.mapRectScaleTranslate(&dst, fR);
    324             }
    325         } else {
    326             for (int i = 0; i < MEGA_LOOP; ++i) {
    327                 fM.mapRect(&dst, fR);
    328             }
    329         }
    330     }
    331 };
    332 DEF_BENCH( return new MapRectMatrixBench("maprect", false); )
    333 DEF_BENCH( return new MapRectMatrixBench("maprectscaletrans", true); )
    334