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 }