blob: edea57d10a880fe9086ee902aa2ca3bb533d47de [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)
rileya@google.com61348d12012-09-06 13:38:53 +000031 , fBulkLoad(bulkLoad) {
32 fName.append("rtree_");
33 fName.append(name);
34 fName.append("_build");
35 if (fBulkLoad) {
36 fName.append("_bulk");
37 }
38 }
robertphillips@google.com07a05d52012-09-11 11:54:07 +000039 virtual ~BBoxBuildBench() {
40 delete fTree;
41 }
rileya@google.com981b33a2012-09-05 18:36:17 +000042protected:
43 virtual const char* onGetName() {
rileya@google.com61348d12012-09-06 13:38:53 +000044 return fName.c_str();
rileya@google.com981b33a2012-09-05 18:36:17 +000045 }
46 virtual void onDraw(SkCanvas* canvas) {
47 SkRandom rand;
48 for (int i = 0; i < SkBENCHLOOP(100); ++i) {
49 for (int j = 0; j < NUM_BUILD_RECTS; ++j) {
50 fTree->insert(reinterpret_cast<void*>(j), fProc(rand, j, NUM_BUILD_RECTS),
51 fBulkLoad);
52 }
53 fTree->flushDeferredInserts();
54 fTree->clear();
55 }
56 }
57private:
58 SkBBoxHierarchy* fTree;
59 MakeRectProc fProc;
rileya@google.com61348d12012-09-06 13:38:53 +000060 SkString fName;
rileya@google.com981b33a2012-09-05 18:36:17 +000061 bool fBulkLoad;
62 typedef SkBenchmark INHERITED;
63};
64
65// Time how long it takes to perform queries on an R-Tree, bulk-loaded or not
66class BBoxQueryBench : public SkBenchmark {
67public:
68 enum QueryType {
69 kSmall_QueryType, // small queries
70 kLarge_QueryType, // large queries
71 kRandom_QueryType,// randomly sized queries
72 kFull_QueryType // queries that cover everything
73 };
74
skia.committer@gmail.com6c778162012-09-06 02:01:13 +000075 BBoxQueryBench(void* param, const char* name, MakeRectProc proc, bool bulkLoad,
rileya@google.com981b33a2012-09-05 18:36:17 +000076 QueryType q, SkBBoxHierarchy* tree)
skia.committer@gmail.com6c778162012-09-06 02:01:13 +000077 : INHERITED(param)
rileya@google.com981b33a2012-09-05 18:36:17 +000078 , fTree(tree)
79 , fProc(proc)
rileya@google.com981b33a2012-09-05 18:36:17 +000080 , fBulkLoad(bulkLoad)
81 , fQuery(q) {
rileya@google.com61348d12012-09-06 13:38:53 +000082 fName.append("rtree_");
83 fName.append(name);
84 fName.append("_query");
85 if (fBulkLoad) {
86 fName.append("_bulk");
87 }
rileya@google.com981b33a2012-09-05 18:36:17 +000088 SkRandom rand;
89 for (int j = 0; j < SkBENCHLOOP(NUM_QUERY_RECTS); ++j) {
90 fTree->insert(reinterpret_cast<void*>(j), fProc(rand, j,
91 SkBENCHLOOP(NUM_QUERY_RECTS)), fBulkLoad);
92 }
93 fTree->flushDeferredInserts();
94 }
robertphillips@google.com07a05d52012-09-11 11:54:07 +000095 virtual ~BBoxQueryBench() {
96 delete fTree;
97 }
rileya@google.com981b33a2012-09-05 18:36:17 +000098protected:
99 virtual const char* onGetName() {
rileya@google.com61348d12012-09-06 13:38:53 +0000100 return fName.c_str();
rileya@google.com981b33a2012-09-05 18:36:17 +0000101 }
102 virtual void onDraw(SkCanvas* canvas) {
103 SkRandom rand;
104 for (int i = 0; i < SkBENCHLOOP(NUM_QUERIES); ++i) {
105 SkTDArray<void*> hits;
106 SkIRect query;
107 switch(fQuery) {
108 case kSmall_QueryType:
109 query.fLeft = rand.nextU() % GENERATE_EXTENTS;
110 query.fTop = rand.nextU() % GENERATE_EXTENTS;
111 query.fRight = query.fLeft + (GENERATE_EXTENTS / 20);
112 query.fBottom = query.fTop + (GENERATE_EXTENTS / 20);
113 break;
114 case kLarge_QueryType:
115 query.fLeft = rand.nextU() % GENERATE_EXTENTS;
116 query.fTop = rand.nextU() % GENERATE_EXTENTS;
117 query.fRight = query.fLeft + (GENERATE_EXTENTS / 2);
118 query.fBottom = query.fTop + (GENERATE_EXTENTS / 2);
119 break;
120 case kFull_QueryType:
121 query.fLeft = -GENERATE_EXTENTS;
122 query.fTop = -GENERATE_EXTENTS;
123 query.fRight = 2 * GENERATE_EXTENTS;
124 query.fBottom = 2 * GENERATE_EXTENTS;
125 break;
126 default: // fallthrough
127 case kRandom_QueryType:
128 query.fLeft = rand.nextU() % GENERATE_EXTENTS;
129 query.fTop = rand.nextU() % GENERATE_EXTENTS;
130 query.fRight = query.fLeft + 1 + rand.nextU() % (GENERATE_EXTENTS / 2);
131 query.fBottom = query.fTop + 1 + rand.nextU() % (GENERATE_EXTENTS / 2);
132 break;
133 };
134 fTree->search(query, &hits);
135 }
136 }
137private:
138 SkBBoxHierarchy* fTree;
139 MakeRectProc fProc;
rileya@google.com61348d12012-09-06 13:38:53 +0000140 SkString fName;
rileya@google.com981b33a2012-09-05 18:36:17 +0000141 bool fBulkLoad;
142 QueryType fQuery;
143 typedef SkBenchmark INHERITED;
144};
145
146static SkIRect make_simple_rect(SkRandom&, int index, int numRects) {
147 SkIRect out = {0, 0, GENERATE_EXTENTS, GENERATE_EXTENTS};
148 return out;
149}
150
151static SkIRect make_concentric_rects_increasing(SkRandom&, int index, int numRects) {
152 SkIRect out = {0, 0, index + 1, index + 1};
153 return out;
154}
155
156static SkIRect make_concentric_rects_decreasing(SkRandom&, int index, int numRects) {
157 SkIRect out = {0, 0, numRects - index, numRects - index};
158 return out;
159}
160
161static SkIRect make_point_rects(SkRandom& rand, int index, int numRects) {
162 SkIRect out;
163 out.fLeft = rand.nextU() % GENERATE_EXTENTS;
164 out.fTop = rand.nextU() % GENERATE_EXTENTS;
165 out.fRight = out.fLeft + (GENERATE_EXTENTS / 200);
166 out.fBottom = out.fTop + (GENERATE_EXTENTS / 200);
167 return out;
168}
169
170static SkIRect make_random_rects(SkRandom& rand, int index, int numRects) {
171 SkIRect out;
172 out.fLeft = rand.nextS() % GENERATE_EXTENTS;
173 out.fTop = rand.nextS() % GENERATE_EXTENTS;
174 out.fRight = out.fLeft + 1 + rand.nextU() % (GENERATE_EXTENTS / 5);
175 out.fBottom = out.fTop + 1 + rand.nextU() % (GENERATE_EXTENTS / 5);
176 return out;
177}
178
179static SkIRect make_large_rects(SkRandom& rand, int index, int numRects) {
180 SkIRect out;
181 out.fLeft = rand.nextU() % GENERATE_EXTENTS;
182 out.fTop = rand.nextU() % GENERATE_EXTENTS;
183 out.fRight = out.fLeft + (GENERATE_EXTENTS / 3);
184 out.fBottom = out.fTop + (GENERATE_EXTENTS / 3);
185 return out;
186}
187
188///////////////////////////////////////////////////////////////////////////////
189
190static SkBenchmark* Fact0(void* p) {
191 return SkNEW_ARGS(BBoxBuildBench, (p, "random", &make_random_rects, true,
192 SkRTree::Create(5, 16)));
193}
194static SkBenchmark* Fact1(void* p) {
195 return SkNEW_ARGS(BBoxBuildBench, (p, "random", &make_random_rects, false,
196 SkRTree::Create(5, 16)));
197}
198static SkBenchmark* Fact2(void* p) {
199 return SkNEW_ARGS(BBoxBuildBench, (p, "concentric",
200 &make_concentric_rects_increasing, true, SkRTree::Create(5, 16)));
201}
202static SkBenchmark* Fact3(void* p) {
203 return SkNEW_ARGS(BBoxQueryBench, (p, "random", &make_random_rects, true,
204 BBoxQueryBench::kRandom_QueryType, SkRTree::Create(5, 16)));
205}
206static SkBenchmark* Fact4(void* p) {
207 return SkNEW_ARGS(BBoxQueryBench, (p, "random", &make_random_rects, false,
208 BBoxQueryBench::kRandom_QueryType, SkRTree::Create(5, 16)));
209}
210
211static BenchRegistry gReg0(Fact0);
212static BenchRegistry gReg1(Fact1);
213static BenchRegistry gReg2(Fact2);
214static BenchRegistry gReg3(Fact3);
215static BenchRegistry gReg4(Fact4);
216