OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / syndtr / goleveldb / leveldb / bench_test.go
1 // Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
2 // All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style license that can be
5 // found in the LICENSE file.
6
7 package leveldb
8
9 import (
10         "bytes"
11         "fmt"
12         "math/rand"
13         "os"
14         "path/filepath"
15         "runtime"
16         "sync/atomic"
17         "testing"
18
19         "github.com/syndtr/goleveldb/leveldb/iterator"
20         "github.com/syndtr/goleveldb/leveldb/opt"
21         "github.com/syndtr/goleveldb/leveldb/storage"
22 )
23
24 func randomString(r *rand.Rand, n int) []byte {
25         b := new(bytes.Buffer)
26         for i := 0; i < n; i++ {
27                 b.WriteByte(' ' + byte(r.Intn(95)))
28         }
29         return b.Bytes()
30 }
31
32 func compressibleStr(r *rand.Rand, frac float32, n int) []byte {
33         nn := int(float32(n) * frac)
34         rb := randomString(r, nn)
35         b := make([]byte, 0, n+nn)
36         for len(b) < n {
37                 b = append(b, rb...)
38         }
39         return b[:n]
40 }
41
42 type valueGen struct {
43         src []byte
44         pos int
45 }
46
47 func newValueGen(frac float32) *valueGen {
48         v := new(valueGen)
49         r := rand.New(rand.NewSource(301))
50         v.src = make([]byte, 0, 1048576+100)
51         for len(v.src) < 1048576 {
52                 v.src = append(v.src, compressibleStr(r, frac, 100)...)
53         }
54         return v
55 }
56
57 func (v *valueGen) get(n int) []byte {
58         if v.pos+n > len(v.src) {
59                 v.pos = 0
60         }
61         v.pos += n
62         return v.src[v.pos-n : v.pos]
63 }
64
65 var benchDB = filepath.Join(os.TempDir(), fmt.Sprintf("goleveldbbench-%d", os.Getuid()))
66
67 type dbBench struct {
68         b    *testing.B
69         stor storage.Storage
70         db   *DB
71
72         o  *opt.Options
73         ro *opt.ReadOptions
74         wo *opt.WriteOptions
75
76         keys, values [][]byte
77 }
78
79 func openDBBench(b *testing.B, noCompress bool) *dbBench {
80         _, err := os.Stat(benchDB)
81         if err == nil {
82                 err = os.RemoveAll(benchDB)
83                 if err != nil {
84                         b.Fatal("cannot remove old db: ", err)
85                 }
86         }
87
88         p := &dbBench{
89                 b:  b,
90                 o:  &opt.Options{},
91                 ro: &opt.ReadOptions{},
92                 wo: &opt.WriteOptions{},
93         }
94         p.stor, err = storage.OpenFile(benchDB, false)
95         if err != nil {
96                 b.Fatal("cannot open stor: ", err)
97         }
98         if noCompress {
99                 p.o.Compression = opt.NoCompression
100         }
101
102         p.db, err = Open(p.stor, p.o)
103         if err != nil {
104                 b.Fatal("cannot open db: ", err)
105         }
106
107         return p
108 }
109
110 func (p *dbBench) reopen() {
111         p.db.Close()
112         var err error
113         p.db, err = Open(p.stor, p.o)
114         if err != nil {
115                 p.b.Fatal("Reopen: got error: ", err)
116         }
117 }
118
119 func (p *dbBench) populate(n int) {
120         p.keys, p.values = make([][]byte, n), make([][]byte, n)
121         v := newValueGen(0.5)
122         for i := range p.keys {
123                 p.keys[i], p.values[i] = []byte(fmt.Sprintf("%016d", i)), v.get(100)
124         }
125 }
126
127 func (p *dbBench) randomize() {
128         m := len(p.keys)
129         times := m * 2
130         r1, r2 := rand.New(rand.NewSource(0xdeadbeef)), rand.New(rand.NewSource(0xbeefface))
131         for n := 0; n < times; n++ {
132                 i, j := r1.Int()%m, r2.Int()%m
133                 if i == j {
134                         continue
135                 }
136                 p.keys[i], p.keys[j] = p.keys[j], p.keys[i]
137                 p.values[i], p.values[j] = p.values[j], p.values[i]
138         }
139 }
140
141 func (p *dbBench) writes(perBatch int) {
142         b := p.b
143         db := p.db
144
145         n := len(p.keys)
146         m := n / perBatch
147         if n%perBatch > 0 {
148                 m++
149         }
150         batches := make([]Batch, m)
151         j := 0
152         for i := range batches {
153                 first := true
154                 for ; j < n && ((j+1)%perBatch != 0 || first); j++ {
155                         first = false
156                         batches[i].Put(p.keys[j], p.values[j])
157                 }
158         }
159         runtime.GC()
160
161         b.ResetTimer()
162         b.StartTimer()
163         for i := range batches {
164                 err := db.Write(&(batches[i]), p.wo)
165                 if err != nil {
166                         b.Fatal("write failed: ", err)
167                 }
168         }
169         b.StopTimer()
170         b.SetBytes(116)
171 }
172
173 func (p *dbBench) gc() {
174         p.keys, p.values = nil, nil
175         runtime.GC()
176 }
177
178 func (p *dbBench) puts() {
179         b := p.b
180         db := p.db
181
182         b.ResetTimer()
183         b.StartTimer()
184         for i := range p.keys {
185                 err := db.Put(p.keys[i], p.values[i], p.wo)
186                 if err != nil {
187                         b.Fatal("put failed: ", err)
188                 }
189         }
190         b.StopTimer()
191         b.SetBytes(116)
192 }
193
194 func (p *dbBench) fill() {
195         b := p.b
196         db := p.db
197
198         perBatch := 10000
199         batch := new(Batch)
200         for i, n := 0, len(p.keys); i < n; {
201                 first := true
202                 for ; i < n && ((i+1)%perBatch != 0 || first); i++ {
203                         first = false
204                         batch.Put(p.keys[i], p.values[i])
205                 }
206                 err := db.Write(batch, p.wo)
207                 if err != nil {
208                         b.Fatal("write failed: ", err)
209                 }
210                 batch.Reset()
211         }
212 }
213
214 func (p *dbBench) gets() {
215         b := p.b
216         db := p.db
217
218         b.ResetTimer()
219         for i := range p.keys {
220                 _, err := db.Get(p.keys[i], p.ro)
221                 if err != nil {
222                         b.Error("got error: ", err)
223                 }
224         }
225         b.StopTimer()
226 }
227
228 func (p *dbBench) seeks() {
229         b := p.b
230
231         iter := p.newIter()
232         defer iter.Release()
233         b.ResetTimer()
234         for i := range p.keys {
235                 if !iter.Seek(p.keys[i]) {
236                         b.Error("value not found for: ", string(p.keys[i]))
237                 }
238         }
239         b.StopTimer()
240 }
241
242 func (p *dbBench) newIter() iterator.Iterator {
243         iter := p.db.NewIterator(nil, p.ro)
244         err := iter.Error()
245         if err != nil {
246                 p.b.Fatal("cannot create iterator: ", err)
247         }
248         return iter
249 }
250
251 func (p *dbBench) close() {
252         if bp, err := p.db.GetProperty("leveldb.blockpool"); err == nil {
253                 p.b.Log("Block pool stats: ", bp)
254         }
255         p.db.Close()
256         p.stor.Close()
257         os.RemoveAll(benchDB)
258         p.db = nil
259         p.keys = nil
260         p.values = nil
261         runtime.GC()
262 }
263
264 func BenchmarkDBWrite(b *testing.B) {
265         p := openDBBench(b, false)
266         p.populate(b.N)
267         p.writes(1)
268         p.close()
269 }
270
271 func BenchmarkDBWriteBatch(b *testing.B) {
272         p := openDBBench(b, false)
273         p.populate(b.N)
274         p.writes(1000)
275         p.close()
276 }
277
278 func BenchmarkDBWriteUncompressed(b *testing.B) {
279         p := openDBBench(b, true)
280         p.populate(b.N)
281         p.writes(1)
282         p.close()
283 }
284
285 func BenchmarkDBWriteBatchUncompressed(b *testing.B) {
286         p := openDBBench(b, true)
287         p.populate(b.N)
288         p.writes(1000)
289         p.close()
290 }
291
292 func BenchmarkDBWriteRandom(b *testing.B) {
293         p := openDBBench(b, false)
294         p.populate(b.N)
295         p.randomize()
296         p.writes(1)
297         p.close()
298 }
299
300 func BenchmarkDBWriteRandomSync(b *testing.B) {
301         p := openDBBench(b, false)
302         p.wo.Sync = true
303         p.populate(b.N)
304         p.writes(1)
305         p.close()
306 }
307
308 func BenchmarkDBOverwrite(b *testing.B) {
309         p := openDBBench(b, false)
310         p.populate(b.N)
311         p.writes(1)
312         p.writes(1)
313         p.close()
314 }
315
316 func BenchmarkDBOverwriteRandom(b *testing.B) {
317         p := openDBBench(b, false)
318         p.populate(b.N)
319         p.writes(1)
320         p.randomize()
321         p.writes(1)
322         p.close()
323 }
324
325 func BenchmarkDBPut(b *testing.B) {
326         p := openDBBench(b, false)
327         p.populate(b.N)
328         p.puts()
329         p.close()
330 }
331
332 func BenchmarkDBRead(b *testing.B) {
333         p := openDBBench(b, false)
334         p.populate(b.N)
335         p.fill()
336         p.gc()
337
338         iter := p.newIter()
339         b.ResetTimer()
340         for iter.Next() {
341         }
342         iter.Release()
343         b.StopTimer()
344         b.SetBytes(116)
345         p.close()
346 }
347
348 func BenchmarkDBReadGC(b *testing.B) {
349         p := openDBBench(b, false)
350         p.populate(b.N)
351         p.fill()
352
353         iter := p.newIter()
354         b.ResetTimer()
355         for iter.Next() {
356         }
357         iter.Release()
358         b.StopTimer()
359         b.SetBytes(116)
360         p.close()
361 }
362
363 func BenchmarkDBReadUncompressed(b *testing.B) {
364         p := openDBBench(b, true)
365         p.populate(b.N)
366         p.fill()
367         p.gc()
368
369         iter := p.newIter()
370         b.ResetTimer()
371         for iter.Next() {
372         }
373         iter.Release()
374         b.StopTimer()
375         b.SetBytes(116)
376         p.close()
377 }
378
379 func BenchmarkDBReadTable(b *testing.B) {
380         p := openDBBench(b, false)
381         p.populate(b.N)
382         p.fill()
383         p.reopen()
384         p.gc()
385
386         iter := p.newIter()
387         b.ResetTimer()
388         for iter.Next() {
389         }
390         iter.Release()
391         b.StopTimer()
392         b.SetBytes(116)
393         p.close()
394 }
395
396 func BenchmarkDBReadReverse(b *testing.B) {
397         p := openDBBench(b, false)
398         p.populate(b.N)
399         p.fill()
400         p.gc()
401
402         iter := p.newIter()
403         b.ResetTimer()
404         iter.Last()
405         for iter.Prev() {
406         }
407         iter.Release()
408         b.StopTimer()
409         b.SetBytes(116)
410         p.close()
411 }
412
413 func BenchmarkDBReadReverseTable(b *testing.B) {
414         p := openDBBench(b, false)
415         p.populate(b.N)
416         p.fill()
417         p.reopen()
418         p.gc()
419
420         iter := p.newIter()
421         b.ResetTimer()
422         iter.Last()
423         for iter.Prev() {
424         }
425         iter.Release()
426         b.StopTimer()
427         b.SetBytes(116)
428         p.close()
429 }
430
431 func BenchmarkDBSeek(b *testing.B) {
432         p := openDBBench(b, false)
433         p.populate(b.N)
434         p.fill()
435         p.seeks()
436         p.close()
437 }
438
439 func BenchmarkDBSeekRandom(b *testing.B) {
440         p := openDBBench(b, false)
441         p.populate(b.N)
442         p.fill()
443         p.randomize()
444         p.seeks()
445         p.close()
446 }
447
448 func BenchmarkDBGet(b *testing.B) {
449         p := openDBBench(b, false)
450         p.populate(b.N)
451         p.fill()
452         p.gets()
453         p.close()
454 }
455
456 func BenchmarkDBGetRandom(b *testing.B) {
457         p := openDBBench(b, false)
458         p.populate(b.N)
459         p.fill()
460         p.randomize()
461         p.gets()
462         p.close()
463 }
464
465 func BenchmarkDBReadConcurrent(b *testing.B) {
466         p := openDBBench(b, false)
467         p.populate(b.N)
468         p.fill()
469         p.gc()
470         defer p.close()
471
472         b.ResetTimer()
473         b.SetBytes(116)
474
475         b.RunParallel(func(pb *testing.PB) {
476                 iter := p.newIter()
477                 defer iter.Release()
478                 for pb.Next() && iter.Next() {
479                 }
480         })
481 }
482
483 func BenchmarkDBReadConcurrent2(b *testing.B) {
484         p := openDBBench(b, false)
485         p.populate(b.N)
486         p.fill()
487         p.gc()
488         defer p.close()
489
490         b.ResetTimer()
491         b.SetBytes(116)
492
493         var dir uint32
494         b.RunParallel(func(pb *testing.PB) {
495                 iter := p.newIter()
496                 defer iter.Release()
497                 if atomic.AddUint32(&dir, 1)%2 == 0 {
498                         for pb.Next() && iter.Next() {
499                         }
500                 } else {
501                         if pb.Next() && iter.Last() {
502                                 for pb.Next() && iter.Prev() {
503                                 }
504                         }
505                 }
506         })
507 }