...

Source file src/github.com/syndtr/goleveldb/leveldb/batch_test.go

Documentation: github.com/syndtr/goleveldb/leveldb

     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  	"testing"
    14  	"testing/quick"
    15  
    16  	"github.com/syndtr/goleveldb/leveldb/testutil"
    17  )
    18  
    19  func TestBatchHeader(t *testing.T) {
    20  	f := func(seq uint64, length uint32) bool {
    21  		encoded := encodeBatchHeader(nil, seq, int(length))
    22  		decSeq, decLength, err := decodeBatchHeader(encoded)
    23  		return err == nil && decSeq == seq && decLength == int(length)
    24  	}
    25  	config := &quick.Config{
    26  		Rand: testutil.NewRand(),
    27  	}
    28  	if err := quick.Check(f, config); err != nil {
    29  		t.Error(err)
    30  	}
    31  }
    32  
    33  type batchKV struct {
    34  	kt   keyType
    35  	k, v []byte
    36  }
    37  
    38  func TestBatch(t *testing.T) {
    39  	var (
    40  		kvs         []batchKV
    41  		internalLen int
    42  	)
    43  	batch := new(Batch)
    44  	rbatch := new(Batch)
    45  	abatch := new(Batch)
    46  	testBatch := func(i int, kt keyType, k, v []byte) error {
    47  		kv := kvs[i]
    48  		if kv.kt != kt {
    49  			return fmt.Errorf("invalid key type, index=%d: %d vs %d", i, kv.kt, kt)
    50  		}
    51  		if !bytes.Equal(kv.k, k) {
    52  			return fmt.Errorf("invalid key, index=%d", i)
    53  		}
    54  		if !bytes.Equal(kv.v, v) {
    55  			return fmt.Errorf("invalid value, index=%d", i)
    56  		}
    57  		return nil
    58  	}
    59  	f := func(ktr uint8, k, v []byte) bool {
    60  		kt := keyType(ktr % 2)
    61  		if kt == keyTypeVal {
    62  			batch.Put(k, v)
    63  			rbatch.Put(k, v)
    64  			kvs = append(kvs, batchKV{kt: kt, k: k, v: v})
    65  			internalLen += len(k) + len(v) + 8
    66  		} else {
    67  			batch.Delete(k)
    68  			rbatch.Delete(k)
    69  			kvs = append(kvs, batchKV{kt: kt, k: k})
    70  			internalLen += len(k) + 8
    71  		}
    72  		if batch.Len() != len(kvs) {
    73  			t.Logf("batch.Len: %d vs %d", len(kvs), batch.Len())
    74  			return false
    75  		}
    76  		if batch.internalLen != internalLen {
    77  			t.Logf("abatch.internalLen: %d vs %d", internalLen, batch.internalLen)
    78  			return false
    79  		}
    80  		if len(kvs)%1000 == 0 {
    81  			if err := batch.replayInternal(testBatch); err != nil {
    82  				t.Logf("batch.replayInternal: %v", err)
    83  				return false
    84  			}
    85  
    86  			abatch.append(rbatch)
    87  			rbatch.Reset()
    88  			if abatch.Len() != len(kvs) {
    89  				t.Logf("abatch.Len: %d vs %d", len(kvs), abatch.Len())
    90  				return false
    91  			}
    92  			if abatch.internalLen != internalLen {
    93  				t.Logf("abatch.internalLen: %d vs %d", internalLen, abatch.internalLen)
    94  				return false
    95  			}
    96  			if err := abatch.replayInternal(testBatch); err != nil {
    97  				t.Logf("abatch.replayInternal: %v", err)
    98  				return false
    99  			}
   100  
   101  			nbatch := new(Batch)
   102  			if err := nbatch.Load(batch.Dump()); err != nil {
   103  				t.Logf("nbatch.Load: %v", err)
   104  				return false
   105  			}
   106  			if nbatch.Len() != len(kvs) {
   107  				t.Logf("nbatch.Len: %d vs %d", len(kvs), nbatch.Len())
   108  				return false
   109  			}
   110  			if nbatch.internalLen != internalLen {
   111  				t.Logf("nbatch.internalLen: %d vs %d", internalLen, nbatch.internalLen)
   112  				return false
   113  			}
   114  			if err := nbatch.replayInternal(testBatch); err != nil {
   115  				t.Logf("nbatch.replayInternal: %v", err)
   116  				return false
   117  			}
   118  		}
   119  		if len(kvs)%10000 == 0 {
   120  			nbatch := new(Batch)
   121  			if err := batch.Replay(nbatch); err != nil {
   122  				t.Logf("batch.Replay: %v", err)
   123  				return false
   124  			}
   125  			if nbatch.Len() != len(kvs) {
   126  				t.Logf("nbatch.Len: %d vs %d", len(kvs), nbatch.Len())
   127  				return false
   128  			}
   129  			if nbatch.internalLen != internalLen {
   130  				t.Logf("nbatch.internalLen: %d vs %d", internalLen, nbatch.internalLen)
   131  				return false
   132  			}
   133  			if err := nbatch.replayInternal(testBatch); err != nil {
   134  				t.Logf("nbatch.replayInternal: %v", err)
   135  				return false
   136  			}
   137  		}
   138  		return true
   139  	}
   140  	config := &quick.Config{
   141  		MaxCount: 40000,
   142  		Rand:     testutil.NewRand(),
   143  	}
   144  	if err := quick.Check(f, config); err != nil {
   145  		t.Error(err)
   146  	}
   147  	t.Logf("length=%d internalLen=%d", len(kvs), internalLen)
   148  }
   149  
   150  func BenchmarkDefaultBatchWrite(b *testing.B) {
   151  	benchmarkBatchWrite(b, nil)
   152  }
   153  
   154  func BenchmarkFastAllocationBatchWrite(b *testing.B) {
   155  	benchmarkBatchWrite(b, &BatchConfig{
   156  		GrowLimit: 10 * batchGrowLimit,
   157  	})
   158  }
   159  
   160  func benchmarkBatchWrite(b *testing.B, config *BatchConfig) {
   161  	var (
   162  		keys [][]byte
   163  		vals [][]byte
   164  		r    = rand.New(rand.NewSource(1337))
   165  	)
   166  	for i := 0; i < 50000; i++ {
   167  		keys = append(keys, randomString(r, 32))
   168  		vals = append(vals, randomString(r, 100))
   169  	}
   170  	b.ResetTimer()
   171  	for round := 0; round < b.N; round++ {
   172  		batch := MakeBatchWithConfig(config)
   173  		for i := 0; i < len(keys); i++ {
   174  			batch.Put(keys[i], vals[i])
   175  		}
   176  	}
   177  	b.ReportAllocs()
   178  }
   179  

View as plain text