性能分析工具pprof与图形展示go-torch的使用

性能分析工具pprof与图形展示go-torch的使用

一 准备

  • 安装graphviz

    # ubuntu
    sudo apt install graphviz
    # centos
    sudo yum install graphviz
    
  • G O P A T H / b i n 加 入 GOPATH/bin 加入 GOPATH/binPATH下

  • 安装go-torch

    go get -u github.com/uber-archive/go-torch
    

    下载并复制flamegraph.pl(https://github.com/brendangregg/FlameGraph)至$GOPATH/bin 路径下

二 通过文件方式输出Profile

API 文档:

http://docscn.studygolang.com/pkg/runtime/pprof/

使用 :

go tool pprof [binary] [binary.prof]

example:

func getrangeint() int {
	s := rand.New(rand.NewSource(time.Now().UnixNano()))
	return s.Intn(22)
}

func fillstr(s string, n int) string {
	a := ""
	for i := 0; i < n; i++ {
		a = a + genstr(s, getrangeint())
	}
	return a
}

func genstr(s string, n int) string {
	a := ""
	for i := 0; i < n; i++ {
		a = a + s
	}
	return a
}

func main() {
	// cpu 信息
	// 创建输出文件
	f, err := os.Create("cpu.prof")
	defer f.Close()
	if err != nil {
		log.Fatal("cloud not create cpu.prof file,err=", err)
	}
	// 获取系统信息
	if err = pprof.StartCPUProfile(f); err != nil {
		log.Fatal("could not start cpu profile,err=", err)
	}
	defer pprof.StopCPUProfile()

	fmt.Println(len(fillstr("s", 50000)))

	// 堆栈信息
	f1, err := os.Create("mem.prof")
	if err != nil {
		log.Fatal("cloud not create mem.prof file,err=", err)
	}
	defer f1.Close()

	if err = pprof.WriteHeapProfile(f1); err != nil {
		log.Fatal("could not write memory profile,err=", err)
	}

	// 协程信息
	f2, err := os.Create("goroutine.prof")
	defer f2.Close()
	if err != nil {
		log.Fatal("cloud not create goroutine.prof file,err=", err)
	}
	if gProf := pprof.Lookup("goroutine"); gProf == nil {
		log.Fatal("could not write goroutine profile")
	} else {
		gProf.WriteTo(f2, 0)
	}

}

这个例子主要功能是生成随机个字符,但是由于每次都是 + 链接字符,很耗费内存

生成执行文件并运行,得到文件

go build main.go

ls

cpu.prof  goroutine.prof  main  main.go  mem.prof
  • 查看cpuinfo
$ go tool pprof main cpu.prof 
File: main
Type: cpu
Time: May 20, 2019 at 8:52pm (CST)
Duration: 3s, Total samples = 3.69s (122.84%)
Entering interactive mode (type "help" for commands, "o" for options)
# 查看cpu占用大小前十
(pprof) top  
Showing nodes accounting for 3060ms, 82.93% of 3690ms total
Dropped 38 nodes (cum <= 18.45ms)
Showing top 10 nodes out of 112
      flat  flat%   sum%        cum   cum%
    1630ms 44.17% 44.17%     1630ms 44.17%  runtime.memmove
     460ms 12.47% 56.64%      460ms 12.47%  math/rand.seedrand
     240ms  6.50% 63.14%      310ms  8.40%  runtime.scanobject
     200ms  5.42% 68.56%      200ms  5.42%  runtime.futex
     150ms  4.07% 72.63%      150ms  4.07%  runtime.procyield
     110ms  2.98% 75.61%      110ms  2.98%  runtime.memclrNoHeapPointers
     110ms  2.98% 78.59%      160ms  4.34%  runtime.scanblock
      60ms  1.63% 80.22%      520ms 14.09%  math/rand.(*rngSource).Seed
      60ms  1.63% 81.84%       80ms  2.17%  runtime.findObject
      40ms  1.08% 82.93%      140ms  3.79%  runtime.gentraceback
     # 图形化显示
(pprof) svg 
Generating report in profile001.svg
(pprof) exit

可以看到 大步分cpu用来进行字节拷贝,小部分用于生成随机数。

使用打开 profile001.svg

  • 或者使用go-toch 生成火炬图
$ go-torch mem.prof 
INFO[21:30:07] Run pprof command: go tool pprof -raw -seconds 30 mem.prof
INFO[21:30:07] Writing svg to torch.svg

三 通过HTTP 方式输出profile

  • 适合持续性运行的应用
  • 在应用中导入 import _ “net/http/pprof”,并启动http server
  • http://:/debug/pprof/
  • go tool pprof http://:/debug/pprof/profile?seconds=10(默认30s)
  • go-torch -seconds 10 http://:/debug/pprof/profile
# example
package main

import (
	"encoding/json"
	"fmt"
	"github.com/luslin/golang-http-funs/parse"
	"net/http"
	_ "net/http/pprof"
)

var P *parse.RequestParser

func init(){
	P = parse.NewRequestParser()
	P.AddArgument("did",true,"did error",parse.Json,parse.Post)
	P.AddArgument("ssu-uid",true,"ssu-uid error",parse.Str,parse.Header)
}

func main() {
	http.HandleFunc("/", IndexHandler)
	_ = http.ListenAndServe("127.0.0.1:8001", nil)
}


func IndexHandler(w http.ResponseWriter, r *http.Request) {
	var ret []byte
	for i:= 0; i<10000;i++{
		res , err := P.Parse(r)
		if err != nil{
			_ ,_ = fmt.Fprintln(w, err.Error())
			return
		}
		ret ,_ = json.Marshal(res)
	}
	fmt.Println(ret)
	_ ,_ = fmt.Fprintln(w, string(ret))
}

运行后打开网址

http://127.0.0.1:8001/debug/pprof/

或者使用命令行工具

$ go tool pprof http://127.0.0.1:8001/debug/pprof/profile?seconds=10

你可能感兴趣的:(go)