首页 > 解决方案 > 无法从 CPU 分析中获取数据

问题描述

我正在尝试学习使用 Go 的分析功能。考虑到这一点,我创建了这个简单的应用程序:https ://github.com/Matias-Barrios/countWords ,它只是计算给定txt文件的单词出现次数。

问题是,一旦创建了.cpu.prof文件,我什么都看不到。一旦我打开文件,我就会收到此错误:

(0) matias #> go tool pprof .cpu.prof 
File: main
Type: cpu
Time: Oct 9, 2019 at 12:38am (-03)
Duration: 201.31ms, Total samples = 0 
No samples were found with the default sample value type.
Try "sample_index" command to analyze different sample values.
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 0, 0% of 0 total
      flat  flat%   sum%        cum   cum%
(pprof) 

我在这里做错了什么?

注意:我的 Go 版本是go 版本 go1.13.1 linux/amd64

标签: goprofiling

解决方案


对我来说,问题是我的代码执行得太快了。我所做的是使用runtime.SetCPUProfileRate更改采样率。请注意,在runtime.pprof.StartCPUProfile中,采样率为 100 Hz,建议为 500 Hz。

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

    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
}

但在我的情况下,将其设置为 500 Hz 还不够快。查看runtime.SetCPUProfileRate的代码后,您似乎可以提供高达 100000 Hz 的频率。将其设置为足够大的值后,它解决了我的问题。

// SetCPUProfileRate sets the CPU profiling rate to hz samples per second.
// If hz <= 0, SetCPUProfileRate turns off profiling.
// If the profiler is on, the rate cannot be changed without first turning it off.
//
// Most clients should use the runtime/pprof package or
// the testing package's -test.cpuprofile flag instead of calling
// SetCPUProfileRate directly.

func SetCPUProfileRate(hz int) {

    // Clamp hz to something reasonable.
    if hz < 0 {
        hz = 0
    }
    if hz > 1000000 {
        hz = 1000000
    }

    lock(&cpuprof.lock)
    if hz > 0 {
        if cpuprof.on || cpuprof.log != nil {
            print("runtime: cannot set cpu profile rate until previous profile has finished.\n")
            unlock(&cpuprof.lock)
            return
        }

        cpuprof.on = true
        cpuprof.log = newProfBuf(1, 1<<17, 1<<14)
        hdr := [1]uint64{uint64(hz)}
        cpuprof.log.write(nil, nanotime(), hdr[:], nil)
        setcpuprofilerate(int32(hz))
    } else if cpuprof.on {
        setcpuprofilerate(0)
        cpuprof.on = false
        cpuprof.addExtra()
        cpuprof.log.close()
    }
    unlock(&cpuprof.lock)
}

推荐阅读