github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/system/trace/pprof.go (about)

     1  package trace
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path"
     7  	"runtime/pprof"
     8  	"time"
     9  
    10  	"github.com/fibonacci-chain/fbc/libs/tendermint/libs/log"
    11  )
    12  
    13  const (
    14  	defaultLoggerFlags     = os.O_RDWR | os.O_CREATE | os.O_APPEND
    15  	defaultLoggerPerm      = 0644
    16  	defaultCPUSamplingTime = 30 * time.Second // collect 30s cpu profile
    17  	defaultCoolDown        = 3 * time.Minute
    18  )
    19  
    20  var singlePprofDumper *pprofDumper
    21  
    22  func InitializePprofDumper(logger log.Logger, dumpPath string, coolDownStr string, abciElapsed int64) {
    23  	if singlePprofDumper != nil {
    24  		return
    25  	}
    26  	coolDown, err := time.ParseDuration(coolDownStr)
    27  	if err != nil {
    28  		coolDown = defaultCoolDown
    29  	}
    30  	singlePprofDumper = &pprofDumper{
    31  		logger:             logger.With("module", "main"),
    32  		dumpPath:           dumpPath,
    33  		coolDown:           coolDown,
    34  		cpuCoolDownTime:    time.Now(),
    35  		triggerAbciElapsed: abciElapsed,
    36  	}
    37  }
    38  
    39  type pprofDumper struct {
    40  	logger   log.Logger
    41  	dumpPath string
    42  	// the cool down time after every type of dump
    43  	coolDown           time.Duration
    44  	cpuCoolDownTime    time.Time
    45  	triggerAbciElapsed int64
    46  }
    47  
    48  func (dumper *pprofDumper) cpuProfile(height int64) {
    49  	if dumper.cpuCoolDownTime.After(time.Now()) {
    50  		dumper.logger.Info(fmt.Sprintf("height(%d) cpu dump is in coolDown", height))
    51  		return
    52  	}
    53  	dumper.cpuCoolDownTime = time.Now().Add(dumper.coolDown)
    54  	go dumper.dumpCpuPprof(height)
    55  }
    56  
    57  func (dumper *pprofDumper) dumpCpuPprof(height int64) {
    58  	fileName := dumper.getBinaryFileName(height)
    59  	bf, err := os.OpenFile(fileName, defaultLoggerFlags, defaultLoggerPerm)
    60  	if err != nil {
    61  		dumper.logger.Error("height(%d) dump cpu pprof, open file(%s) error:%s", height, fileName, err.Error())
    62  		return
    63  	}
    64  	defer bf.Close()
    65  
    66  	err = pprof.StartCPUProfile(bf)
    67  	if err != nil {
    68  		dumper.logger.Error("height(%d) dump cpu pprof, StartCPUProfile error:%s", height, err.Error())
    69  		return
    70  	}
    71  
    72  	time.Sleep(defaultCPUSamplingTime)
    73  	pprof.StopCPUProfile()
    74  	dumper.logger.Info("height(%d) dump cpu pprof file(%s)", fileName)
    75  }
    76  
    77  func (dumper *pprofDumper) getBinaryFileName(height int64) string {
    78  	var (
    79  		binarySuffix = time.Now().Format("20060102150405") + ".bin"
    80  	)
    81  	fileName := fmt.Sprintf("interval_%d_%s", height, binarySuffix)
    82  	return path.Join(dumper.dumpPath, fileName)
    83  }