github.com/Finschia/finschia-sdk@v0.49.1/store/cachekv/store_bench_test.go (about) 1 package cachekv_test 2 3 import ( 4 "testing" 5 6 dbm "github.com/tendermint/tm-db" 7 8 "github.com/Finschia/finschia-sdk/store/cachekv" 9 "github.com/Finschia/finschia-sdk/store/dbadapter" 10 ) 11 12 var sink interface{} 13 14 const defaultValueSizeBz = 1 << 12 15 16 // This benchmark measures the time of iterator.Next() when the parent store is blank 17 func benchmarkBlankParentIteratorNext(b *testing.B, keysize int) { 18 b.Helper() 19 mem := dbadapter.Store{DB: dbm.NewMemDB()} 20 kvstore := cachekv.NewStore(mem) 21 // Use a singleton for value, to not waste time computing it 22 value := randSlice(defaultValueSizeBz) 23 // Use simple values for keys, pick a random start, 24 // and take next b.N keys sequentially after.] 25 startKey := randSlice(32) 26 27 // Add 1 to avoid issues when b.N = 1 28 keys := generateSequentialKeys(startKey, b.N+1) 29 for _, k := range keys { 30 kvstore.Set(k, value) 31 } 32 33 b.ReportAllocs() 34 b.ResetTimer() 35 36 iter := kvstore.Iterator(keys[0], keys[b.N]) 37 defer iter.Close() 38 39 for _ = iter.Key(); iter.Valid(); iter.Next() { 40 // deadcode elimination stub 41 sink = iter 42 } 43 } 44 45 // Benchmark setting New keys to a store, where the new keys are in sequence. 46 func benchmarkBlankParentAppend(b *testing.B, keysize int) { 47 b.Helper() 48 mem := dbadapter.Store{DB: dbm.NewMemDB()} 49 kvstore := cachekv.NewStore(mem) 50 51 // Use a singleton for value, to not waste time computing it 52 value := randSlice(32) 53 // Use simple values for keys, pick a random start, 54 // and take next b.N keys sequentially after. 55 startKey := randSlice(32) 56 57 keys := generateSequentialKeys(startKey, b.N) 58 59 b.ReportAllocs() 60 b.ResetTimer() 61 62 for _, k := range keys { 63 kvstore.Set(k, value) 64 } 65 } 66 67 // Benchmark setting New keys to a store, where the new keys are random. 68 // the speed of this function does not depend on the values in the parent store 69 func benchmarkRandomSet(b *testing.B, keysize int) { 70 b.Helper() 71 mem := dbadapter.Store{DB: dbm.NewMemDB()} 72 kvstore := cachekv.NewStore(mem) 73 74 // Use a singleton for value, to not waste time computing it 75 value := randSlice(defaultValueSizeBz) 76 keys := generateRandomKeys(keysize, b.N) 77 78 b.ReportAllocs() 79 b.ResetTimer() 80 81 for _, k := range keys { 82 kvstore.Set(k, value) 83 } 84 85 iter := kvstore.Iterator(nil, nil) 86 defer iter.Close() 87 88 for _ = iter.Key(); iter.Valid(); iter.Next() { 89 // deadcode elimination stub 90 sink = iter 91 } 92 } 93 94 // Benchmark creating an iterator on a parent with D entries, 95 // that are all deleted in the cacheKV store. 96 // We essentially are benchmarking the cacheKV iterator creation & iteration times 97 // with the number of entries deleted in the parent. 98 func benchmarkIteratorOnParentWithManyDeletes(b *testing.B, numDeletes int) { 99 b.Helper() 100 mem := dbadapter.Store{DB: dbm.NewMemDB()} 101 102 // Use a singleton for value, to not waste time computing it 103 value := randSlice(32) 104 // Use simple values for keys, pick a random start, 105 // and take next D keys sequentially after. 106 startKey := randSlice(32) 107 keys := generateSequentialKeys(startKey, numDeletes) 108 // setup parent db with D keys. 109 for _, k := range keys { 110 mem.Set(k, value) 111 } 112 kvstore := cachekv.NewStore(mem) 113 // Delete all keys from the cache KV store. 114 // The keys[1:] is to keep at least one entry in parent, due to a bug in the SDK iterator design. 115 // Essentially the iterator will never be valid, in that it should never run. 116 // However, this is incompatible with the for loop structure the SDK uses, hence 117 // causes a panic. Thus we do keys[1:]. 118 for _, k := range keys[1:] { 119 kvstore.Delete(k) 120 } 121 122 b.ReportAllocs() 123 b.ResetTimer() 124 125 iter := kvstore.Iterator(keys[0], keys[b.N]) 126 defer iter.Close() 127 128 for _ = iter.Key(); iter.Valid(); iter.Next() { 129 // deadcode elimination stub 130 sink = iter 131 } 132 } 133 134 func BenchmarkBlankParentIteratorNextKeySize32(b *testing.B) { 135 benchmarkBlankParentIteratorNext(b, 32) 136 } 137 138 func BenchmarkBlankParentAppendKeySize32(b *testing.B) { 139 benchmarkBlankParentAppend(b, 32) 140 } 141 142 func BenchmarkSetKeySize32(b *testing.B) { 143 benchmarkRandomSet(b, 32) 144 } 145 146 func BenchmarkIteratorOnParentWith1MDeletes(b *testing.B) { 147 benchmarkIteratorOnParentWithManyDeletes(b, 1_000_000) 148 }