5

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

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

2015/06/16 12:04:00 配置文件:启用 cpu 分析,/var/folders/kg/4fxym1sn0bx02zl_2sdbmrhr9wjvqt/T/profile680799962/cpu.pprof

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

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

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

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

去工具 pprof ./fact /var/folders/kg/4fxym1sn0bx02zl_2sdbmrhr9wjvqt/T/profile680799962/cpu.pprof

前十名 -->

(pprof) top10 0 of 0 total (0%) flat flat% sum% cum cum%

所以,当我进行分析时,就像什么都没有发生。

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

谢谢,费尔

4

2 回答 2

10

正如 inf 已经提到的,您的代码执行得太快了。原因是 pprof 的工作原理是在程序执行期间反复暂停程序,查看当时正在运行的函数并将其写下来(连同整个函数调用堆栈)。Pprof 以每秒 100 个样本的速率进行采样。这是在 runtime/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。

于 2015-07-12T10:38:15.577 回答
4

问题是您的函数运行速度太快,pprof 无法对其进行采样。尝试在调用周围添加一个循环fact并对结果求和以人为地延长程序。

于 2015-06-16T15:52:56.097 回答