github.com/Hnampk/fabric@v2.1.1+incompatible/core/ledger/kvledger/benchmark/experiments/readwrite_txs_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package experiments 8 9 import ( 10 "fmt" 11 "math/rand" 12 "sync" 13 "testing" 14 "time" 15 16 "github.com/hyperledger/fabric/common/util" 17 "github.com/hyperledger/fabric/core/ledger/kvledger/benchmark/chainmgmt" 18 ) 19 20 // BenchmarkReadWriteTxs opens the existing chains and modifies the Key-values by simulating read-write transactions 21 // For each of the chains, this test launches the parallel clients (based on the configuration) and the clients 22 // simulate and commit read-write transactions. This test assumes the pre-populated chain by previously running 23 // BenchmarkInsertTxs. Each transaction simultated by this benchmark randomly selects a configurable number of keys 24 // and modifies their values 25 // 26 // For instance, if this benchmark is invoked with the following test parameters 27 // -testParams=-NumChains=2, -NumParallelTxPerChain=2, -NumKVs=100, -NumTotalTx=200 28 // then client_1, and client_2 both execute 50 transactions on chain_1 in parallel. Similarly, 29 // client_3, and client_4 both execute 50 transactions on chain_2 in parallel 30 // In each of the transactions executed by any client, the transaction expects 31 // and modifies any key(s) between Key_1 to key_50 (because, total keys are to be 100 across two chains) 32 func BenchmarkReadWriteTxs(b *testing.B) { 33 if b.N != 1 { 34 panic(fmt.Errorf(`This benchmark should be called with N=1 only. Run this with more volume of data`)) 35 } 36 runReadWriteTest() 37 } 38 39 func runReadWriteTest() { 40 testEnv := chainmgmt.InitTestEnv(conf.chainMgrConf, conf.batchConf, chainmgmt.ChainInitOpOpen) 41 for _, chain := range testEnv.Chains() { 42 go runReadWriteClientsForChain(chain) 43 } 44 testEnv.WaitForTestCompletion() 45 } 46 47 func runReadWriteClientsForChain(chain *chainmgmt.Chain) { 48 numClients := conf.txConf.numParallelTxsPerChain 49 numTxForChain := calculateShare(conf.txConf.numTotalTxs, conf.chainMgrConf.NumChains, int(chain.ID)) 50 wg := &sync.WaitGroup{} 51 wg.Add(numClients) 52 for i := 0; i < numClients; i++ { 53 numTxForClient := calculateShare(numTxForChain, numClients, i) 54 randomNumGen := rand.New(rand.NewSource(int64(time.Now().Nanosecond()) + int64(chain.ID))) 55 go runReadWriteClient(chain, randomNumGen, numTxForClient, wg) 56 } 57 wg.Wait() 58 chain.Done() 59 } 60 61 func runReadWriteClient(chain *chainmgmt.Chain, rand *rand.Rand, numTx int, wg *sync.WaitGroup) { 62 numWritesPerTx := conf.txConf.numWritesPerTx 63 numReadsPerTx := conf.txConf.numReadsPerTx 64 maxKeyNumber := calculateShare(conf.dataConf.numKVs, conf.chainMgrConf.NumChains, int(chain.ID)) 65 kvSize := conf.dataConf.kvSize 66 useJSON := conf.dataConf.useJSON 67 var value []byte 68 69 for i := 0; i < numTx; i++ { 70 simulator, err := chain.NewTxSimulator(util.GenerateUUID()) 71 panicOnError(err) 72 maxKeys := max(numReadsPerTx, numWritesPerTx) 73 keysToOperateOn := []int{} 74 for i := 0; i < maxKeys; i++ { 75 keysToOperateOn = append(keysToOperateOn, rand.Intn(maxKeyNumber)) 76 } 77 78 for i := 0; i < numReadsPerTx; i++ { 79 keyNumber := keysToOperateOn[i] 80 value, err = simulator.GetState(chaincodeName, constructKey(keyNumber)) 81 panicOnError(err) 82 if useJSON { 83 if !verifyJSONValue(keyNumber, value) { 84 panic(fmt.Errorf("Value %s is not expected for key number %d", value, keyNumber)) 85 } 86 } else { 87 if !verifyValue(keyNumber, value) { 88 panic(fmt.Errorf("Value %s is not expected for key number %d", value, keyNumber)) 89 } 90 } 91 } 92 93 for i := 0; i < numWritesPerTx; i++ { 94 keyNumber := keysToOperateOn[i] 95 key := constructKey(keyNumber) 96 if useJSON { 97 value = []byte(constructJSONValue(keyNumber, kvSize)) 98 } else { 99 value = []byte(constructValue(keyNumber, kvSize)) 100 } 101 panicOnError(simulator.SetState(chaincodeName, key, value)) 102 } 103 simulator.Done() 104 sr, err := simulator.GetTxSimulationResults() 105 panicOnError(err) 106 srBytes, err := sr.GetPubSimulationBytes() 107 panicOnError(err) 108 chain.SubmitTx(srBytes) 109 } 110 wg.Done() 111 } 112 113 func max(a, b int) int { 114 if a > b { 115 return a 116 } 117 return b 118 }