简体   繁体   English

无法让 golang pprof 工作

[英]Can't get golang pprof working

I have tried to profile some golang applications but I couldn't have that working, I have followed these two tutorials:我曾尝试分析一些 golang 应用程序,但无法正常工作,我遵循了以下两个教程:

Both says that after adding some code lines to the application, you have to execute your app, I did that and I receiveed the following message in the screen:两者都说在向应用程序添加一些代码行后,您必须执行您的应用程序,我这样做了,我在屏幕上收到以下消息:

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

So, I understand that the profiling is being executed, sending info to the file.所以,我知道正在执行分析,将信息发送到文件。

But, when I see the file size, in any program that I test, it is always 64bytes.但是,当我看到文件大小时,在我测试的任何程序中,它总是 64 字节。

When I try to open the cpu.pprof file with pprof, and I execute the "top10" command, I see that nothing is in the file:当我尝试使用 pprof 打开 cpu.pprof 文件并执行“top10”命令时,我看到文件中没有任何内容:

("./fact" is my app) (“./fact”是我的应用程序)

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

top10 -->前十名 -->

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

So, it is like nothing is happening when I am profiling.所以,当我进行分析时,就像什么都没有发生。

I have tested it in mac (this example) and in ubuntu, with three different programs.我已经在 mac(本例)和 ubuntu 中使用三个不同的程序对其进行了测试。

Do you know that I am doing wrong?你知道我做错了吗?

Then example program is very simple, this is the code (is a very simple factorial program that I take from internet):然后示例程序非常简单,这是代码(是我从互联网上获取的一个非常简单的阶乘程序):

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))
}

Thanks, Fer谢谢,费尔

As inf mentioned already, your code executes too fast.正如 inf 已经提到的,您的代码执行得太快了。 The reason is that pprof works by repeatedly halting your program during its execution, looking at which function is running at that moment in time and writing that down (together with the whole function call stack).原因是 pprof 的工作原理是在程序执行期间反复停止程序,查看当时正在运行的函数并将其写下来(连同整个函数调用堆栈)。 Pprof samples with a rate of 100 samples per second. Pprof 以每秒 100 个样本的速率进行采样。 This is hardcoded in runtime/pprof/pprof.go as you can easily check (see https://golang.org/src/runtime/pprof/pprof.go line 575 and the comment above it):这是在 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

} }

The longer your program runs the more samples can be made and the more probable it will become that also short running functions will be sampled.您的程序运行的时间越长,可以制作的样本越多,并且对短期运行的函数也进行采样的可能性就越大。 If your program finishes before even the first sample is made, than the generated cpu.pprof will be empty.如果您的程序甚至在第一个样本制作完成之前就完成了,那么生成的 cpu.pprof 将是空的。

As you can see from the code above, the sampling rate is set with从上面的代码可以看出,采样率设置为

runtime.SetCPUProfileRate(..)

If you call runtime.SetCPUProfileRate() with another value before you call StartCPUProfile(), you can override the sampling rate.如果在调用 StartCPUProfile()之前使用另一个值调用 runtime.SetCPUProfileRate(),则可以覆盖采样率。 You will receive a warning message during execution of your program telling you "runtime: cannot set cpu profile rate until previous profile has finished."您将在程序执行期间收到一条警告消息,告诉您“运行时:在前一个配置文件完成之前无法设置 cpu 配置文件速率”。 which you can ignore.你可以忽略它。 It results since pprof.go calls SetCPUProfileRate() again.这是因为 pprof.go 再次调用 SetCPUProfileRate()。 Since you have already set the value, the one from pprof will be ignored.由于您已经设置了该值,因此 pprof 中的值将被忽略。

Also, Dave Cheney has released a new version of his profiling tool, you can find it here: https://github.com/pkg/profile .此外,Dave Cheney 发布了他的分析工具的新版本,你可以在这里找到它: https ://github.com/pkg/profile。 There, you can, among other changes, specify the path where the cpu.pprof is written to:在那里,除了其他更改之外,您还可以指定写入 cpu.pprof 的路径:

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

You can read about it here: http://dave.cheney.net/2014/10/22/simple-profiling-package-moved-updated你可以在这里阅读:http: //dave.cheney.net/2014/10/22/simple-profiling-package-moved-updated

By the way, your fact() function will quickly overflow, even if you take int64 as parameter and return value.顺便说一句,即使您将 int64 作为参数并返回值,您的 fact() 函数也会很快溢出。 30! 30! is roughly 2*10^32 and an int64 stores values only up to 2^63-1 which is roughly 9*10^18.大约是 2*10^32,而 int64 只存储高达 2^63-1 的值,大约是 9*10^18。

The problem is that your function is running too fast and pprof can't sample it.问题是您的函数运行速度太快,pprof 无法对其进行采样。 Try adding a loop around the fact call and sum the result to artificially prolong the program.尝试在fact调用周围添加一个循环并对结果求和以人为地延长程序。

I struggled with empty pprof files, until I realized that I followed outdated blog articles.我一直在处理空的 pprof 文件,直到我意识到我关注的是过时的博客文章。

The upstream docs are good: https://pkg.go.dev/runtime/pprof上游文档很好: https ://pkg.go.dev/runtime/pprof

Write a test which you want to profile, then:编写一个要分析的测试,然后:

go test -cpuprofile cpu.prof -memprofile mem.prof -bench .

this creates cpu.prof and mem.prof.这将创建 cpu.prof 和 mem.prof。

You can analyze them like this:你可以像这样分析它们:

go tool pprof cpu.prof

This gives you a command-line.这为您提供了一个命令行。 The "top" and "web" commands are used often. “top”和“web”命令经常被使用。

Same for memory:内存也一样:

go tool pprof mem.prof

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM