3 * Copyright 2012 Google Inc.
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
15 // confine rectangles to a smallish area, so queries generally hit something, and overlap occurs:
16 static const SkScalar GENERATE_EXTENTS = 1000.0f;
17 static const int NUM_BUILD_RECTS = 500;
18 static const int NUM_QUERY_RECTS = 5000;
19 static const int GRID_WIDTH = 100;
21 typedef SkRect (*MakeRectProc)(SkRandom&, int, int);
23 // Time how long it takes to build an R-Tree either bulk-loaded or not
24 class RTreeBuildBench : public Benchmark {
26 RTreeBuildBench(const char* name, MakeRectProc proc, bool bulkLoad,
27 SkBBoxHierarchy* tree)
30 , fBulkLoad(bulkLoad) {
31 fName.append("rtree_");
33 fName.append("_build");
35 fName.append("_bulk");
39 virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
40 return backend == kNonRendering_Backend;
43 virtual ~RTreeBuildBench() {
47 virtual const char* onGetName() SK_OVERRIDE {
50 virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
52 for (int i = 0; i < loops; ++i) {
53 for (int j = 0; j < NUM_BUILD_RECTS; ++j) {
54 fTree->insert(reinterpret_cast<void*>(j), fProc(rand, j, NUM_BUILD_RECTS),
57 fTree->flushDeferredInserts();
62 SkBBoxHierarchy* fTree;
66 typedef Benchmark INHERITED;
69 // Time how long it takes to perform queries on an R-Tree, bulk-loaded or not
70 class RTreeQueryBench : public Benchmark {
73 kSmall_QueryType, // small queries
74 kLarge_QueryType, // large queries
75 kRandom_QueryType,// randomly sized queries
76 kFull_QueryType // queries that cover everything
79 RTreeQueryBench(const char* name, MakeRectProc proc, bool bulkLoad,
80 QueryType q, SkBBoxHierarchy* tree)
85 fName.append("rtree_");
87 fName.append("_query");
89 fName.append("_bulk");
93 virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
94 return backend == kNonRendering_Backend;
97 virtual ~RTreeQueryBench() {
101 virtual const char* onGetName() SK_OVERRIDE {
102 return fName.c_str();
104 virtual void onPreDraw() SK_OVERRIDE {
106 for (int j = 0; j < NUM_QUERY_RECTS; ++j) {
107 fTree->insert(reinterpret_cast<void*>(j),
108 fProc(rand, j, NUM_QUERY_RECTS),
111 fTree->flushDeferredInserts();
114 virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
116 for (int i = 0; i < loops; ++i) {
117 SkTDArray<void*> hits;
120 case kSmall_QueryType:
121 query.fLeft = rand.nextRangeF(0, GENERATE_EXTENTS);
122 query.fTop = rand.nextRangeF(0, GENERATE_EXTENTS);
123 query.fRight = query.fLeft + (GENERATE_EXTENTS / 20);
124 query.fBottom = query.fTop + (GENERATE_EXTENTS / 20);
126 case kLarge_QueryType:
127 query.fLeft = rand.nextRangeF(0, GENERATE_EXTENTS);
128 query.fTop = rand.nextRangeF(0, GENERATE_EXTENTS);
129 query.fRight = query.fLeft + (GENERATE_EXTENTS / 2);
130 query.fBottom = query.fTop + (GENERATE_EXTENTS / 2);
132 case kFull_QueryType:
133 query.fLeft = -GENERATE_EXTENTS;
134 query.fTop = -GENERATE_EXTENTS;
135 query.fRight = 2 * GENERATE_EXTENTS;
136 query.fBottom = 2 * GENERATE_EXTENTS;
138 default: // fallthrough
139 case kRandom_QueryType:
140 query.fLeft = rand.nextRangeF(0, GENERATE_EXTENTS);
141 query.fTop = rand.nextRangeF(0, GENERATE_EXTENTS);
142 query.fRight = query.fLeft + 1 + rand.nextRangeF(0, GENERATE_EXTENTS/2);
143 query.fBottom = query.fTop + 1 + rand.nextRangeF(0, GENERATE_EXTENTS/2);
146 fTree->search(query, &hits);
150 SkBBoxHierarchy* fTree;
155 typedef Benchmark INHERITED;
158 static inline SkRect make_concentric_rects_increasing(SkRandom&, int index, int numRects) {
159 SkRect out = SkRect::MakeWH(SkIntToScalar(index+1), SkIntToScalar(index+1));
163 static inline SkRect make_XYordered_rects(SkRandom& rand, int index, int numRects) {
165 out.fLeft = SkIntToScalar(index % GRID_WIDTH);
166 out.fTop = SkIntToScalar(index / GRID_WIDTH);
167 out.fRight = out.fLeft + 1 + rand.nextRangeF(0, GENERATE_EXTENTS/3);
168 out.fBottom = out.fTop + 1 + rand.nextRangeF(0, GENERATE_EXTENTS/3);
171 static inline SkRect make_YXordered_rects(SkRandom& rand, int index, int numRects) {
173 out.fLeft = SkIntToScalar(index / GRID_WIDTH);
174 out.fTop = SkIntToScalar(index % GRID_WIDTH);
175 out.fRight = out.fLeft + 1 + rand.nextRangeF(0, GENERATE_EXTENTS/3);
176 out.fBottom = out.fTop + 1 + rand.nextRangeF(0, GENERATE_EXTENTS/3);
180 static inline SkRect make_random_rects(SkRandom& rand, int index, int numRects) {
182 out.fLeft = rand.nextRangeF(0, GENERATE_EXTENTS);
183 out.fTop = rand.nextRangeF(0, GENERATE_EXTENTS);
184 out.fRight = out.fLeft + 1 + rand.nextRangeF(0, GENERATE_EXTENTS/5);
185 out.fBottom = out.fTop + 1 + rand.nextRangeF(0, GENERATE_EXTENTS/5);
189 ///////////////////////////////////////////////////////////////////////////////
192 return SkNEW_ARGS(RTreeBuildBench, ("XYordered", &make_XYordered_rects, false,
193 SkRTree::Create(5, 16)));
196 return SkNEW_ARGS(RTreeBuildBench, ("XYordered", &make_XYordered_rects, true,
197 SkRTree::Create(5, 16)));
200 return SkNEW_ARGS(RTreeBuildBench, ("(unsorted)XYordered", &make_XYordered_rects, true,
201 SkRTree::Create(5, 16, 1, false)));
204 return SkNEW_ARGS(RTreeQueryBench, ("XYordered", &make_XYordered_rects, true,
205 RTreeQueryBench::kRandom_QueryType, SkRTree::Create(5, 16)));
208 return SkNEW_ARGS(RTreeQueryBench, ("(unsorted)XYordered", &make_XYordered_rects, true,
209 RTreeQueryBench::kRandom_QueryType, SkRTree::Create(5, 16, 1, false)));
213 return SkNEW_ARGS(RTreeBuildBench, ("YXordered", &make_YXordered_rects, false,
214 SkRTree::Create(5, 16)));
217 return SkNEW_ARGS(RTreeBuildBench, ("YXordered", &make_YXordered_rects, true,
218 SkRTree::Create(5, 16)));
221 return SkNEW_ARGS(RTreeBuildBench, ("(unsorted)YXordered", &make_YXordered_rects, true,
222 SkRTree::Create(5, 16, 1, false)));
225 return SkNEW_ARGS(RTreeQueryBench, ("YXordered", &make_YXordered_rects, true,
226 RTreeQueryBench::kRandom_QueryType, SkRTree::Create(5, 16)));
229 return SkNEW_ARGS(RTreeQueryBench, ("(unsorted)YXordered", &make_YXordered_rects, true,
230 RTreeQueryBench::kRandom_QueryType, SkRTree::Create(5, 16, 1, false)));
234 return SkNEW_ARGS(RTreeBuildBench, ("random", &make_random_rects, false,
235 SkRTree::Create(5, 16)));
238 return SkNEW_ARGS(RTreeBuildBench, ("random", &make_random_rects, true,
239 SkRTree::Create(5, 16)));
242 return SkNEW_ARGS(RTreeBuildBench, ("(unsorted)random", &make_random_rects, true,
243 SkRTree::Create(5, 16, 1, false)));
246 return SkNEW_ARGS(RTreeQueryBench, ("random", &make_random_rects, true,
247 RTreeQueryBench::kRandom_QueryType, SkRTree::Create(5, 16)));
250 return SkNEW_ARGS(RTreeQueryBench, ("(unsorted)random", &make_random_rects, true,
251 RTreeQueryBench::kRandom_QueryType, SkRTree::Create(5, 16, 1, false)));
255 return SkNEW_ARGS(RTreeBuildBench, ("concentric",
256 &make_concentric_rects_increasing, true, SkRTree::Create(5, 16)));
259 return SkNEW_ARGS(RTreeBuildBench, ("(unsorted)concentric",
260 &make_concentric_rects_increasing, true, SkRTree::Create(5, 16, 1, false)));
263 return SkNEW_ARGS(RTreeQueryBench, ("concentric", &make_concentric_rects_increasing, true,
264 RTreeQueryBench::kRandom_QueryType, SkRTree::Create(5, 16)));
267 return SkNEW_ARGS(RTreeQueryBench, ("(unsorted)concentric", &make_concentric_rects_increasing, true,
268 RTreeQueryBench::kRandom_QueryType, SkRTree::Create(5, 16, 1, false)));