我曾尝试剖析某些golang应用程序,但无法正常工作,我遵循了以下两个教程:
两者都说,在向应用程序添加一些代码行之后,您必须执行您的应用程序,我做到了,并且在屏幕上收到以下消息:
因此,我了解到正在执行概要分析,并将信息发送到文件。
但是,当我看到文件大小时,在我测试的任何程序中,该大小始终为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/