2 回答

TA貢獻(xiàn)1810條經(jīng)驗 獲得超4個贊
對我來說,問題是我的代碼執(zhí)行得太快。我所做的是使用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
}
但就我而言,將其設(shè)置為 500 Hz 還不夠快。查看runtime.SetCPUProfileRate的代碼后,您似乎可以提供高達(dá)100000 Hz的頻率。將其設(shè)置為足夠大的值后,它解決了我的問題。
// 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)
}

TA貢獻(xiàn)1878條經(jīng)驗 獲得超4個贊
Go 編程語言規(guī)范
推遲陳述
“defer”語句調(diào)用一個函數(shù),該函數(shù)的執(zhí)行被推遲到周圍函數(shù)返回的那一刻,要么是因為周圍函數(shù)執(zhí)行了 return 語句,到達(dá)了其函數(shù)體的末尾,要么是因為相應(yīng)的 goroutine 正在恐慌。
修復(fù)CPU文件過早關(guān)閉的問題:
func CPUprofiling() {
? ? fd, err := os.Create(".cpu.prof")
? ? if err != nil {
? ? ? ? log.Fatalln(err.Error())
? ? }
? ? defer fd.Close()
? ? pprof.StartCPUProfile(fd)
? ? defer pprof.StopCPUProfile()
}
例如,
package main
import (
? ? "bufio"
? ? "flag"
? ? "fmt"
? ? "log"
? ? "os"
? ? "runtime/pprof"
? ? "strings"
)
var filename string
func main() {
? ? cpu, err := os.Create(".cpu.prof")
? ? if err != nil {
? ? ? ? log.Fatalln(err.Error())
? ? }
? ? defer cpu.Close()
? ? pprof.StartCPUProfile(cpu)
? ? defer pprof.StopCPUProfile()
? ? flag.StringVar(&filename, "f", "", "Path to the input file")
? ? flag.Parse()
? ? if filename == "" {
? ? ? ? flag.Usage()
? ? ? ? log.Fatalln()
? ? }
? ? for w, c := range getResults(filename) {
? ? ? ? fmt.Printf("%-20s\t%d\n", w, c)
? ? }
? ? mem, err := os.Create(".mem.prof")
? ? if err != nil {
? ? ? ? log.Fatalln(err.Error())
? ? }
? ? defer mem.Close()
? ? pprof.WriteHeapProfile(mem)
}
func getResults(path string) map[string]int {
? ? results := make(map[string]int)
? ? file, err := os.Open(filename)
? ? defer file.Close()
? ? if err != nil {
? ? ? ? log.Fatalln(err.Error())
? ? }
? ? scanner := bufio.NewScanner(file)
? ? scanner.Split(bufio.ScanWords)
? ? for scanner.Scan() {
? ? ? ? results[removeNonWordChars(scanner.Text())]++
? ? }
? ? delete(results, "")
? ? return results
}
func removeNonWordChars(input string) string {
? ? var result strings.Builder
? ? result.Grow(len(input))
? ? for _, r := range strings.ToLower(input) {
? ? ? ? if r >= 'a' && r <= 'z' {
? ? ? ? ? ? _, err := result.WriteRune(r)
? ? ? ? ? ? if err != nil {
? ? ? ? ? ? ? ? log.Fatalln(err.Error())
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? return result.String()
}
輸出:
$ go tool pprof .cpu.prof
File: main
Type: cpu
Time: Oct 9, 2019 at 5:39am (EDT)
Duration: 600.79ms, Total samples = 390ms (64.91%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 320ms, 82.05% of 390ms total
Showing top 10 nodes out of 43
? ? ? flat? flat%? ?sum%? ? ? ? cum? ?cum%
? ? ?110ms 28.21% 28.21%? ? ? 110ms 28.21%? syscall.Syscall
? ? ? 60ms 15.38% 43.59%? ? ? ?90ms 23.08%? runtime.mapassign_faststr
? ? ? 40ms 10.26% 53.85%? ? ? ?40ms 10.26%? unicode/utf8.DecodeRune
? ? ? 30ms? 7.69% 61.54%? ? ? ?30ms? 7.69%? strings.(*Builder).WriteRune
? ? ? 20ms? 5.13% 66.67%? ? ? ?20ms? 5.13%? runtime.slicebytetostring
? ? ? 20ms? 5.13% 71.79%? ? ? ?20ms? 5.13%? strings.ToLower
? ? ? 10ms? 2.56% 74.36%? ? ? ?60ms 15.38%? bufio.ScanWords
? ? ? 10ms? 2.56% 76.92%? ? ? ?10ms? 2.56%? bufio.isSpace
? ? ? 10ms? 2.56% 79.49%? ? ? ?10ms? 2.56%? fmt.(*buffer).writeString
? ? ? 10ms? 2.56% 82.05%? ? ? ?10ms? 2.56%? memeqbody
(pprof) quit
$?
- 2 回答
- 0 關(guān)注
- 186 瀏覽
添加回答
舉報