Go生态系统提供了一整套用于诊断Go程序中的逻辑和性能问题的API和工具。该篇文章总结了可用的工具,并帮助Go用户针对他们的特定问题选择合适的工具。html
诊断解决方案能够分为如下几类:前端
注意:某些诊断工具可能会相互干扰。例如,内存分析会影响CPU profiles,goroutine 阻塞分析会影响调度程序跟踪。一次只使用一种工具以得到更精确的信息。git
分析对于识别消耗资源严重或常常调用的代码段颇有用。 Go运行时以pprof可视化工具所需的格式提供概要分析数据。能够在测试过程当中经过go test或 net/http/pprof 程序包中提供的端点收集性能分析数据。用户须要收集性能分析数据并使用pprof工具来过滤和可视化代码路径。github
runtime/pprof 软件包提供的预约义profiles:golang
我还可使用哪些其余分析器来分析Go程序?web
在Linux上,可使用perf工具来分析Go程序。 Perf能够分析和解散cgo /SWIG代码和内核,所以深刻了解本机/内核性能瓶颈可能颇有用。在macOS上,Instruments套件可用于profile Go程序。数据库
我能够profile个人生产服务吗?编程
是。在生产环境中对程序进行概要分析是安全的,可是启用某些概要文件(例如CPU概要文件)会增长成本。您应该指望看到性能降低。能够经过在生产以前打开Profiler来测量Profiler的开销来估算性能损失。后端
您可能须要按期分析生产服务。特别是在具备单个进程多个副本的系统中,按期选择随机副本是一个安全的选择。选择一个生产过程,每隔Y秒将其概要分析X秒,并保存结果以进行可视化和分析;而后按期重复。能够手动或自动查看结果以发现问题。profile的收集可能会相互干扰,所以建议一次仅收集一个profile。安全
可视化分析数据的最佳方法是什么?
Go工具使用go tool pprof提供profile数据的文本,图形和callgrind可视化。阅读Profiling Go程序以查看它们的运行状况。
以文本形式列出最消耗资源的调用
将最消耗资源的调用可视化为图表
Weblist视图在HTML页面中逐行显示源代码最消耗资源的部分。在下面的示例中,运行时花费了530毫秒。runtime.concatstrings和清单中列出了每行的成本。
将最消耗资源的调用可视化为weblist
可视化轮廓数据的另外一种方法是火焰图。火焰图使您能够在特定的祖先路径中移动,所以能够放大/缩小代码的特定部分。上游pprof支持火焰图。
我是否限于内置profiles?
除了运行时提供的功能外,Go用户还能够经过pprof.Profile建立其自定义profile,并使用现有工具进行检查。
我能够在其余路径和端口上提供事件探查器处理程序(/debug/pprof/ ...)吗?
是。 net/http/pprof软件包默认状况下将其处理程序注册到默认的多路复用器,可是您也可使用从软件包中导出的处理程序本身注册它们。
例如,如下示例将在 /custom_debug_path/profile上的:7777上提供pprof.Profile处理程序:
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)) }
跟踪是一种工具代码,能够分析整个调用链的整个生命周期中的延迟。 Go提供golang.org/x/net/trace软件包做为每一个Go节点的最小跟踪后端,并提供带有简单仪表板的最小检测库。 Go还提供了一个执行跟踪器,以跟踪一个间隔内的运行时事件。
Tracing 能够在如下方面帮助到咱们:
在单片系统中,从程序的构建块中收集诊断数据相对容易。全部模块都生活在一个过程当中,并共享公共资源来报告日志,错误和其余诊断信息。一旦您的系统超出了单个进程并开始分布,就很难跟踪从前端Web服务器到其全部后端的调用,直到将响应返回给用户为止。在这里,分布式跟踪对仪器和分析生产系统起着重要做用。
分布式跟踪是一种工具代码,能够分析用户请求整个生命周期中的延迟。当系统是分布式的而且常规的性能分析和调试工具没法扩展时,您可能但愿使用分布式跟踪工具来分析用户请求和RPC的性能。
分布式跟踪在如下几个方面能够帮助到咱们:
Go生态系统为每一个跟踪系统和与后端无关的数据库提供了各类分布式跟踪库。
有没有一种方法能够自动拦截每一个函数调用并建立跟踪?
Go没法提供一种自动拦截每一个函数调用并建立跟踪范围的方法。您须要手动检测代码以建立,结束和注释跨度。
我应该如何在Go库中传播跟踪头?
您能够在context.Context中传播跟踪标识符和标记。业界尚无规范的跟踪键或跟踪头的通用表示形式。每一个跟踪提供者都有责任在其Go库中提供传播实用程序。
标准库或运行时中还有哪些其余低级事件能够包含在跟踪中?
标准库和运行时正尝试公开一些其余API,以在发生低级内部事件时进行通知。例如,httptrace.ClientTrace提供API以在传出请求的生命周期中跟踪低级事件。正在进行中的工做是从运行时执行跟踪器中检索低级运行时事件,并容许用户定义和记录其用户事件。
调试是肯定程序行为异常的过程。调试器使咱们可以了解程序的执行流程和当前状态。调试有几种样式。本节仅关注将调试器附加到程序和core dump调试。
Go用户一般使用如下调试器:
调试器与Go程序的配合状况如何?
gc编译器执行优化,例如函数内联和变量注册。这些优化有时会使调试器的调试更加困难。正在进行不断的努力来改善为优化的二进制文件生成的DWARF信息的质量。在这些改进可用以前,咱们建议在构建要调试的代码时禁用优化。如下命令生成没有编译器优化的软件包:
$ go build -gcflags=all="-N -l"
做为改进工做的一部分,Go 1.10引入了新的编译器标志-dwarflocationlists。该标志使编译器添加位置列表,以帮助调试器使用优化的二进制文件。如下命令使用DWARF位置列表构建具备优化的软件包:
$ go build -gcflags="-dwarflocationlists=true"
推荐的调试器用户界面是什么?
尽管delve和gdb都提供了CLI,可是大多数编辑器集成和IDE都提供了特定于调试的用户界面。
可使用Go程序进行过后调试吗?
core dump文件是一个文件,其中包含正在运行的进程的内存dump及其进程状态。它主要用于程序的过后调试,并在程序仍在运行时了解其状态。这两种状况使core dump的调试成为进行过后分析和分析生产服务的良好诊断工具。能够从Go程序中获取core文件,并使用delve或gdb进行调试,有关逐步指南,请参见core dump调试页面。
运行时为用户提供内部事件的统计信息和报告,以在运行时级别诊断性能和利用率问题。
用户能够监视这些统计信息,以更好地了解Go程序的总体运行情况和性能。一些常常监视的统计信息和状态:
Go附带了一个运行时执行跟踪程序,以捕获各类运行时事件。调度,系统调用,垃圾回收,堆大小和其余事件由运行时收集,而且能够经过go工具跟踪进行可视化。执行跟踪器是检测延迟和利用率问题的工具。您能够检查CPU的利用率,以及什么时候网络链接或系统调用会致使goroutine抢占。
跟踪器在一下几个方面能够帮助到您:
可是,这对于识别热点(例如分析过多的内存或CPU使用率的缘由)不是很好。而是首先使用分析工具来解决它们。
上面的go工具跟踪可视化显示执行开始良好,而后序列化了。它代表可能存在致使瓶颈的共享资源的锁争用。
请参阅go tool trace以收集和分析运行时跟踪。
若是相应地设置了GODEBUG环境变量,则运行时还会发出事件和信息。
GODEBUG环境变量可用于在标准库和运行时中禁用指令集扩展。