go.etcd.io/etcd@v3.3.27+incompatible/mvcc/kvstore_bench_test.go (about)

     1  // Copyright 2015 The etcd Authors
     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 mvcc
    16  
    17  import (
    18  	"sync/atomic"
    19  	"testing"
    20  
    21  	"github.com/coreos/etcd/lease"
    22  	"github.com/coreos/etcd/mvcc/backend"
    23  )
    24  
    25  type fakeConsistentIndex uint64
    26  
    27  func (i *fakeConsistentIndex) ConsistentIndex() uint64 {
    28  	return atomic.LoadUint64((*uint64)(i))
    29  }
    30  
    31  func BenchmarkStorePut(b *testing.B) {
    32  	var i fakeConsistentIndex
    33  	be, tmpPath := backend.NewDefaultTmpBackend()
    34  	s := NewStore(be, &lease.FakeLessor{}, &i)
    35  	defer cleanup(s, be, tmpPath)
    36  
    37  	// arbitrary number of bytes
    38  	bytesN := 64
    39  	keys := createBytesSlice(bytesN, b.N)
    40  	vals := createBytesSlice(bytesN, b.N)
    41  
    42  	b.ResetTimer()
    43  	for i := 0; i < b.N; i++ {
    44  		s.Put(keys[i], vals[i], lease.NoLease)
    45  	}
    46  }
    47  
    48  func BenchmarkStoreRangeKey1(b *testing.B)   { benchmarkStoreRange(b, 1) }
    49  func BenchmarkStoreRangeKey100(b *testing.B) { benchmarkStoreRange(b, 100) }
    50  
    51  func benchmarkStoreRange(b *testing.B, n int) {
    52  	var i fakeConsistentIndex
    53  	be, tmpPath := backend.NewDefaultTmpBackend()
    54  	s := NewStore(be, &lease.FakeLessor{}, &i)
    55  	defer cleanup(s, be, tmpPath)
    56  
    57  	// 64 byte key/val
    58  	keys, val := createBytesSlice(64, n), createBytesSlice(64, 1)
    59  	for i := range keys {
    60  		s.Put(keys[i], val[0], lease.NoLease)
    61  	}
    62  	// Force into boltdb tx instead of backend read tx.
    63  	s.Commit()
    64  
    65  	var begin, end []byte
    66  	if n == 1 {
    67  		begin, end = keys[0], nil
    68  	} else {
    69  		begin, end = []byte{}, []byte{}
    70  	}
    71  
    72  	b.ReportAllocs()
    73  	b.ResetTimer()
    74  	for i := 0; i < b.N; i++ {
    75  		s.Range(begin, end, RangeOptions{})
    76  	}
    77  }
    78  
    79  func BenchmarkConsistentIndex(b *testing.B) {
    80  	fci := fakeConsistentIndex(10)
    81  	be, tmpPath := backend.NewDefaultTmpBackend()
    82  	s := NewStore(be, &lease.FakeLessor{}, &fci)
    83  	defer cleanup(s, be, tmpPath)
    84  
    85  	tx := s.b.BatchTx()
    86  	tx.Lock()
    87  	s.saveIndex(tx)
    88  	tx.Unlock()
    89  
    90  	b.ReportAllocs()
    91  	b.ResetTimer()
    92  	for i := 0; i < b.N; i++ {
    93  		s.ConsistentIndex()
    94  	}
    95  }
    96  
    97  // BenchmarkStoreTxnPutUpdate is same as above, but instead updates single key
    98  func BenchmarkStorePutUpdate(b *testing.B) {
    99  	var i fakeConsistentIndex
   100  	be, tmpPath := backend.NewDefaultTmpBackend()
   101  	s := NewStore(be, &lease.FakeLessor{}, &i)
   102  	defer cleanup(s, be, tmpPath)
   103  
   104  	// arbitrary number of bytes
   105  	keys := createBytesSlice(64, 1)
   106  	vals := createBytesSlice(1024, 1)
   107  
   108  	b.ResetTimer()
   109  	for i := 0; i < b.N; i++ {
   110  		s.Put(keys[0], vals[0], lease.NoLease)
   111  	}
   112  }
   113  
   114  // BenchmarkStoreTxnPut benchmarks the Put operation
   115  // with transaction begin and end, where transaction involves
   116  // some synchronization operations, such as mutex locking.
   117  func BenchmarkStoreTxnPut(b *testing.B) {
   118  	var i fakeConsistentIndex
   119  	be, tmpPath := backend.NewDefaultTmpBackend()
   120  	s := NewStore(be, &lease.FakeLessor{}, &i)
   121  	defer cleanup(s, be, tmpPath)
   122  
   123  	// arbitrary number of bytes
   124  	bytesN := 64
   125  	keys := createBytesSlice(bytesN, b.N)
   126  	vals := createBytesSlice(bytesN, b.N)
   127  
   128  	b.ResetTimer()
   129  	b.ReportAllocs()
   130  	for i := 0; i < b.N; i++ {
   131  		txn := s.Write()
   132  		txn.Put(keys[i], vals[i], lease.NoLease)
   133  		txn.End()
   134  	}
   135  }
   136  
   137  // benchmarkStoreRestore benchmarks the restore operation
   138  func benchmarkStoreRestore(revsPerKey int, b *testing.B) {
   139  	var i fakeConsistentIndex
   140  	be, tmpPath := backend.NewDefaultTmpBackend()
   141  	s := NewStore(be, &lease.FakeLessor{}, &i)
   142  	// use closure to capture 's' to pick up the reassignment
   143  	defer func() { cleanup(s, be, tmpPath) }()
   144  
   145  	// arbitrary number of bytes
   146  	bytesN := 64
   147  	keys := createBytesSlice(bytesN, b.N)
   148  	vals := createBytesSlice(bytesN, b.N)
   149  
   150  	for i := 0; i < b.N; i++ {
   151  		for j := 0; j < revsPerKey; j++ {
   152  			txn := s.Write()
   153  			txn.Put(keys[i], vals[i], lease.NoLease)
   154  			txn.End()
   155  		}
   156  	}
   157  	s.Close()
   158  
   159  	b.ReportAllocs()
   160  	b.ResetTimer()
   161  	s = NewStore(be, &lease.FakeLessor{}, &i)
   162  }
   163  
   164  func BenchmarkStoreRestoreRevs1(b *testing.B) {
   165  	benchmarkStoreRestore(1, b)
   166  }
   167  
   168  func BenchmarkStoreRestoreRevs10(b *testing.B) {
   169  	benchmarkStoreRestore(10, b)
   170  }
   171  
   172  func BenchmarkStoreRestoreRevs20(b *testing.B) {
   173  	benchmarkStoreRestore(20, b)
   174  }