去分析配置文件是空的

时间:2017-02-17 13:12:40

标签: memory go

我在关于Go分析的this tutorial之后,按照建议行事:

flag.Parse()
if *cpuprofile != "" {
    f, err := os.Create(*cpuprofile)
    if err != nil {
        log.Fatal(err)
    }
    pprof.StartCPUProfile(f)
    defer pprof.StopCPUProfile()
}

然后我用标志-cpuprofile=myprogram.prof启动了我的代码并创建了文件。然后我用

开始了pprof tool
go tool pprof myprogram myprogram.prof

好吧,myprogram读取一个大的json文件并将其映射到一个大的map [string]字符串,所以我的程序中有很多内容,但是当我喜欢top10时{ {1}},我明白了:

pprof

6 个答案:

答案 0 :(得分:0)

很可能你的代码执行得太快了,即使你认为它做得很多。好几次发生在我身上。

您可以通过runtime.SetCPUProfileRate更改采样率。 -  将其设置为默认值100以上的值,单位为Hz。请注意,Go作者不建议高于500的值 - see explanation

pprof.StartCPUProfile之前完成。您还会看到警告runtime: cannot set cpu profile rate until previous profile has finished - 请参阅this answer以获取解释。

HTH

答案 1 :(得分:0)

您是否处理了ctrl-c信号? 如果还没有,程序将被OS停止。您必须确保程序正常退出,然后配置文件才会写入文件。 您还可以检查netprof模块。

答案 2 :(得分:0)

对于配置go程序,您可以将pprof用作Web服务器。您需要在go程序/应用程序的主文件中添加一些代码以启动pprof服务器,该服务器将不断在服务器上为您的程序提供资源使用详细信息,并且您可以轻松获取所有相关详细信息。如果您遵循下面的代码,则可以在浏览器上的 http://localhost:6060/debug/pprof/ 上查看程序的详细信息。 (需要刷新页面以查看更新的数据)

您可能会在下面看到代码片段,或转到以下链接以获取完整的代码: github.com/arbaaz-khan/GoLangLearning/blob/master/ProfilingGoProgram/profile_go_prog.go

go func() {
    log.Printf("Starting Server! \t Go to http://localhost:6060/debug/pprof/\n")
    err := http.ListenAndServe("localhost:6060", nil)
    if err != nil {
        log.Printf("Failed to start the server! Error: %v", err)
        wg.Done()
    }
}()

希望有帮助!

答案 3 :(得分:0)

如果使用ctrl-c停止程序,请确保在profile.Start()中传入profile.NoShutdownHook参数。

答案 4 :(得分:0)

很可能您没有处理系统中断信号。您应该显式处理它,以便“ pprof.StopCPUProfile()”成功写入配置文件数据,否则,当使用“ ctrl + c”退出时,程序将快速退出。 这是一个示例解决方案:

var f *os.File

func main() {
    flag.Parse()
    if *cpuProfile != "" {
        cpuProfileFile, err := os.Create(*cpuProfile)
        if err != nil {
            log.Fatal(err)
        }
       defer f.Close()
       pprof.StartCPUProfile(cpuProfileFile)
    }

    c := make(chan os.Signal, 2)                    
    signal.Notify(c, os.Interrupt, syscall.SIGTERM) // subscribe to system signals
    onKill := func(c chan os.Signal) {
        select {
        case <-c: 
            defer f.Close()
            defer pprof.StopCPUProfile()
            defer os.Exit(0)
        }

    // try to handle os interrupt(signal terminated)
    go onKill(c)
}

答案 5 :(得分:0)

对我来说,问题在于我的代码执行得太快。我所做的是使用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的代码后,似乎可以提供高达1000000 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)
}