我曾尝试剖析某些golang应用程序,但无法正常工作,我遵循了以下两个教程:

  • http://blog.golang.org/profiling-go-programs
  • http://saml.rilspace.org/profiling-and-creating-call-graphs-for-go-programs-with-go-tool-pprof

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



    因此,我了解到正在执行概要分析,并将信息发送到文件。

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

    当我尝试使用pprof打开cpu.pprof文件并执行“top10”命令时,我发现该文件中没有任何内容:

    (“./fact”是我的应用)



    因此,当我进行概要分析时,就像什么也没有发生。

    我已经在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))
    }
    

    谢谢,
    费尔

    最佳答案

    如前所述,您的代码执行速度太快。原因是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(..)
    

    如果您在之前调用runtime.SetCPUProfileRate()并使用另一个值来调用StartCPUProfile(),则可以覆盖采样率。在程序执行期间,您将收到一条警告消息,告诉您“运行时:在之前的配置文件完成之前,无法设置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。

    关于go - 无法使golang pprof工作,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30871691/

    10-09 05:56