来源:cyningsun.github.io/07-21-2019/…php
Go生态系统提供了大量API和工具来诊断Go程序中的逻辑和性能问题。 此页面总结了可用的工具,并帮助Go用户针对他们的特定问题选择正确的工具。html
诊断解决方案可分为如下几组:前端
注意:某些诊断工具可能会相互干扰。 例如,精确的 memory profiling 会扭曲 CPU profiles,而goroutine blocking profiling 会影响 scheduler trace。 隔离使用工具可得到更精确的信息。git
Profiling 对于识别昂贵或常常调用的代码段颇有用。 Go runtime 以 pprof 可视化工具所指望的格式提供 profiling data。 在测试期间能够经过 go test
或 net/http/pprof 包提供的 endpoints 收集 profiling data。 用户须要收集 profiling data 并使用 pprof 工具来过滤和可视化顶部代码路径。github
runtime/pprof 包提供的预约义 profiles:golang
runtime.SetBlockProfileRate
启用。runtime.SetMutexProfileFraction
启用。我可使用其余哪些 profilers 来介绍Go程序?web
在Linux上,perf tools 可用于分析Go程序。 Perf 能够 profile 和展开 cgo/SWIG 代码和内核,所以深刻了解native/内核性能瓶颈很是有用。 在macOS上, Instruments 套件能够用来 profile Go 程序。编程
我能够 profile 个人生产环境的服务吗?后端
是的。 在生产环境中对程序进行 profile 是安全的,但启用某些 profiles(例如:CPU profile)会增长消耗。 您应该会看到性能降级。 在生产中打开探测器以前,能够经过测量 profiler 的开销来估计性能损失。安全
您可能但愿按期分析您的生产服务。 特别是在具备单进程多副本的系统中,按期选择随机副本是安全的选择。 选择一个生产服务, 每隔Y秒 profile X秒并保存结果以进行可视化和分析; 而后按期重复。 能够 手动/自动 检查结果以发现问题。 profiles 收集可能会相互干扰,所以建议一次只收集一个 profile。
可视化分析数据的最佳方法是什么?
Go tools使用 go tool pprof
提供文本,图形和 callgrind 可视化的 profile data。 阅读 Profiling Go programs 以查看它们的实际使用。
文本方式查看最大的消耗的调用
图片方式可视化最大的消耗的调用
Weblist视图在HTML页面中逐行显示源代码最大消耗的部分。 在如下示例中,530ms用于 runtime.concatstrings
,每行的消耗显示在列表中。
weblist方式可视化最大的消耗的调用
另外一种可视化轮廓数据的方法是火焰图。 火焰图容许您在特定的祖先路径中移动,所以您能够放大/缩小特定的代码段。upstream pprof支持火焰图。
火焰图方式可视化以发现最昂贵的代码路径
我是否仅限于内置profiles?
除了 runtime 提供的工具以外,Go用户还能够经过 pprof.Profile 建立自定义 profiles,并使用现有工具对其进行检查。
我能够在不一样的路径和端口上提供 profiler handlers(/debug/pprof/...) 吗?
是的。 默认状况下, net/http/pprof
包将其 handlers 注册到默认的mux,但您也可使用从包中导出的handler net/http/pprof注册它们。
例如,如下示例将在7777端口/custom_debug_path/profile上提供 pprof.Profile handler:
package main
import (
"log"
"net/http"
"net/http/pprof"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/custom_debug_path/profile", pprof.Profile)
log.Fatal(http.ListenAndServe(":7777", mux))
}
复制代码
Tracing 是一种检测代码的方法,用于分析一系列调用的生命周期中的延迟。 Go提供 golang.org/x/net/trace 包做为每一个Go节点的最小 tracing backend,并提供一个带有简单仪表板的最小检测库。 Go还提供了一个执行跟踪器来跟踪时间间隔内的 runtime events。
Tracing 使咱们可以:
在单机系统中,从程序的构成模块收集诊断数据相对容易。 全部模块都位于一个进程中,并共享公共资源以报告日志,错误和其余诊断信息。一旦您的系统超出单个进程并开始变为分布式,跟踪从前端Web服务器到其全部后端的调用,直到将响应返回给用户,将变得更加困难。这就是分布式 tracing 在检测和分析生产系统方面发挥重要做用的地方。
分布式 tracing 是一种检测代码的方法,用于分析用户请求在整个生命周期中的延迟。 当系统分布式化,而且传统的分析和调试工具没法scale时,您可能但愿使用分布式 tracing 工具来分析用户请求和RPC的性能。
分布式 tracing 使咱们可以:
GO生态系统为每一个跟踪系统提供了不一样的分布式跟踪库和后端无关的跟踪库。
有没有办法自动拦截每一个函数调用并建立 tracing ?
Go没有提供自动拦截每一个函数调用和建立trace spans的方法。 您须要手动检测代码以建立,结束和注释 spans。
我应该如何在Go库中传播 trace headers ?
您能够在 context.Context
传播trace标识符和标记。 目前行业中尚未 trace key 的规范和 trace headers 的通用表示。 每一个tracing提供程序都负责在其Go库中提供传播工具。
标准库或 runtime 中的其余低级事件能够包含在 trace 中吗?
标准库和 runtime 试图公开几个额外的API来通知低级内部事件。 例如, httptrace.ClientTrace
提供API以跟踪传出请求生命周期中的低级事件。 目前正在努力从 runtime execution tracer 中检索低级运行时事件,并容许用户定义和记录其用户事件。
Debugging 是识别程序错误行为的过程。调试器容许咱们理解程序的执行流程和当前状态。有几种调试方式;本节只关注将调试器 attach 到程序和 core dump 调试。
GO用户主要使用如下调试器:
调试器与 Go 程序的兼容性如何?
gc
编译器执行优化,例如函数内联和变量注册。 这些优化有时会使调试器调试更困难。 目前正在努力提升优化后的二进制文件的DWARF 信息的质量。 在这些改进可用以前,咱们建议在构建正在调试的代码时禁用优化。 如下命令构建一个没有编译器优化的包:
$ go build -gcflags=all="-N -l"
复制代码
做为改进工做的一部分,Go 1.10引入了一个新的编译器flag -dwarflocationlists
。 该标志使编译器添加位置列表,以帮助调试器使用优化后的二进制文件。 如下命令构建使用优化但包含 DWARF 位置列表的包:
$ go build -gcflags="-dwarflocationlists=true"
复制代码
推荐的用户界面调试器是什么?
尽管 delve 和 gdb 都提供了 CLI,但大多数集成编辑器和IDE都提供了特定于调试的用户界面。
是否可使用Go程序进行过后调试?
core dump 文件是包含正在运行的进程及其进程状态的 memory dump 文件。 它主要用于程序的过后调试,并了解它仍在程序运行时的状态。 这两种状况使 core dump 的调试成为一种良好的诊断工具,可用于过后分析和分析生产服务。 能够从Go程序获取core文件,并使用delve或gdb进行调试,请参阅 core dump debugging 页面以获取分步指南。
runtime 为用户提供内部事件的统计信息和报告,以便在 runtime 级别诊断性能和利用率问题。
用户能够监控这些统计数据,以更好地了解Go程序的总体运行情况和性能。 一些常常监控的统计数据和状态:
runtime.ReadMemStats
报告与堆分配和垃圾回收相关的metrics。 内存统计信息对于监视进程正在消耗多少内存资源,进程是否能够很好地利用内存以及捕获内存泄漏很是有用。debug.ReadGCStats
读取有关垃圾收集的统计信息。 查看有多少资源用于GC暂停很是有用。 它还报告垃圾收集器暂停和暂停时间百分比的 timeline。debug.Stack
返回当前 stack trace。stack trace 有助于查看当前正在运行的 goroutine 数量,它们正在执行的操做,以及它们是否被阻塞。debug.WriteHeapDump
挂起全部 goroutine 的执行,并容许您将堆 dump 到文件中。 heap dump 是给定时间Go进程的内存快照。 它包含全部已分配的对象以及 goroutine,finalizers 等。runtime.NumGoroutine
返回当前 goroutine 的数量。 能够监视该值以查看是否使用了足够的goroutine,或检测goroutine泄漏。Go附带了一个runtime execution tracer,用于捕获各类运行时事件。 调度,系统调用,垃圾收集,堆大小和其余由 runtime 收集的事件,并可经过 go tool trace 进行可视化。 Execution tracer 是一种检测延迟和利用率问题的工具。 您能够检查CPU的使用状况,以及当网络或系统调用成为goroutines抢占的缘由。
Tracer 使咱们可以:
可是,识别热点(如分析内存过多或CPU使用率的缘由)并非很好用。 首先使用 profiling tools 来解决它们。
以上,go tool trace 可视化显示执行开始正常,而后它变得顺序化。 它代表可能存在共享资源的锁竞争致使的瓶颈。
请参阅 go tool trace
以收集和分析 runtime traces。
若是相应地设置了 GODEBUG 环境变量,Runtime 也会发出事件和信息。
GODEBUG 环境变量可用于禁用标准库和 runtime 中 instruction set extensions 的使用。
extension 是指令集扩展名的小写名称,例如 sse41 或 avx 。