1 /* 2 * Copyright 2012 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 8 #include "Benchmark.h" 9 #include "SkCanvas.h" 10 #include "SkRTree.h" 11 #include "SkRandom.h" 12 #include "SkString.h" 13 14 // confine rectangles to a smallish area, so queries generally hit something, and overlap occurs: 15 static const SkScalar GENERATE_EXTENTS = 1000.0f; 16 static const int NUM_BUILD_RECTS = 500; 17 static const int NUM_QUERY_RECTS = 5000; 18 static const int GRID_WIDTH = 100; 19 20 typedef SkRect (*MakeRectProc)(SkRandom&, int, int); 21 22 // Time how long it takes to build an R-Tree. 23 class RTreeBuildBench : public Benchmark { 24 public: 25 RTreeBuildBench(const char* name, MakeRectProc proc) : fProc(proc) { 26 fName.printf("rtree_%s_build", name); 27 } 28 29 bool isSuitableFor(Backend backend) override { 30 return backend == kNonRendering_Backend; 31 } 32 33 protected: 34 const char* onGetName() override { 35 return fName.c_str(); 36 } 37 void onDraw(int loops, SkCanvas* canvas) override { 38 SkRandom rand; 39 SkAutoTMalloc<SkRect> rects(NUM_BUILD_RECTS); 40 for (int i = 0; i < NUM_BUILD_RECTS; ++i) { 41 rects[i] = fProc(rand, i, NUM_BUILD_RECTS); 42 } 43 44 for (int i = 0; i < loops; ++i) { 45 SkRTree tree; 46 tree.insert(rects.get(), NUM_BUILD_RECTS); 47 SkASSERT(rects != nullptr); // It'd break this bench if the tree took ownership of rects. 48 } 49 } 50 private: 51 MakeRectProc fProc; 52 SkString fName; 53 typedef Benchmark INHERITED; 54 }; 55 56 // Time how long it takes to perform queries on an R-Tree. 57 class RTreeQueryBench : public Benchmark { 58 public: 59 RTreeQueryBench(const char* name, MakeRectProc proc) : fProc(proc) { 60 fName.printf("rtree_%s_query", name); 61 } 62 63 bool isSuitableFor(Backend backend) override { 64 return backend == kNonRendering_Backend; 65 } 66 protected: 67 const char* onGetName() override { 68 return fName.c_str(); 69 } 70 void onDelayedSetup() override { 71 SkRandom rand; 72 SkAutoTMalloc<SkRect> rects(NUM_QUERY_RECTS); 73 for (int i = 0; i < NUM_QUERY_RECTS; ++i) { 74 rects[i] = fProc(rand, i, NUM_QUERY_RECTS); 75 } 76 fTree.insert(rects.get(), NUM_QUERY_RECTS); 77 } 78 79 void onDraw(int loops, SkCanvas* canvas) override { 80 SkRandom rand; 81 for (int i = 0; i < loops; ++i) { 82 SkTDArray<int> hits; 83 SkRect query; 84 query.fLeft = rand.nextRangeF(0, GENERATE_EXTENTS); 85 query.fTop = rand.nextRangeF(0, GENERATE_EXTENTS); 86 query.fRight = query.fLeft + 1 + rand.nextRangeF(0, GENERATE_EXTENTS/2); 87 query.fBottom = query.fTop + 1 + rand.nextRangeF(0, GENERATE_EXTENTS/2); 88 fTree.search(query, &hits); 89 } 90 } 91 private: 92 SkRTree fTree; 93 MakeRectProc fProc; 94 SkString fName; 95 typedef Benchmark INHERITED; 96 }; 97 98 static inline SkRect make_XYordered_rects(SkRandom& rand, int index, int numRects) { 99 SkRect out; 100 out.fLeft = SkIntToScalar(index % GRID_WIDTH); 101 out.fTop = SkIntToScalar(index / GRID_WIDTH); 102 out.fRight = out.fLeft + 1 + rand.nextRangeF(0, GENERATE_EXTENTS/3); 103 out.fBottom = out.fTop + 1 + rand.nextRangeF(0, GENERATE_EXTENTS/3); 104 return out; 105 } 106 static inline SkRect make_YXordered_rects(SkRandom& rand, int index, int numRects) { 107 SkRect out; 108 out.fLeft = SkIntToScalar(index / GRID_WIDTH); 109 out.fTop = SkIntToScalar(index % GRID_WIDTH); 110 out.fRight = out.fLeft + 1 + rand.nextRangeF(0, GENERATE_EXTENTS/3); 111 out.fBottom = out.fTop + 1 + rand.nextRangeF(0, GENERATE_EXTENTS/3); 112 return out; 113 } 114 115 static inline SkRect make_random_rects(SkRandom& rand, int index, int numRects) { 116 SkRect out; 117 out.fLeft = rand.nextRangeF(0, GENERATE_EXTENTS); 118 out.fTop = rand.nextRangeF(0, GENERATE_EXTENTS); 119 out.fRight = out.fLeft + 1 + rand.nextRangeF(0, GENERATE_EXTENTS/5); 120 out.fBottom = out.fTop + 1 + rand.nextRangeF(0, GENERATE_EXTENTS/5); 121 return out; 122 } 123 124 static inline SkRect make_concentric_rects(SkRandom&, int index, int numRects) { 125 return SkRect::MakeWH(SkIntToScalar(index+1), SkIntToScalar(index+1)); 126 } 127 128 /////////////////////////////////////////////////////////////////////////////// 129 130 DEF_BENCH(return new RTreeBuildBench("XY", &make_XYordered_rects)); 131 DEF_BENCH(return new RTreeBuildBench("YX", &make_YXordered_rects)); 132 DEF_BENCH(return new RTreeBuildBench("random", &make_random_rects)); 133 DEF_BENCH(return new RTreeBuildBench("concentric", &make_concentric_rects)); 134 135 DEF_BENCH(return new RTreeQueryBench("XY", &make_XYordered_rects)); 136 DEF_BENCH(return new RTreeQueryBench("YX", &make_YXordered_rects)); 137 DEF_BENCH(return new RTreeQueryBench("random", &make_random_rects)); 138 DEF_BENCH(return new RTreeQueryBench("concentric", &make_concentric_rects)); 139