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