github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/internal/debug/api.go (about)

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