无法让golang pprof工作

时间:2015-06-16 15:18:17

标签: go profiling pprof

我试图介绍一些golang应用程序但我无法正常工作,我已经按照这两个教程进行了编写:

两者都说在向应用程序添加一些代码行后,你必须执行你的应用程序,我这样做了,我在屏幕上收到了以下消息:

  

2015/06/16 12:04:00 profile:启用cpu profiling,   /var/folders/kg/4fxym1sn0bx02zl_2sdbmrhr9wjvqt/T/profile680799962/cpu.pprof

所以,我知道正在执行分析,将信息发送到文件。

但是,当我看到文件大小时,在我测试的任何程序中,它总是64字节。

当我尝试用pprof打开cpu.pprof文件时,我执行" top10"命令,我看到文件中没有任何内容:

(" ./ fact"是我的应用程序)

  

go tool pprof ./fact   /var/folders/kg/4fxym1sn0bx02zl_2sdbmrhr9wjvqt/T/profile680799962/cpu.pprof

     

top10 - >

     

(pprof)top10 0 of 0 total(0%)         持平均价%和暨%

所以,当我进行剖析时,就好像什么都没发生一样。

我已经在mac(本例)和ubuntu中测试了它,有三个不同的程序。

你知道我做错了吗?

然后示例程序非常简单,这是代码(是一个非常简单的因子程序,我从互联网上获取):

import "fmt"
import "github.com/davecheney/profile"

func fact(n int) int {
      if n == 0 {
        return 1
      }
      return n * fact(n-1)
}

func main() {
      defer profile.Start(profile.CPUProfile).Stop()
      fmt.Println(fact(30))
}

谢谢, FER

2 个答案:

答案 0 :(得分:7)

如前所述,您的代码执行速度太快。原因是pprof通过在执行期间反复暂停程序来工作,查看当时正在运行的函数并将其写入(与整个函数调用堆栈一起)。 Pprof样品的速率为每秒100个样品。这在运行时/ pprof / pprof.go中是硬编码的,因为您可以轻松检查(参见https://golang.org/src/runtime/pprof/pprof.go第575行及其上面的注释):

func StartCPUProfile(w io.Writer) error {
// The runtime routines allow a variable profiling rate,
// but in practice operating systems cannot trigger signals
// at more than about 500 Hz, and our processing of the
// signal is not cheap (mostly getting the stack trace).
// 100 Hz is a reasonable choice: it is frequent enough to
// produce useful data, rare enough not to bog down the
// system, and a nice round number to make it easy to
// convert sample counts to seconds.  Instead of requiring
// each client to specify the frequency, we hard code it.
const hz = 100

// Avoid queueing behind StopCPUProfile.
// Could use TryLock instead if we had it.
if cpu.profiling {
    return fmt.Errorf("cpu profiling already in use")
}

cpu.Lock()
defer cpu.Unlock()
if cpu.done == nil {
    cpu.done = make(chan bool)
}
// Double-check.
if cpu.profiling {
    return fmt.Errorf("cpu profiling already in use")
}
cpu.profiling = true
runtime.SetCPUProfileRate(hz)
go profileWriter(w)
return nil

}

程序运行的时间越长,可以制作的样本越多,可能性越小,也会对短运行函数进行采样。如果您的程序在完成第一个样本之前完成,那么生成的cpu.pprof将为空。

从上面的代码中可以看出,采样率设置为

runtime.SetCPUProfileRate(..)

如果在调用StartCPUProfile()之前使用之前的另一个值调用runtime.SetCPUProfileRate(),则可以覆盖采样率。在执行程序期间,您将收到一条警告消息,告诉您"运行时:在上一个配置文件完成之前无法设置cpu配置文件速率。"你可以忽略。结果是因为pprof.go再次调用SetCPUProfileRate()。由于您已经设置了值,因此将忽略pprof中的值。

另外,Dave Cheney发布了他的分析工具的新版本,你可以在这里找到它:https://github.com/pkg/profile。除此之外,您还可以指定写入cpu.pprof的路径:

defer profile.Start(profile.CPUProfile, profile.ProfilePath(".")).Stop()

您可以在此处阅读:http://dave.cheney.net/2014/10/22/simple-profiling-package-moved-updated

顺便说一下,即使你把int64作为参数并返回值,你的fact()函数也会快速溢出。 30!大约是2 * 10 ^ 32,int64存储的值最多只有2 ^ 63-1,大约是9 * 10 ^ 18。

答案 1 :(得分:4)

问题是你的功能运行得太快而且pprof无法对其进行采样。尝试在fact调用周围添加一个循环,并将结果汇​​总以人为地延长程序。