github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/system/trace/analyzer.go (about) 1 package trace 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 ) 8 9 var ( 10 analyzer *Analyzer = &Analyzer{} 11 ) 12 13 type Analyzer struct { 14 status bool 15 currentTxIndex int64 16 blockHeight int64 17 dbRead int64 18 dbWrite int64 19 evmCost int64 20 txs []*txLog 21 } 22 23 func (s *Analyzer) reset (height int64) { 24 s.status = status 25 s.currentTxIndex = 0 26 s.blockHeight = height 27 s.dbRead = 0 28 s.dbWrite = 0 29 s.evmCost = 0 30 s.txs = nil 31 } 32 33 func (s *Analyzer) onAppDeliverTxEnter() { 34 if s.status { 35 s.newTxLog() 36 } 37 } 38 39 func (s *Analyzer) onCommitDone() { 40 if s.status { 41 s.format() 42 } 43 } 44 45 func (s *Analyzer) newTxLog() { 46 s.currentTxIndex++ 47 s.txs = append(s.txs, newTxLog()) 48 } 49 50 func (s *Analyzer) startTxLog(oper string) { 51 if s.status { 52 if s.currentTxIndex > 0 && int64(len(s.txs)) == s.currentTxIndex { 53 s.txs[s.currentTxIndex-1].StartTxLog(oper) 54 } 55 } 56 } 57 58 func (s *Analyzer) stopTxLog(oper string) { 59 if s.status { 60 if s.currentTxIndex > 0 && int64(len(s.txs)) == s.currentTxIndex { 61 s.txs[s.currentTxIndex-1].StopTxLog(oper) 62 } 63 } 64 } 65 66 func (s *Analyzer) format() { 67 68 evmcore, record := s.genRecord() 69 for k, v := range record { 70 insertElapse(k, v) 71 } 72 73 if !openAnalyzer { 74 formatNecessaryDeliverTx(record) 75 return 76 } 77 formatDeliverTx(record) 78 formatRunAnteDetail(record) 79 formatEvmHandlerDetail(record) 80 81 // evm 82 GetElapsedInfo().AddInfo(Evm, fmt.Sprintf(EVM_FORMAT, s.dbRead, s.dbWrite, evmcore-s.dbRead-s.dbWrite)) 83 } 84 85 func (s *Analyzer) genRecord() (int64, map[string]int64) { 86 var evmcore int64 87 var record = make(map[string]int64) 88 for _, v := range s.txs { 89 for oper, operObj := range v.Record { 90 operType := dbOper.GetOperType(oper) 91 switch operType { 92 case READ: 93 s.dbRead += operObj.TimeCost 94 case WRITE: 95 s.dbWrite += operObj.TimeCost 96 case EVMALL: 97 evmcore += operObj.TimeCost 98 default: 99 if _, ok := record[oper]; !ok { 100 record[oper] = operObj.TimeCost 101 } else { 102 record[oper] += operObj.TimeCost 103 } 104 } 105 } 106 } 107 108 return evmcore, record 109 } 110 111 func formatNecessaryDeliverTx(record map[string]int64) { 112 // deliver txs 113 var deliverTxsKeys = []string{ 114 RunAnte, 115 RunMsg, 116 Refund, 117 } 118 addInfo(DeliverTxs, deliverTxsKeys, record) 119 } 120 121 func formatDeliverTx(record map[string]int64) { 122 // deliver txs 123 var deliverTxsKeys = []string{ 124 //----- DeliverTx 125 //bam.DeliverTx, 126 //bam.TxDecoder, 127 //bam.RunTx, 128 //----- run_tx 129 //bam.InitCtx, 130 ValTxMsgs, 131 RunAnte, 132 RunMsg, 133 Refund, 134 //EvmHandler, 135 } 136 addInfo(DeliverTxs, deliverTxsKeys, record) 137 } 138 139 func formatEvmHandlerDetail(record map[string]int64) { 140 // run msg 141 var evmHandlerKeys = []string{ 142 //bam.ConsumeGas, 143 //bam.Recover, 144 //----- handler 145 //bam.EvmHandler, 146 //bam.ParseChainID, 147 //bam.VerifySig, 148 Txhash, 149 SaveTx, 150 TransitionDb, 151 //bam.Bloomfilter, 152 //bam.EmitEvents, 153 //bam.HandlerDefer, 154 //----- 155 } 156 addInfo(EvmHandlerDetail, evmHandlerKeys, record) 157 } 158 159 func formatRunAnteDetail(record map[string]int64) { 160 // ante 161 var anteKeys = []string{ 162 CacheTxContext, 163 AnteChain, 164 AnteOther, 165 CacheStoreWrite, 166 } 167 addInfo(RunAnteDetail, anteKeys, record) 168 } 169 170 171 // formatRecord format the record in the format fmt.Sprintf(", %s<%dms>", v, record[v]) 172 func formatRecord(i int, key string, ms int64) string { 173 t := strconv.FormatInt(ms, 10) 174 b := strings.Builder{} 175 b.Grow(2 + len(key) + 1 + len(t) + 3) 176 if i != 0 { 177 b.WriteString(", ") 178 } 179 b.WriteString(key) 180 b.WriteString("<") 181 b.WriteString(t) 182 b.WriteString("ms>") 183 return b.String() 184 } 185 186 func addInfo(name string, keys []string, record map[string]int64) { 187 var strs = make([]string, len(keys)) 188 length := 0 189 for i, v := range keys { 190 strs[i] = formatRecord(i, v, record[v]) 191 length += len(strs[i]) 192 } 193 builder := strings.Builder{} 194 builder.Grow(length) 195 for _, v := range strs { 196 builder.WriteString(v) 197 } 198 GetElapsedInfo().AddInfo(name, builder.String()) 199 }