blob: 759037e00ede2c59727bc1a08bf7330bd702a457 [file] [log] [blame]
rileya@google.com981b33a2012-09-05 18:36:17 +00001
2/*
3 * Copyright 2012 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
9#include "SkBenchmark.h"
10#include "SkCanvas.h"
11#include "SkRTree.h"
12#include "SkRandom.h"
13#include "SkString.h"
14
15// confine rectangles to a smallish area, so queries generally hit something, and overlap occurs:
16static const int GENERATE_EXTENTS = 1000;
17static const int NUM_BUILD_RECTS = 500;
18static const int NUM_QUERY_RECTS = 5000;
19static const int NUM_QUERIES = 1000;
20
21typedef SkIRect (*MakeRectProc)(SkRandom&, int, int);
22
23// Time how long it takes to build an R-Tree either bulk-loaded or not
24class BBoxBuildBench : public SkBenchmark {
25public:
26 BBoxBuildBench(void* param, const char* name, MakeRectProc proc, bool bulkLoad,
27 SkBBoxHierarchy* tree)
skia.committer@gmail.com6c778162012-09-06 02:01:13 +000028 : INHERITED(param)
rileya@google.com981b33a2012-09-05 18:36:17 +000029 , fTree(tree)
30 , fProc(proc)
skia.committer@gmail.com6c778162012-09-06 02:01:13 +000031 , fName(name)
rileya@google.com981b33a2012-09-05 18:36:17 +000032 , fBulkLoad(bulkLoad) { }
33protected:
34 virtual const char* onGetName() {
35 SkString str;
36 str.append("rtree_");
37 str.append(fName);
38 str.append("_build");
39 if (fBulkLoad) {
40 str.append("_bulk");
41 }
42 return str.c_str();
43 }
44 virtual void onDraw(SkCanvas* canvas) {
45 SkRandom rand;
46 for (int i = 0; i < SkBENCHLOOP(100); ++i) {
47 for (int j = 0; j < NUM_BUILD_RECTS; ++j) {
48 fTree->insert(reinterpret_cast<void*>(j), fProc(rand, j, NUM_BUILD_RECTS),
49 fBulkLoad);
50 }
51 fTree->flushDeferredInserts();
52 fTree->clear();
53 }
54 }
55private:
56 SkBBoxHierarchy* fTree;
57 MakeRectProc fProc;
58 const char* fName;
59 bool fBulkLoad;
60 typedef SkBenchmark INHERITED;
61};
62
63// Time how long it takes to perform queries on an R-Tree, bulk-loaded or not
64class BBoxQueryBench : public SkBenchmark {
65public:
66 enum QueryType {
67 kSmall_QueryType, // small queries
68 kLarge_QueryType, // large queries
69 kRandom_QueryType,// randomly sized queries
70 kFull_QueryType // queries that cover everything
71 };
72
skia.committer@gmail.com6c778162012-09-06 02:01:13 +000073 BBoxQueryBench(void* param, const char* name, MakeRectProc proc, bool bulkLoad,
rileya@google.com981b33a2012-09-05 18:36:17 +000074 QueryType q, SkBBoxHierarchy* tree)
skia.committer@gmail.com6c778162012-09-06 02:01:13 +000075 : INHERITED(param)
rileya@google.com981b33a2012-09-05 18:36:17 +000076 , fTree(tree)
77 , fProc(proc)
78 , fName(name)
79 , fBulkLoad(bulkLoad)
80 , fQuery(q) {
81 SkRandom rand;
82 for (int j = 0; j < SkBENCHLOOP(NUM_QUERY_RECTS); ++j) {
83 fTree->insert(reinterpret_cast<void*>(j), fProc(rand, j,
84 SkBENCHLOOP(NUM_QUERY_RECTS)), fBulkLoad);
85 }
86 fTree->flushDeferredInserts();
87 }
88protected:
89 virtual const char* onGetName() {
90 SkString str;
91 str.append("rtree_");
92 str.append(fName);
93 str.append("_query");
94 if (fBulkLoad) {
95 str.append("_bulk");
96 }
97 return str.c_str();
98 }
99 virtual void onDraw(SkCanvas* canvas) {
100 SkRandom rand;
101 for (int i = 0; i < SkBENCHLOOP(NUM_QUERIES); ++i) {
102 SkTDArray<void*> hits;
103 SkIRect query;
104 switch(fQuery) {
105 case kSmall_QueryType:
106 query.fLeft = rand.nextU() % GENERATE_EXTENTS;
107 query.fTop = rand.nextU() % GENERATE_EXTENTS;
108 query.fRight = query.fLeft + (GENERATE_EXTENTS / 20);
109 query.fBottom = query.fTop + (GENERATE_EXTENTS / 20);
110 break;
111 case kLarge_QueryType:
112 query.fLeft = rand.nextU() % GENERATE_EXTENTS;
113 query.fTop = rand.nextU() % GENERATE_EXTENTS;
114 query.fRight = query.fLeft + (GENERATE_EXTENTS / 2);
115 query.fBottom = query.fTop + (GENERATE_EXTENTS / 2);
116 break;
117 case kFull_QueryType:
118 query.fLeft = -GENERATE_EXTENTS;
119 query.fTop = -GENERATE_EXTENTS;
120 query.fRight = 2 * GENERATE_EXTENTS;
121 query.fBottom = 2 * GENERATE_EXTENTS;
122 break;
123 default: // fallthrough
124 case kRandom_QueryType:
125 query.fLeft = rand.nextU() % GENERATE_EXTENTS;
126 query.fTop = rand.nextU() % GENERATE_EXTENTS;
127 query.fRight = query.fLeft + 1 + rand.nextU() % (GENERATE_EXTENTS / 2);
128 query.fBottom = query.fTop + 1 + rand.nextU() % (GENERATE_EXTENTS / 2);
129 break;
130 };
131 fTree->search(query, &hits);
132 }
133 }
134private:
135 SkBBoxHierarchy* fTree;
136 MakeRectProc fProc;
137 const char* fName;
138 bool fBulkLoad;
139 QueryType fQuery;
140 typedef SkBenchmark INHERITED;
141};
142
143static SkIRect make_simple_rect(SkRandom&, int index, int numRects) {
144 SkIRect out = {0, 0, GENERATE_EXTENTS, GENERATE_EXTENTS};
145 return out;
146}
147
148static SkIRect make_concentric_rects_increasing(SkRandom&, int index, int numRects) {
149 SkIRect out = {0, 0, index + 1, index + 1};
150 return out;
151}
152
153static SkIRect make_concentric_rects_decreasing(SkRandom&, int index, int numRects) {
154 SkIRect out = {0, 0, numRects - index, numRects - index};
155 return out;
156}
157
158static SkIRect make_point_rects(SkRandom& rand, int index, int numRects) {
159 SkIRect out;
160 out.fLeft = rand.nextU() % GENERATE_EXTENTS;
161 out.fTop = rand.nextU() % GENERATE_EXTENTS;
162 out.fRight = out.fLeft + (GENERATE_EXTENTS / 200);
163 out.fBottom = out.fTop + (GENERATE_EXTENTS / 200);
164 return out;
165}
166
167static SkIRect make_random_rects(SkRandom& rand, int index, int numRects) {
168 SkIRect out;
169 out.fLeft = rand.nextS() % GENERATE_EXTENTS;
170 out.fTop = rand.nextS() % GENERATE_EXTENTS;
171 out.fRight = out.fLeft + 1 + rand.nextU() % (GENERATE_EXTENTS / 5);
172 out.fBottom = out.fTop + 1 + rand.nextU() % (GENERATE_EXTENTS / 5);
173 return out;
174}
175
176static SkIRect make_large_rects(SkRandom& rand, int index, int numRects) {
177 SkIRect out;
178 out.fLeft = rand.nextU() % GENERATE_EXTENTS;
179 out.fTop = rand.nextU() % GENERATE_EXTENTS;
180 out.fRight = out.fLeft + (GENERATE_EXTENTS / 3);
181 out.fBottom = out.fTop + (GENERATE_EXTENTS / 3);
182 return out;
183}
184
185///////////////////////////////////////////////////////////////////////////////
186
187static SkBenchmark* Fact0(void* p) {
188 return SkNEW_ARGS(BBoxBuildBench, (p, "random", &make_random_rects, true,
189 SkRTree::Create(5, 16)));
190}
191static SkBenchmark* Fact1(void* p) {
192 return SkNEW_ARGS(BBoxBuildBench, (p, "random", &make_random_rects, false,
193 SkRTree::Create(5, 16)));
194}
195static SkBenchmark* Fact2(void* p) {
196 return SkNEW_ARGS(BBoxBuildBench, (p, "concentric",
197 &make_concentric_rects_increasing, true, SkRTree::Create(5, 16)));
198}
199static SkBenchmark* Fact3(void* p) {
200 return SkNEW_ARGS(BBoxQueryBench, (p, "random", &make_random_rects, true,
201 BBoxQueryBench::kRandom_QueryType, SkRTree::Create(5, 16)));
202}
203static SkBenchmark* Fact4(void* p) {
204 return SkNEW_ARGS(BBoxQueryBench, (p, "random", &make_random_rects, false,
205 BBoxQueryBench::kRandom_QueryType, SkRTree::Create(5, 16)));
206}
207
208static BenchRegistry gReg0(Fact0);
209static BenchRegistry gReg1(Fact1);
210static BenchRegistry gReg2(Fact2);
211static BenchRegistry gReg3(Fact3);
212static BenchRegistry gReg4(Fact4);
213