1 // Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
2 // All rights reserved.
4 // Use of this source code is governed by a BSD-style license that can be
5 // found in the LICENSE file.
19 "github.com/syndtr/goleveldb/leveldb/iterator"
20 "github.com/syndtr/goleveldb/leveldb/opt"
21 "github.com/syndtr/goleveldb/leveldb/storage"
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)))
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)
42 type valueGen struct {
47 func newValueGen(frac float32) *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)...)
57 func (v *valueGen) get(n int) []byte {
58 if v.pos+n > len(v.src) {
62 return v.src[v.pos-n : v.pos]
65 var benchDB = filepath.Join(os.TempDir(), fmt.Sprintf("goleveldbbench-%d", os.Getuid()))
79 func openDBBench(b *testing.B, noCompress bool) *dbBench {
80 _, err := os.Stat(benchDB)
82 err = os.RemoveAll(benchDB)
84 b.Fatal("cannot remove old db: ", err)
91 ro: &opt.ReadOptions{},
92 wo: &opt.WriteOptions{},
94 p.stor, err = storage.OpenFile(benchDB, false)
96 b.Fatal("cannot open stor: ", err)
99 p.o.Compression = opt.NoCompression
102 p.db, err = Open(p.stor, p.o)
104 b.Fatal("cannot open db: ", err)
110 func (p *dbBench) reopen() {
113 p.db, err = Open(p.stor, p.o)
115 p.b.Fatal("Reopen: got error: ", err)
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)
127 func (p *dbBench) randomize() {
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
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]
141 func (p *dbBench) writes(perBatch int) {
150 batches := make([]Batch, m)
152 for i := range batches {
154 for ; j < n && ((j+1)%perBatch != 0 || first); j++ {
156 batches[i].Put(p.keys[j], p.values[j])
163 for i := range batches {
164 err := db.Write(&(batches[i]), p.wo)
166 b.Fatal("write failed: ", err)
173 func (p *dbBench) gc() {
174 p.keys, p.values = nil, nil
178 func (p *dbBench) puts() {
184 for i := range p.keys {
185 err := db.Put(p.keys[i], p.values[i], p.wo)
187 b.Fatal("put failed: ", err)
194 func (p *dbBench) fill() {
200 for i, n := 0, len(p.keys); i < n; {
202 for ; i < n && ((i+1)%perBatch != 0 || first); i++ {
204 batch.Put(p.keys[i], p.values[i])
206 err := db.Write(batch, p.wo)
208 b.Fatal("write failed: ", err)
214 func (p *dbBench) gets() {
219 for i := range p.keys {
220 _, err := db.Get(p.keys[i], p.ro)
222 b.Error("got error: ", err)
228 func (p *dbBench) seeks() {
234 for i := range p.keys {
235 if !iter.Seek(p.keys[i]) {
236 b.Error("value not found for: ", string(p.keys[i]))
242 func (p *dbBench) newIter() iterator.Iterator {
243 iter := p.db.NewIterator(nil, p.ro)
246 p.b.Fatal("cannot create iterator: ", err)
251 func (p *dbBench) close() {
252 if bp, err := p.db.GetProperty("leveldb.blockpool"); err == nil {
253 p.b.Log("Block pool stats: ", bp)
257 os.RemoveAll(benchDB)
264 func BenchmarkDBWrite(b *testing.B) {
265 p := openDBBench(b, false)
271 func BenchmarkDBWriteBatch(b *testing.B) {
272 p := openDBBench(b, false)
278 func BenchmarkDBWriteUncompressed(b *testing.B) {
279 p := openDBBench(b, true)
285 func BenchmarkDBWriteBatchUncompressed(b *testing.B) {
286 p := openDBBench(b, true)
292 func BenchmarkDBWriteRandom(b *testing.B) {
293 p := openDBBench(b, false)
300 func BenchmarkDBWriteRandomSync(b *testing.B) {
301 p := openDBBench(b, false)
308 func BenchmarkDBOverwrite(b *testing.B) {
309 p := openDBBench(b, false)
316 func BenchmarkDBOverwriteRandom(b *testing.B) {
317 p := openDBBench(b, false)
325 func BenchmarkDBPut(b *testing.B) {
326 p := openDBBench(b, false)
332 func BenchmarkDBRead(b *testing.B) {
333 p := openDBBench(b, false)
348 func BenchmarkDBReadGC(b *testing.B) {
349 p := openDBBench(b, false)
363 func BenchmarkDBReadUncompressed(b *testing.B) {
364 p := openDBBench(b, true)
379 func BenchmarkDBReadTable(b *testing.B) {
380 p := openDBBench(b, false)
396 func BenchmarkDBReadReverse(b *testing.B) {
397 p := openDBBench(b, false)
413 func BenchmarkDBReadReverseTable(b *testing.B) {
414 p := openDBBench(b, false)
431 func BenchmarkDBSeek(b *testing.B) {
432 p := openDBBench(b, false)
439 func BenchmarkDBSeekRandom(b *testing.B) {
440 p := openDBBench(b, false)
448 func BenchmarkDBGet(b *testing.B) {
449 p := openDBBench(b, false)
456 func BenchmarkDBGetRandom(b *testing.B) {
457 p := openDBBench(b, false)
465 func BenchmarkDBReadConcurrent(b *testing.B) {
466 p := openDBBench(b, false)
475 b.RunParallel(func(pb *testing.PB) {
478 for pb.Next() && iter.Next() {
483 func BenchmarkDBReadConcurrent2(b *testing.B) {
484 p := openDBBench(b, false)
494 b.RunParallel(func(pb *testing.PB) {
497 if atomic.AddUint32(&dir, 1)%2 == 0 {
498 for pb.Next() && iter.Next() {
501 if pb.Next() && iter.Last() {
502 for pb.Next() && iter.Prev() {