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  }