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