诊断程序

介绍

Go生态系统提供了一整套用于诊断Go程序中的逻辑和性能问题的API和工具. 该页面总结了可用的工具,并帮助Go用户针对他们的特定问题选择合适的工具.

诊断解决方案可以分为以下几类:

注意:某些诊断工具可能会相互干扰. 例如,精确的内存分析会歪曲CPU配置文件,goroutine阻止分析会影响调度程序跟踪. 孤立地使用工具以获得更精确的信息.

剖析

分析对于识别昂贵或经常调用的代码段很有用. Go运行时以pprof可视化工具所需的格式提供概要分析数据 . 可以在测试过程中通过go testnet / http / pprof程序包中提供的端点收集性能分析数据. 用户需要收集性能分析数据并使用pprof工具来过滤和可视化顶部代码路径.

runtime / pprof软件包提供的预定义配置文件:

我还可以使用哪些其他分析器来分析Go程序?

在Linux上,可以使用perf工具来分析Go程序. Perf可以分析和解散cgo / SWIG代码和内核,因此深入了解本机/内核性能瓶颈可能很有用. 在macOS上, Instruments套件可用于profile Go程序.

我可以介绍我的生产服务吗?

是. 在生产环境中对程序进行概要分析是安全的,但是启用某些概要文件(例​​如CPU概要文件)会增加成本. 您应该期望看到性能下降. 可以通过在生产之前打开Profiler来测量Profiler的开销来估算性能损失.

您可能需要定期分析生产服务. 特别是在具有单个进程多个副本的系统中,定期选择随机副本是一个安全的选择. 选择一个生产过程,每隔Y秒将其概要分析X秒,并保存结果以进行可视化和分析; 然后定期重复. 可以手动和/或自动查看结果以发现问题. 配置文件的收集可能会相互干扰,因此建议一次仅收集一个配置文件.

可视化分析数据的最佳方法是什么?

Go工具使用go tool pprof配置文件数据的文本,图形和callgrind可视化. 阅读Profiling Go程序以查看它们的运行情况.


以文字形式列出最昂贵的通话.


将最昂贵的呼叫可视化为图表.

Weblist视图在HTML页面中逐行显示源的昂贵部分. 在以下示例中,530ms花费在runtime.concatstrings和每行的成本在列表中呈现.


将最昂贵的呼叫可视化为网络列表.

可视化轮廓数据的另一种方法是火焰图 . 火焰图使您可以在特定的祖先路径中移动,因此可以放大/缩小代码的特定部分. 上游pprof支持火焰图.


火焰图提供可视化功能,以找出最昂贵的代码路径.

我是否限于内置配置文件?

除了运行时提供的功能外,Go用户还可以通过pprof.Profile创建其自定义配置文件,并使用现有工具进行检查.

我可以在其他路径和端口上提供事件探查器处理程序(/ debug / pprof / ...)吗?

是. net/http/pprof软件包默认情况下将其处理程序注册到默认的多路复用器,但是您也可以使用从软件包中导出的处理程序自己注册它们.

例如,以下示例将在/ custom_debug_path / profile上的:7777上提供pprof.Profile处理程序:

  包主

 导入(
	 "日志"
	 " net / http"
	 " net / http / pprof"
 )

 func main(){
	 多路复用器:= http.NewServeMux()
	 mux.HandleFunc(" / custom_debug_path / profile",pprof.Profile)
	 log.Fatal(http.ListenAndServe(":7777",mux))
 }

追踪

跟踪是一种工具代码,可以分析整个调用链的整个生命周期中的延迟. Go提供golang.org/x/net/trace软件包作为每个Go节点的最小跟踪后端,并提供带有简单仪表板的最小检测库. Go还提供了一个执行跟踪器,以跟踪一个间隔内的运行时事件.

跟踪使我们能够:

在单片系统中,从程序的构建块中收集诊断数据相对容易. 所有模块都生活在一个过程中,并共享公共资源来报告日志,错误和其他诊断信息. 一旦您的系统超出了单个进程并开始分布,就很难跟踪从前端Web服务器到其所有后端的调用,直到将响应返回给用户为止. 在这里,分布式跟踪对仪器和分析生产系统起着重要作用.

分布式跟踪是一种工具代码,可以分析用户请求整个生命周期中的延迟. 当系统是分布式的并且常规的性能分析和调试工具无法扩展时,您可能希望使用分布式跟踪工具来分析用户请求和RPC的性能.

分布式跟踪使我们能够:

Go生态系统为每个跟踪系统和与后端无关的数据库提供了各种分布式跟踪库.

有没有一种方法可以自动拦截每个函数调用并创建跟踪?

Go没有提供一种自动拦截每个函数调用并创建跟踪范围的方法. 您需要手动检测代码以创建,结束和注释跨度.

我应该如何在Go库中传播跟踪头?

您可以在context.Context传播跟踪标识符和标记. 业界尚无规范的跟踪键或跟踪头的通用表示形式. 每个跟踪提供者都有责任在其Go库中提供传播实用程序.

标准库或运行时中还有哪些其他低级事件可以包含在跟踪中?

标准库和运行时正尝试公开一些其他API,以在发生低级内部事件时进行通知. 例如, httptrace.ClientTrace提供API以在传出请求的生命周期中跟踪低级事件. 正在进行中的工作是从运行时执行跟踪器中检索低级运行时事件,并允许用户定义和记录其用户事件.

调试

调试是确定程序行为异常的过程. 调试器使我们能够了解程序的执行流程和当前状态. 调试有几种样式. 本节仅关注将调试器附加到程序和核心转储调试.

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程序进行事后调试吗?

核心转储文件是一个文件,其中包含正在运行的进程的内存转储及其进程状态. 它主要用于程序的事后调试,并在程序仍在运行时了解其状态. 这两种情况使核心转储的调试成为进行事后分析和分析生产服务的良好诊断工具. 可以从Go程序中获取核心文件,并使用delve或gdb进行调试,有关逐步指南,请参见核心转储调试页面.

运行时统计信息和事件

运行时为用户提供内部事件的统计信息和报告,以在运行时级别诊断性能和利用率问题.

用户可以监视这些统计信息,以更好地了解Go程序的整体运行状况和性能. 一些经常监视的统计信息和状态:

执行追踪器

Go附带了一个运行时执行跟踪程序,以捕获各种运行时事件. 调度,系统调用,垃圾回收,堆大小和其他事件由运行时收集,并且可以通过go工具跟踪进行可视化. 执行跟踪器是检测延迟和利用率问题的工具. 您可以检查CPU的利用率,以及何时网络连接或系统调用会导致goroutine抢占.

跟踪器可用于:

但是,这对于识别热点(例如分析过多的内存或CPU使用率的原因)不是很好. 而是首先使用分析工具来解决它们.

上面的go工具跟踪可视化显示执行开始良好,然后序列化了. 它表明可能存在导致瓶颈的共享资源的锁争用.

请参阅go tool trace以收集和分析运行时跟踪.

哥德宝

如果相应地设置了GODEBUG环境变量,则运行时还会发出事件和信息.

GODEBUG环境变量可用于在标准库和运行时中禁用指令集扩展.

by  ICOPY.SITE