github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/syndtr/goleveldb/leveldb/bench_test.go (about)

     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/insionng/yougam/libraries/syndtr/goleveldb/leveldb/iterator"
    20  	"github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/opt"
    21  	"github.com/insionng/yougam/libraries/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  	runtime.GOMAXPROCS(runtime.NumCPU())
   108  	return p
   109  }
   110  
   111  func (p *dbBench) reopen() {
   112  	p.db.Close()
   113  	var err error
   114  	p.db, err = Open(p.stor, p.o)
   115  	if err != nil {
   116  		p.b.Fatal("Reopen: got error: ", err)
   117  	}
   118  }
   119  
   120  func (p *dbBench) populate(n int) {
   121  	p.keys, p.values = make([][]byte, n), make([][]byte, n)
   122  	v := newValueGen(0.5)
   123  	for i := range p.keys {
   124  		p.keys[i], p.values[i] = []byte(fmt.Sprintf("%016d", i)), v.get(100)
   125  	}
   126  }
   127  
   128  func (p *dbBench) randomize() {
   129  	m := len(p.keys)
   130  	times := m * 2
   131  	r1, r2 := rand.New(rand.NewSource(0xdeadbeef)), rand.New(rand.NewSource(0xbeefface))
   132  	for n := 0; n < times; n++ {
   133  		i, j := r1.Int()%m, r2.Int()%m
   134  		if i == j {
   135  			continue
   136  		}
   137  		p.keys[i], p.keys[j] = p.keys[j], p.keys[i]
   138  		p.values[i], p.values[j] = p.values[j], p.values[i]
   139  	}
   140  }
   141  
   142  func (p *dbBench) writes(perBatch int) {
   143  	b := p.b
   144  	db := p.db
   145  
   146  	n := len(p.keys)
   147  	m := n / perBatch
   148  	if n%perBatch > 0 {
   149  		m++
   150  	}
   151  	batches := make([]Batch, m)
   152  	j := 0
   153  	for i := range batches {
   154  		first := true
   155  		for ; j < n && ((j+1)%perBatch != 0 || first); j++ {
   156  			first = false
   157  			batches[i].Put(p.keys[j], p.values[j])
   158  		}
   159  	}
   160  	runtime.GC()
   161  
   162  	b.ResetTimer()
   163  	b.StartTimer()
   164  	for i := range batches {
   165  		err := db.Write(&(batches[i]), p.wo)
   166  		if err != nil {
   167  			b.Fatal("write failed: ", err)
   168  		}
   169  	}
   170  	b.StopTimer()
   171  	b.SetBytes(116)
   172  }
   173  
   174  func (p *dbBench) gc() {
   175  	p.keys, p.values = nil, nil
   176  	runtime.GC()
   177  }
   178  
   179  func (p *dbBench) puts() {
   180  	b := p.b
   181  	db := p.db
   182  
   183  	b.ResetTimer()
   184  	b.StartTimer()
   185  	for i := range p.keys {
   186  		err := db.Put(p.keys[i], p.values[i], p.wo)
   187  		if err != nil {
   188  			b.Fatal("put failed: ", err)
   189  		}
   190  	}
   191  	b.StopTimer()
   192  	b.SetBytes(116)
   193  }
   194  
   195  func (p *dbBench) fill() {
   196  	b := p.b
   197  	db := p.db
   198  
   199  	perBatch := 10000
   200  	batch := new(Batch)
   201  	for i, n := 0, len(p.keys); i < n; {
   202  		first := true
   203  		for ; i < n && ((i+1)%perBatch != 0 || first); i++ {
   204  			first = false
   205  			batch.Put(p.keys[i], p.values[i])
   206  		}
   207  		err := db.Write(batch, p.wo)
   208  		if err != nil {
   209  			b.Fatal("write failed: ", err)
   210  		}
   211  		batch.Reset()
   212  	}
   213  }
   214  
   215  func (p *dbBench) gets() {
   216  	b := p.b
   217  	db := p.db
   218  
   219  	b.ResetTimer()
   220  	for i := range p.keys {
   221  		_, err := db.Get(p.keys[i], p.ro)
   222  		if err != nil {
   223  			b.Error("got error: ", err)
   224  		}
   225  	}
   226  	b.StopTimer()
   227  }
   228  
   229  func (p *dbBench) seeks() {
   230  	b := p.b
   231  
   232  	iter := p.newIter()
   233  	defer iter.Release()
   234  	b.ResetTimer()
   235  	for i := range p.keys {
   236  		if !iter.Seek(p.keys[i]) {
   237  			b.Error("value not found for: ", string(p.keys[i]))
   238  		}
   239  	}
   240  	b.StopTimer()
   241  }
   242  
   243  func (p *dbBench) newIter() iterator.Iterator {
   244  	iter := p.db.NewIterator(nil, p.ro)
   245  	err := iter.Error()
   246  	if err != nil {
   247  		p.b.Fatal("cannot create iterator: ", err)
   248  	}
   249  	return iter
   250  }
   251  
   252  func (p *dbBench) close() {
   253  	if bp, err := p.db.GetProperty("leveldb.blockpool"); err == nil {
   254  		p.b.Log("Block pool stats: ", bp)
   255  	}
   256  	p.db.Close()
   257  	p.stor.Close()
   258  	os.RemoveAll(benchDB)
   259  	p.db = nil
   260  	p.keys = nil
   261  	p.values = nil
   262  	runtime.GC()
   263  	runtime.GOMAXPROCS(1)
   264  }
   265  
   266  func BenchmarkDBWrite(b *testing.B) {
   267  	p := openDBBench(b, false)
   268  	p.populate(b.N)
   269  	p.writes(1)
   270  	p.close()
   271  }
   272  
   273  func BenchmarkDBWriteBatch(b *testing.B) {
   274  	p := openDBBench(b, false)
   275  	p.populate(b.N)
   276  	p.writes(1000)
   277  	p.close()
   278  }
   279  
   280  func BenchmarkDBWriteUncompressed(b *testing.B) {
   281  	p := openDBBench(b, true)
   282  	p.populate(b.N)
   283  	p.writes(1)
   284  	p.close()
   285  }
   286  
   287  func BenchmarkDBWriteBatchUncompressed(b *testing.B) {
   288  	p := openDBBench(b, true)
   289  	p.populate(b.N)
   290  	p.writes(1000)
   291  	p.close()
   292  }
   293  
   294  func BenchmarkDBWriteRandom(b *testing.B) {
   295  	p := openDBBench(b, false)
   296  	p.populate(b.N)
   297  	p.randomize()
   298  	p.writes(1)
   299  	p.close()
   300  }
   301  
   302  func BenchmarkDBWriteRandomSync(b *testing.B) {
   303  	p := openDBBench(b, false)
   304  	p.wo.Sync = true
   305  	p.populate(b.N)
   306  	p.writes(1)
   307  	p.close()
   308  }
   309  
   310  func BenchmarkDBOverwrite(b *testing.B) {
   311  	p := openDBBench(b, false)
   312  	p.populate(b.N)
   313  	p.writes(1)
   314  	p.writes(1)
   315  	p.close()
   316  }
   317  
   318  func BenchmarkDBOverwriteRandom(b *testing.B) {
   319  	p := openDBBench(b, false)
   320  	p.populate(b.N)
   321  	p.writes(1)
   322  	p.randomize()
   323  	p.writes(1)
   324  	p.close()
   325  }
   326  
   327  func BenchmarkDBPut(b *testing.B) {
   328  	p := openDBBench(b, false)
   329  	p.populate(b.N)
   330  	p.puts()
   331  	p.close()
   332  }
   333  
   334  func BenchmarkDBRead(b *testing.B) {
   335  	p := openDBBench(b, false)
   336  	p.populate(b.N)
   337  	p.fill()
   338  	p.gc()
   339  
   340  	iter := p.newIter()
   341  	b.ResetTimer()
   342  	for iter.Next() {
   343  	}
   344  	iter.Release()
   345  	b.StopTimer()
   346  	b.SetBytes(116)
   347  	p.close()
   348  }
   349  
   350  func BenchmarkDBReadGC(b *testing.B) {
   351  	p := openDBBench(b, false)
   352  	p.populate(b.N)
   353  	p.fill()
   354  
   355  	iter := p.newIter()
   356  	b.ResetTimer()
   357  	for iter.Next() {
   358  	}
   359  	iter.Release()
   360  	b.StopTimer()
   361  	b.SetBytes(116)
   362  	p.close()
   363  }
   364  
   365  func BenchmarkDBReadUncompressed(b *testing.B) {
   366  	p := openDBBench(b, true)
   367  	p.populate(b.N)
   368  	p.fill()
   369  	p.gc()
   370  
   371  	iter := p.newIter()
   372  	b.ResetTimer()
   373  	for iter.Next() {
   374  	}
   375  	iter.Release()
   376  	b.StopTimer()
   377  	b.SetBytes(116)
   378  	p.close()
   379  }
   380  
   381  func BenchmarkDBReadTable(b *testing.B) {
   382  	p := openDBBench(b, false)
   383  	p.populate(b.N)
   384  	p.fill()
   385  	p.reopen()
   386  	p.gc()
   387  
   388  	iter := p.newIter()
   389  	b.ResetTimer()
   390  	for iter.Next() {
   391  	}
   392  	iter.Release()
   393  	b.StopTimer()
   394  	b.SetBytes(116)
   395  	p.close()
   396  }
   397  
   398  func BenchmarkDBReadReverse(b *testing.B) {
   399  	p := openDBBench(b, false)
   400  	p.populate(b.N)
   401  	p.fill()
   402  	p.gc()
   403  
   404  	iter := p.newIter()
   405  	b.ResetTimer()
   406  	iter.Last()
   407  	for iter.Prev() {
   408  	}
   409  	iter.Release()
   410  	b.StopTimer()
   411  	b.SetBytes(116)
   412  	p.close()
   413  }
   414  
   415  func BenchmarkDBReadReverseTable(b *testing.B) {
   416  	p := openDBBench(b, false)
   417  	p.populate(b.N)
   418  	p.fill()
   419  	p.reopen()
   420  	p.gc()
   421  
   422  	iter := p.newIter()
   423  	b.ResetTimer()
   424  	iter.Last()
   425  	for iter.Prev() {
   426  	}
   427  	iter.Release()
   428  	b.StopTimer()
   429  	b.SetBytes(116)
   430  	p.close()
   431  }
   432  
   433  func BenchmarkDBSeek(b *testing.B) {
   434  	p := openDBBench(b, false)
   435  	p.populate(b.N)
   436  	p.fill()
   437  	p.seeks()
   438  	p.close()
   439  }
   440  
   441  func BenchmarkDBSeekRandom(b *testing.B) {
   442  	p := openDBBench(b, false)
   443  	p.populate(b.N)
   444  	p.fill()
   445  	p.randomize()
   446  	p.seeks()
   447  	p.close()
   448  }
   449  
   450  func BenchmarkDBGet(b *testing.B) {
   451  	p := openDBBench(b, false)
   452  	p.populate(b.N)
   453  	p.fill()
   454  	p.gets()
   455  	p.close()
   456  }
   457  
   458  func BenchmarkDBGetRandom(b *testing.B) {
   459  	p := openDBBench(b, false)
   460  	p.populate(b.N)
   461  	p.fill()
   462  	p.randomize()
   463  	p.gets()
   464  	p.close()
   465  }
   466  
   467  func BenchmarkDBReadConcurrent(b *testing.B) {
   468  	p := openDBBench(b, false)
   469  	p.populate(b.N)
   470  	p.fill()
   471  	p.gc()
   472  	defer p.close()
   473  
   474  	b.ResetTimer()
   475  	b.SetBytes(116)
   476  
   477  	b.RunParallel(func(pb *testing.PB) {
   478  		iter := p.newIter()
   479  		defer iter.Release()
   480  		for pb.Next() && iter.Next() {
   481  		}
   482  	})
   483  }
   484  
   485  func BenchmarkDBReadConcurrent2(b *testing.B) {
   486  	p := openDBBench(b, false)
   487  	p.populate(b.N)
   488  	p.fill()
   489  	p.gc()
   490  	defer p.close()
   491  
   492  	b.ResetTimer()
   493  	b.SetBytes(116)
   494  
   495  	var dir uint32
   496  	b.RunParallel(func(pb *testing.PB) {
   497  		iter := p.newIter()
   498  		defer iter.Release()
   499  		if atomic.AddUint32(&dir, 1)%2 == 0 {
   500  			for pb.Next() && iter.Next() {
   501  			}
   502  		} else {
   503  			if pb.Next() && iter.Last() {
   504  				for pb.Next() && iter.Prev() {
   505  				}
   506  			}
   507  		}
   508  	})
   509  }