github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/internal/debug/api.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:40</date>
    10  //</624342640623620096>
    11  
    12  
    13  //包调试接口转到运行时调试工具。
    14  //这个包主要是胶水代码使这些设施可用
    15  //通过cli和rpc子系统。如果你想从Go代码中使用它们,
    16  //改用包运行时。
    17  package debug
    18  
    19  import (
    20  	"bytes"
    21  	"errors"
    22  	"io"
    23  	"os"
    24  	"os/user"
    25  	"path/filepath"
    26  	"runtime"
    27  	"runtime/debug"
    28  	"runtime/pprof"
    29  	"strings"
    30  	"sync"
    31  	"time"
    32  
    33  	"github.com/ethereum/go-ethereum/log"
    34  )
    35  
    36  //处理程序是全局调试处理程序。
    37  var Handler = new(HandlerT)
    38  
    39  //handlert实现调试API。
    40  //不要创建此类型的值,请使用
    41  //而是在处理程序变量中。
    42  type HandlerT struct {
    43  	mu        sync.Mutex
    44  	cpuW      io.WriteCloser
    45  	cpuFile   string
    46  	traceW    io.WriteCloser
    47  	traceFile string
    48  }
    49  
    50  //冗长设置了原木冗长的天花板。单个包装的冗长程度
    51  //源文件可以使用vmodule来提升。
    52  func (*HandlerT) Verbosity(level int) {
    53  	glogger.Verbosity(log.Lvl(level))
    54  }
    55  
    56  //vmodule设置日志冗长模式。有关
    57  //模式语法。
    58  func (*HandlerT) Vmodule(pattern string) error {
    59  	return glogger.Vmodule(pattern)
    60  }
    61  
    62  //backtraceat设置日志backtrace位置。有关详细信息,请参阅包日志
    63  //模式语法。
    64  func (*HandlerT) BacktraceAt(location string) error {
    65  	return glogger.BacktraceAt(location)
    66  }
    67  
    68  //MEMSTATS返回详细的运行时内存统计信息。
    69  func (*HandlerT) MemStats() *runtime.MemStats {
    70  	s := new(runtime.MemStats)
    71  	runtime.ReadMemStats(s)
    72  	return s
    73  }
    74  
    75  //gcstats返回gc统计信息。
    76  func (*HandlerT) GcStats() *debug.GCStats {
    77  	s := new(debug.GCStats)
    78  	debug.ReadGCStats(s)
    79  	return s
    80  }
    81  
    82  //cpuprofile打开cpu配置文件达nsec秒并写入
    83  //配置文件数据到文件。
    84  func (h *HandlerT) CpuProfile(file string, nsec uint) error {
    85  	if err := h.StartCPUProfile(file); err != nil {
    86  		return err
    87  	}
    88  	time.Sleep(time.Duration(nsec) * time.Second)
    89  	h.StopCPUProfile()
    90  	return nil
    91  }
    92  
    93  //startcpuprofile打开CPU配置文件,写入给定文件。
    94  func (h *HandlerT) StartCPUProfile(file string) error {
    95  	h.mu.Lock()
    96  	defer h.mu.Unlock()
    97  	if h.cpuW != nil {
    98  		return errors.New("CPU profiling already in progress")
    99  	}
   100  	f, err := os.Create(expandHome(file))
   101  	if err != nil {
   102  		return err
   103  	}
   104  	if err := pprof.StartCPUProfile(f); err != nil {
   105  		f.Close()
   106  		return err
   107  	}
   108  	h.cpuW = f
   109  	h.cpuFile = file
   110  	log.Info("CPU profiling started", "dump", h.cpuFile)
   111  	return nil
   112  }
   113  
   114  //stopcupprofile停止正在进行的CPU配置文件。
   115  func (h *HandlerT) StopCPUProfile() error {
   116  	h.mu.Lock()
   117  	defer h.mu.Unlock()
   118  	pprof.StopCPUProfile()
   119  	if h.cpuW == nil {
   120  		return errors.New("CPU profiling not in progress")
   121  	}
   122  	log.Info("Done writing CPU profile", "dump", h.cpuFile)
   123  	h.cpuW.Close()
   124  	h.cpuW = nil
   125  	h.cpuFile = ""
   126  	return nil
   127  }
   128  
   129  //gotrace打开对nsec秒的跟踪并写入
   130  //将数据跟踪到文件。
   131  func (h *HandlerT) GoTrace(file string, nsec uint) error {
   132  	if err := h.StartGoTrace(file); err != nil {
   133  		return err
   134  	}
   135  	time.Sleep(time.Duration(nsec) * time.Second)
   136  	h.StopGoTrace()
   137  	return nil
   138  }
   139  
   140  //BoeStand将GOOTONE配置文件转换为NSEC秒,并将配置文件数据写入
   141  //文件。它使用1的配置率来获取最准确的信息。如果不同的利率是
   142  //需要时,设置速率并手动写入配置文件。
   143  func (*HandlerT) BlockProfile(file string, nsec uint) error {
   144  	runtime.SetBlockProfileRate(1)
   145  	time.Sleep(time.Duration(nsec) * time.Second)
   146  	defer runtime.SetBlockProfileRate(0)
   147  	return writeProfile("block", file)
   148  }
   149  
   150  //setBlockProfileRate设置goroutine块配置文件数据收集的速率。
   151  //速率0禁用块分析。
   152  func (*HandlerT) SetBlockProfileRate(rate int) {
   153  	runtime.SetBlockProfileRate(rate)
   154  }
   155  
   156  //WriteBlockProfile将goroutine阻塞配置文件写入给定文件。
   157  func (*HandlerT) WriteBlockProfile(file string) error {
   158  	return writeProfile("block", file)
   159  }
   160  
   161  //mutex profile打开mutex配置文件达nsec秒,并将配置文件数据写入文件。
   162  //它使用1的配置率来获取最准确的信息。如果不同的利率是
   163  //需要时,设置速率并手动写入配置文件。
   164  func (*HandlerT) MutexProfile(file string, nsec uint) error {
   165  	runtime.SetMutexProfileFraction(1)
   166  	time.Sleep(time.Duration(nsec) * time.Second)
   167  	defer runtime.SetMutexProfileFraction(0)
   168  	return writeProfile("mutex", file)
   169  }
   170  
   171  //setmutexprofilefraction设置mutex分析的速率。
   172  func (*HandlerT) SetMutexProfileFraction(rate int) {
   173  	runtime.SetMutexProfileFraction(rate)
   174  }
   175  
   176  //writemutexprofile将goroutine阻塞配置文件写入给定文件。
   177  func (*HandlerT) WriteMutexProfile(file string) error {
   178  	return writeProfile("mutex", file)
   179  }
   180  
   181  //WriteMemProfile将分配配置文件写入给定文件。
   182  //请注意,无法通过API设置分析速率,
   183  //必须在命令行上设置。
   184  func (*HandlerT) WriteMemProfile(file string) error {
   185  	return writeProfile("heap", file)
   186  }
   187  
   188  //Stacks返回所有goroutine堆栈的打印表示。
   189  func (*HandlerT) Stacks() string {
   190  	buf := new(bytes.Buffer)
   191  	pprof.Lookup("goroutine").WriteTo(buf, 2)
   192  	return buf.String()
   193  }
   194  
   195  //FreeosMemory将未使用的内存返回给操作系统。
   196  func (*HandlerT) FreeOSMemory() {
   197  	debug.FreeOSMemory()
   198  }
   199  
   200  //setgcPercent设置垃圾收集目标百分比。它返回上一个
   201  //设置。负值将禁用gc。
   202  func (*HandlerT) SetGCPercent(v int) int {
   203  	return debug.SetGCPercent(v)
   204  }
   205  
   206  func writeProfile(name, file string) error {
   207  	p := pprof.Lookup(name)
   208  	log.Info("Writing profile records", "count", p.Count(), "type", name, "dump", file)
   209  	f, err := os.Create(expandHome(file))
   210  	if err != nil {
   211  		return err
   212  	}
   213  	defer f.Close()
   214  	return p.WriteTo(f, 0)
   215  }
   216  
   217  //在文件路径中展开主目录。
   218  //~someuser/tmp将不会扩展。
   219  func expandHome(p string) string {
   220  	if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") {
   221  		home := os.Getenv("HOME")
   222  		if home == "" {
   223  			if usr, err := user.Current(); err == nil {
   224  				home = usr.HomeDir
   225  			}
   226  		}
   227  		if home != "" {
   228  			p = home + p[1:]
   229  		}
   230  	}
   231  	return filepath.Clean(p)
   232  }
   233