Go: 使用pprof收集样本数据

ℹ️ 本文基于 Go 1.13。

pprof是用于分析性能数据(例如CPU或内存分配)的工具。 对应用程序进行性能分析需要在运行时收集数据,以便稍后聚合它们并生成图形。 现在,让我们深入研究此数据收集的工作流程,并了解如何对其进行调整。

工作流

pprof以固定的时间间隔收集分析数据,该间隔由每秒的收集次数定义。 默认参数是100,这意味着pprof每秒将收集一百次数据,即每10毫秒一次。

可以通过调用StartCPUProfile来启动pprof:

func main() {
   f, _ := os.Create(`cpu.prof`)
   if err != nil {
      log.Fatal(err)
   }
   pprof.StartCPUProfile(f)
   defer pprof.StopCPUProfile()

   ...
}

此过程将在正在运行的线程上自动设置一个定时器(下图中的M表示),该定时器允许Go定期收集分析数据。 这是第一个图:

有关P,M,G表示形式的更多信息,建议您阅读之前的文章  “Go: Goroutine, 系统线程和CPU管理

pprof仅分析当前正在运行的线程。 当Go调度器调度goroutine在某线程上运行时,将实时跟踪该线程。 这是更新的图:

关于Go调度器的更多信息,我建议您阅读之前的文章“Go: g0, 特殊的goroutine

然后,分析数据将按每个定义的时间间隔定期转储到缓冲区:

数据实际上是由gsignal转储的,gsignal是一个处理传入信号的goroutine。实际上,定时器在每个时间间隔发出信号。

关于信号和gsignal的更多信息,我建议您阅读之前的文章“Go:gsignal,信号大师

基于信号

在每个线程上创建的定时器是由setitimer方法和时间间隔定时器ITIMER_PROF管理的。时间计数仅在进程运行时才会减少,这样就能确保分析数据的准确。

一旦达到时间间隔,定时器就会发出一个SIGPROF信号,该信号将被Go截获,并将分析数据转储到缓冲区。可以通过从运行时包中调用函数SetCPUProfileRate来配置分析频率。必须在启动分析器之前执行以下操作:

func main() {
   f, err := os.Create(`cpu.prof`)
   if err != nil {
      log.Fatal(err)
   }

   runtime.SetCPUProfileRate(10)
   pprof.StartCPUProfile(f)
   defer pprof.StopCPUProfile()

   ...
}

配置分析频率只能定义一次,pprof在启动分析器时定义它。在启动分析器之前调用该方法将导致pprof忽略默认值。但是,在大多数情况下,默认值应该足够了。这个选择在软件包中有很好的解释:

100赫兹是一个合理的选择:可以产生足够多有用的数据,足够少影响系统稳定。

数据收集

定时器现在都设置好了。一旦缓冲,pprof需要一种方法来收集所有数据来创建报告。这个过程由一个单独的goroutine完成,该goroutine每隔100毫秒收集并格式化数据。

生成完成后,即分析停止后,专用goroutine会将报告转储到文件中,使其可用并完成可视化。

编译自:https://medium.com/a-journey-with-go/go-samples-collection-with-pprof-2a63c3e8a142

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据