github.com/annchain/OG@v0.0.9/client/cmd/tps.go (about) 1 // Copyright © 2019 Annchain Authors <EMAIL ADDRESS> 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 cmd 16 17 import ( 18 "encoding/binary" 19 "fmt" 20 "github.com/annchain/OG/arefactor/common/io" 21 "github.com/annchain/OG/arefactor/common/utilfuncs" 22 "github.com/annchain/OG/arefactor/og/types" 23 "github.com/annchain/OG/arefactor/og_interface" 24 "github.com/annchain/OG/client/tx_client" 25 "github.com/annchain/OG/common/math" 26 "github.com/annchain/OG/ogdb" 27 "github.com/annchain/OG/rpc" 28 "github.com/spf13/cobra" 29 "github.com/spf13/viper" 30 "strings" 31 "sync" 32 "time" 33 ) 34 35 var ( 36 tpsCmd = &cobra.Command{ 37 Use: "tps", 38 Short: "tps", 39 } 40 tpsGenCmd = &cobra.Command{ 41 Use: "gen", 42 Short: "generate tx", 43 Run: tpsGen, 44 } 45 46 tpsSendTxCmd = &cobra.Command{ 47 Use: "send", 48 Short: "send", 49 Run: tpsSend, 50 } 51 num uint16 52 times uint16 53 accountNum uint16 54 ipports string 55 tpsNum uint16 56 ) 57 58 func tpsInit() { 59 tpsCmd.AddCommand(tpsGenCmd, tpsSendTxCmd) 60 tpsCmd.PersistentFlags().Uint16VarP(&num, "num", "n", 1000, "num 1000") 61 tpsCmd.PersistentFlags().Uint16VarP(&accountNum, "accounts_num", "a", 4, "accounts_num 1000") 62 tpsCmd.PersistentFlags().StringVarP(&ipports, "ips", "i", "", "accounts_num 1000") 63 tpsGenCmd.PersistentFlags().Uint16VarP(×, "times", "t", 1000, "times 1000") 64 tpsSendTxCmd.PersistentFlags().Uint16VarP(&tpsNum, "tps", "t", 1000, "tps 1000") 65 } 66 67 func tepsDataGen(threadNum uint16, db ogdb.Database, total uint16) { 68 _, priv := og_interface.Signer.RandomKeyPair() 69 requester := tx_client.NewRequestGenerator(priv) 70 to := types.RandomAddress() 71 requester.Nodebug = true 72 fmt.Println("will generate tx ", num, " * ", times) 73 for i := uint16(0); i < total; i++ { 74 var reqs rpc.NewTxsRequests 75 for j := uint16(0); j < num; j++ { 76 txReq := requester.NormalTx(0, uint64(i*num+1+j), to, math.NewBigInt(0)) 77 reqs.Txs = append(reqs.Txs, txReq) 78 } 79 data, err := reqs.MarshalMsg(nil) 80 utilfuncs.PanicIfError(err, "marshal err") 81 key := makeKey(threadNum, i) 82 err = db.Put(key, data) 83 utilfuncs.PanicIfError(err, "db err") 84 fmt.Println("gen tx ", i, threadNum) 85 } 86 } 87 88 func makeKey(i, j uint16) []byte { 89 data1 := make([]byte, 2) 90 binary.BigEndian.PutUint16(data1, i) 91 data2 := make([]byte, 2) 92 binary.BigEndian.PutUint16(data2, j) 93 return append(data1, data2...) 94 } 95 96 func tpsGen(cmd *cobra.Command, args []string) { 97 db, err := generateDb() 98 utilfuncs.PanicIfError(err, "") 99 defer db.Close() 100 start := time.Now() 101 //mp:= runtime.GOMAXPROCS(0) 102 mp := int(accountNum) 103 var wg = &sync.WaitGroup{} 104 wg.Wait() 105 for i := 0; i < mp; i++ { 106 wg.Add(1) 107 go func(k uint16) { 108 tepsDataGen(k, db, times/uint16(mp)) 109 wg.Done() 110 }(uint16(i)) 111 } 112 wg.Wait() 113 fmt.Println("used time for generating txs ", time.Since(start), num*times) 114 115 } 116 117 func tpsSend(cmd *cobra.Command, args []string) { 118 db, err := generateDb() 119 utilfuncs.PanicIfError(err, "") 120 defer db.Close() 121 start := time.Now() 122 //mp:= runtime.GOMAXPROCS(0) 123 //mp:= int(accountNum) 124 ipportList := strings.Split(ipports, ";") 125 if len(ipportList) == 0 { 126 fmt.Println("need ips and ports , for example : 127.0.0.1:8000;127.0.0.1:8010") 127 return 128 } 129 if int(accountNum) < len(ipportList) { 130 fmt.Println("need more accounts") 131 return 132 } 133 var wg = &sync.WaitGroup{} 134 hostNum := uint16(len(ipportList)) 135 perHost := accountNum / hostNum 136 tpsPerThread := (tpsNum / hostNum) / perHost 137 if tpsNum == 0 { 138 tpsPerThread = 0 139 } 140 for i := uint16(0); i < hostNum; i++ { 141 for j := uint16(0); j < perHost; j++ { 142 wg.Add(1) 143 go func(k uint16, host string) { 144 tpsSendData(k, db, host, tpsPerThread) 145 wg.Done() 146 }(i*perHost+j, ipportList[i]) 147 } 148 } 149 wg.Wait() 150 fmt.Println("used time for generating txs ", time.Since(start), num*times) 151 152 } 153 154 func tpsSendData(threadNum uint16, db ogdb.Database, host string, tpsPerThread uint16) { 155 txClient := tx_client.NewTxClientWIthTimeOut(host, false, time.Second*120) 156 Max := 1000000 157 for i := 0; i < Max; i++ { 158 var reqs rpc.NewTxsRequests 159 key := makeKey(threadNum, uint16(i)) 160 data, err := db.Get(key) 161 if err != nil || len(data) == 0 { 162 fmt.Println("read data err ", err, i) 163 break 164 } 165 _, err = reqs.UnmarshalMsg(data) 166 utilfuncs.PanicIfError(err, "unmarshal err") 167 j, k := 0, 0 168 for j < len(reqs.Txs) { 169 start := time.Now() 170 var newRequests rpc.NewTxsRequests 171 if int(tpsPerThread/2) < len(reqs.Txs) { 172 j = k + int(tpsPerThread/2) 173 } 174 if j > len(reqs.Txs) || tpsPerThread <= 0 { 175 j = len(reqs.Txs) 176 } 177 newRequests.Txs = append(newRequests.Txs, reqs.Txs[k:j]...) 178 txLen := len(newRequests.Txs) 179 k = j 180 resp, err := txClient.SendNormalTxs(&newRequests) 181 fmt.Println("sending data ", i, j, k, threadNum, txLen) 182 //utilfuncs.PanicIfError(err, resp) 183 if err != nil { 184 fmt.Println(err, resp) 185 return 186 } 187 if tpsPerThread > 0 { 188 if txLen < int(tpsPerThread/2)-1 { 189 continue 190 } 191 duration := time.Now().Sub(start) 192 shoudUseTime := time.Second / 2 193 //shoudUseTime := time.Second * time.Duration(txLen) / time.Duration(tpsPerThread) 194 if duration < shoudUseTime { 195 fmt.Println("should sleep ", i, j, k, shoudUseTime-duration) 196 time.Sleep(shoudUseTime - duration) 197 } 198 } 199 } 200 } 201 } 202 203 func generateDb() (ogdb.Database, error) { 204 path := io.FixPrefixPath(viper.GetString("./"), "test_tps_db") 205 return ogdb.NewLevelDB(path, 512, 512) 206 207 }