Skip to content

Commit 7e6d848

Browse files
Adding benchmark tests over some popular queries (#1755)
Here're results on my computer: ``` [12:52:04] AD: ~/Documents/go/src/github.com/blevesearch/bleve $ go test -run=BenchmarkQuery -bench=BenchmarkQuery -v goos: darwin goarch: amd64 pkg: github.com/blevesearch/bleve/v2 cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz BenchmarkQueryTerm BenchmarkQueryTerm-12 181676 6309 ns/op 4130 B/op 59 allocs/op BenchmarkQueryTermRange BenchmarkQueryTermRange-12 72004 16440 ns/op 7286 B/op 94 allocs/op BenchmarkQueryWildcard BenchmarkQueryWildcard-12 4686 251194 ns/op 124294 B/op 291 allocs/op BenchmarkQueryNumericRange BenchmarkQueryNumericRange-12 59023 20151 ns/op 12760 B/op 155 allocs/op BenchmarkQueryDateRange BenchmarkQueryDateRange-12 34382 33578 ns/op 18647 B/op 256 allocs/op BenchmarkQueryGeoDistance BenchmarkQueryGeoDistance-12 24669 41800 ns/op 26878 B/op 279 allocs/op BenchmarkQueryGeoBoundingBox BenchmarkQueryGeoBoundingBox-12 14122 84857 ns/op 47915 B/op 352 allocs/op PASS ok github.com/blevesearch/bleve/v2 507.927s ```
1 parent 56dc9b2 commit 7e6d848

File tree

1 file changed

+393
-0
lines changed

1 file changed

+393
-0
lines changed

query_bench_test.go

+393
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,393 @@
1+
// Copyright (c) 2022 Couchbase, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package bleve
16+
17+
import (
18+
"strconv"
19+
"testing"
20+
"time"
21+
22+
"github.com/blevesearch/bleve/v2/analysis/analyzer/keyword"
23+
"github.com/blevesearch/bleve/v2/mapping"
24+
)
25+
26+
func BenchmarkQueryTerm(b *testing.B) {
27+
tmpIndexPath := createTmpIndexPath(b)
28+
defer cleanupTmpIndexPath(b, tmpIndexPath)
29+
30+
fm := mapping.NewTextFieldMapping()
31+
fm.Analyzer = keyword.Name
32+
dmap := mapping.NewDocumentMapping()
33+
dmap.AddFieldMappingsAt("text", fm)
34+
imap := mapping.NewIndexMapping()
35+
imap.DefaultMapping = dmap
36+
37+
idx, err := New(tmpIndexPath, imap)
38+
if err != nil {
39+
b.Fatal(err)
40+
}
41+
42+
defer func() {
43+
err = idx.Close()
44+
if err != nil {
45+
b.Fatal(err)
46+
}
47+
}()
48+
49+
members := []string{"abc", "abcdef", "ghi", "jkl", "jklmno"}
50+
for i := 0; i < 100; i++ {
51+
if err = idx.Index(strconv.Itoa(i),
52+
map[string]interface{}{"text": members[i%len(members)]}); err != nil {
53+
b.Fatal(err)
54+
}
55+
}
56+
57+
b.ReportAllocs()
58+
b.ResetTimer()
59+
60+
for i := 0; i < b.N; i++ {
61+
q := NewTermQuery(members[i%len(members)])
62+
q.SetField("text")
63+
req := NewSearchRequest(q)
64+
if _, err = idx.Search(req); err != nil {
65+
b.Fatal(err)
66+
}
67+
}
68+
}
69+
70+
func BenchmarkQueryTermRange(b *testing.B) {
71+
tmpIndexPath := createTmpIndexPath(b)
72+
defer cleanupTmpIndexPath(b, tmpIndexPath)
73+
74+
fm := mapping.NewTextFieldMapping()
75+
fm.Analyzer = keyword.Name
76+
dmap := mapping.NewDocumentMapping()
77+
dmap.AddFieldMappingsAt("text", fm)
78+
imap := mapping.NewIndexMapping()
79+
imap.DefaultMapping = dmap
80+
81+
idx, err := New(tmpIndexPath, imap)
82+
if err != nil {
83+
b.Fatal(err)
84+
}
85+
86+
defer func() {
87+
err = idx.Close()
88+
if err != nil {
89+
b.Fatal(err)
90+
}
91+
}()
92+
93+
members := []string{"abc", "abcdef", "ghi", "jkl", "jklmno"}
94+
for i := 0; i < 100; i++ {
95+
if err = idx.Index(strconv.Itoa(i),
96+
map[string]interface{}{"text": members[i%len(members)]}); err != nil {
97+
b.Fatal(err)
98+
}
99+
}
100+
101+
b.ReportAllocs()
102+
b.ResetTimer()
103+
104+
inclusive := true
105+
for i := 0; i < b.N; i++ {
106+
q := NewTermRangeInclusiveQuery(
107+
members[i%(len(members)-2)],
108+
members[(i+2)%(len(members)-2)],
109+
&inclusive,
110+
&inclusive,
111+
)
112+
q.SetField("text")
113+
req := NewSearchRequest(q)
114+
if _, err = idx.Search(req); err != nil {
115+
b.Fatal(err)
116+
}
117+
}
118+
}
119+
120+
func BenchmarkQueryWildcard(b *testing.B) {
121+
tmpIndexPath := createTmpIndexPath(b)
122+
defer cleanupTmpIndexPath(b, tmpIndexPath)
123+
124+
fm := mapping.NewTextFieldMapping()
125+
fm.Analyzer = keyword.Name
126+
dmap := mapping.NewDocumentMapping()
127+
dmap.AddFieldMappingsAt("text", fm)
128+
imap := mapping.NewIndexMapping()
129+
imap.DefaultMapping = dmap
130+
131+
idx, err := New(tmpIndexPath, imap)
132+
if err != nil {
133+
b.Fatal(err)
134+
}
135+
136+
defer func() {
137+
err = idx.Close()
138+
if err != nil {
139+
b.Fatal(err)
140+
}
141+
}()
142+
143+
members := []string{"abc", "abcdef", "ghi", "jkl", "jklmno"}
144+
for i := 0; i < 100; i++ {
145+
if err = idx.Index(strconv.Itoa(i),
146+
map[string]interface{}{"text": members[i%len(members)]}); err != nil {
147+
b.Fatal(err)
148+
}
149+
}
150+
151+
wildcards := []string{"ab*", "jk*"}
152+
153+
b.ReportAllocs()
154+
b.ResetTimer()
155+
156+
for i := 0; i < b.N; i++ {
157+
q := NewWildcardQuery(wildcards[i%len(wildcards)])
158+
q.SetField("text")
159+
req := NewSearchRequest(q)
160+
if _, err = idx.Search(req); err != nil {
161+
b.Fatal(err)
162+
}
163+
}
164+
}
165+
166+
func BenchmarkQueryNumericRange(b *testing.B) {
167+
tmpIndexPath := createTmpIndexPath(b)
168+
defer cleanupTmpIndexPath(b, tmpIndexPath)
169+
170+
fm := mapping.NewNumericFieldMapping()
171+
dmap := mapping.NewDocumentMapping()
172+
dmap.AddFieldMappingsAt("number", fm)
173+
imap := mapping.NewIndexMapping()
174+
imap.DefaultMapping = dmap
175+
176+
idx, err := New(tmpIndexPath, imap)
177+
if err != nil {
178+
b.Fatal(err)
179+
}
180+
181+
defer func() {
182+
err = idx.Close()
183+
if err != nil {
184+
b.Fatal(err)
185+
}
186+
}()
187+
188+
for i := 0; i < 100; i++ {
189+
if err = idx.Index(strconv.Itoa(i),
190+
map[string]interface{}{"number": i}); err != nil {
191+
b.Fatal(err)
192+
}
193+
}
194+
195+
b.ReportAllocs()
196+
b.ResetTimer()
197+
198+
inclusive := true
199+
for i := 0; i < b.N; i++ {
200+
start := float64(i % 90)
201+
end := float64((i + 10) % 90)
202+
q := NewNumericRangeInclusiveQuery(&start, &end, &inclusive, &inclusive)
203+
q.SetField("number")
204+
req := NewSearchRequest(q)
205+
if _, err = idx.Search(req); err != nil {
206+
b.Fatal(err)
207+
}
208+
}
209+
}
210+
211+
func BenchmarkQueryDateRange(b *testing.B) {
212+
tmpIndexPath := createTmpIndexPath(b)
213+
defer cleanupTmpIndexPath(b, tmpIndexPath)
214+
215+
fm := mapping.NewDateTimeFieldMapping()
216+
dmap := mapping.NewDocumentMapping()
217+
dmap.AddFieldMappingsAt("date", fm)
218+
imap := mapping.NewIndexMapping()
219+
imap.DefaultMapping = dmap
220+
221+
idx, err := New(tmpIndexPath, imap)
222+
if err != nil {
223+
b.Fatal(err)
224+
}
225+
226+
defer func() {
227+
err = idx.Close()
228+
if err != nil {
229+
b.Fatal(err)
230+
}
231+
}()
232+
233+
members := []string{
234+
"2022-11-16T18:45:45Z",
235+
"2022-11-17T18:45:45Z",
236+
"2022-11-18T18:45:45Z",
237+
"2022-11-19T18:45:45Z",
238+
"2022-11-20T18:45:45Z",
239+
}
240+
for i := 0; i < 100; i++ {
241+
if err = idx.Index(strconv.Itoa(i),
242+
map[string]interface{}{"date": members[i%len(members)]}); err != nil {
243+
b.Fatal(err)
244+
}
245+
}
246+
247+
b.ReportAllocs()
248+
b.ResetTimer()
249+
250+
inclusive := true
251+
for i := 0; i < b.N; i++ {
252+
start, _ := time.Parse("2006-01-02T12:00:00Z", members[i%(len(members)-2)])
253+
end, _ := time.Parse("2006-01-02T12:00:00Z", members[(i+2)%(len(members)-2)])
254+
q := NewDateRangeInclusiveQuery(start, end, &inclusive, &inclusive)
255+
q.SetField("date")
256+
req := NewSearchRequest(q)
257+
if _, err = idx.Search(req); err != nil {
258+
b.Fatal(err)
259+
}
260+
}
261+
}
262+
263+
func BenchmarkQueryGeoDistance(b *testing.B) {
264+
tmpIndexPath := createTmpIndexPath(b)
265+
defer cleanupTmpIndexPath(b, tmpIndexPath)
266+
267+
fm := mapping.NewGeoPointFieldMapping()
268+
dmap := mapping.NewDocumentMapping()
269+
dmap.AddFieldMappingsAt("geo", fm)
270+
imap := mapping.NewIndexMapping()
271+
imap.DefaultMapping = dmap
272+
273+
idx, err := New(tmpIndexPath, imap)
274+
if err != nil {
275+
b.Fatal(err)
276+
}
277+
278+
defer func() {
279+
err = idx.Close()
280+
if err != nil {
281+
b.Fatal(err)
282+
}
283+
}()
284+
285+
members := [][]float64{
286+
{-121.96713072883645, 37.380331474621045},
287+
{-97.75518866579938, 30.38974491308761},
288+
{-0.08653451918110022, 51.51063984942306},
289+
{-2.230759791360498, 53.481514330841236},
290+
{77.59542326042589, 12.97215865921956},
291+
}
292+
for i := 0; i < 100; i++ {
293+
if err = idx.Index(strconv.Itoa(i),
294+
map[string]interface{}{"geo": members[i%len(members)]}); err != nil {
295+
b.Fatal(err)
296+
}
297+
}
298+
299+
b.ReportAllocs()
300+
b.ResetTimer()
301+
302+
for i := 0; i < b.N; i++ {
303+
coordinates := members[i%len(members)]
304+
q := NewGeoDistanceQuery(coordinates[0], coordinates[1], "1mi")
305+
q.SetField("geo")
306+
req := NewSearchRequest(q)
307+
if _, err = idx.Search(req); err != nil {
308+
b.Fatal(err)
309+
}
310+
}
311+
}
312+
313+
func BenchmarkQueryGeoBoundingBox(b *testing.B) {
314+
tmpIndexPath := createTmpIndexPath(b)
315+
defer cleanupTmpIndexPath(b, tmpIndexPath)
316+
317+
fm := mapping.NewGeoPointFieldMapping()
318+
dmap := mapping.NewDocumentMapping()
319+
dmap.AddFieldMappingsAt("geo", fm)
320+
imap := mapping.NewIndexMapping()
321+
imap.DefaultMapping = dmap
322+
323+
idx, err := New(tmpIndexPath, imap)
324+
if err != nil {
325+
b.Fatal(err)
326+
}
327+
328+
defer func() {
329+
err = idx.Close()
330+
if err != nil {
331+
b.Fatal(err)
332+
}
333+
}()
334+
335+
members := [][]float64{
336+
{-121.96713072883645, 37.380331474621045},
337+
{-97.75518866579938, 30.38974491308761},
338+
{-0.08653451918110022, 51.51063984942306},
339+
{-2.230759791360498, 53.481514330841236},
340+
{77.59542326042589, 12.97215865921956},
341+
}
342+
for i := 0; i < 100; i++ {
343+
if err = idx.Index(strconv.Itoa(i),
344+
map[string]interface{}{"geo": members[i%len(members)]}); err != nil {
345+
b.Fatal(err)
346+
}
347+
}
348+
349+
boundingBoxes := []struct {
350+
topLeft []float64
351+
bottomRight []float64
352+
}{
353+
{
354+
topLeft: []float64{-122.14424992609722, 37.49751487670511},
355+
bottomRight: []float64{-121.78076546622579, 37.26963069737202},
356+
},
357+
{
358+
topLeft: []float64{-97.85362236226437, 30.473743975245725},
359+
bottomRight: []float64{-97.58691085968482, 30.285211697102895},
360+
},
361+
{
362+
topLeft: []float64{-0.28538822102223094, 51.61106497119687},
363+
bottomRight: []float64{0.16776748108466677, 51.395702237541286},
364+
},
365+
{
366+
topLeft: []float64{-2.373683904907921, 53.54371945714075},
367+
bottomRight: []float64{-2.134365533113197, 53.41788831720595},
368+
},
369+
{
370+
topLeft: []float64{77.52617635172015, 13.037587208986437},
371+
bottomRight: []float64{77.66508989028102, 12.924426170584738},
372+
},
373+
}
374+
375+
b.ReportAllocs()
376+
b.ResetTimer()
377+
378+
for i := 0; i < b.N; i++ {
379+
topLeftCoordinates := boundingBoxes[i%len(boundingBoxes)].topLeft
380+
bottomRightCoordinates := boundingBoxes[i%len(boundingBoxes)].bottomRight
381+
q := NewGeoBoundingBoxQuery(
382+
topLeftCoordinates[0],
383+
topLeftCoordinates[1],
384+
bottomRightCoordinates[0],
385+
bottomRightCoordinates[1],
386+
)
387+
q.SetField("geo")
388+
req := NewSearchRequest(q)
389+
if _, err = idx.Search(req); err != nil {
390+
b.Fatal(err)
391+
}
392+
}
393+
}

0 commit comments

Comments
 (0)