golang-性能分析pprof

1,049 阅读3分钟

1. 什么是pprof?为什么需要使用pprof?

1.1 什么是pprof?

  • 用来做性能分析的工具

1.2 pprof可以从哪些角度来进行分析

  • CPU Profiling:CPU 分析,按照一定的频率采集所监听的应用程序 CPU(含寄存器)的使用情况,可确定应用程序在主动消耗 CPU 周期时花费时间的位置
  • Memory Profiling:内存分析,在应用程序进行堆分配时记录堆栈跟踪,用于监视当前和历史内存使用情况,以及检查内存泄漏
  • Block Profiling:阻塞分析,记录 goroutine 阻塞等待同步(包括定时器通道)的位置
  • Mutex Profiling:互斥锁分析,报告互斥锁的竞争情况

2. pprof 怎么使用?

package main

import (
	"encoding/json"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"net/http"
	netpprof "net/http/pprof"
	"os"
	"runtime/pprof"
	"time"
)

func main() {
	//pprofSingerProgram() // 分析单个程序示例
	//pprofHttp()          // 分析http服务示例
	pprofDiyHttp() // 分析自定义http服务示例
}

func pprofSingerProgram() {
	f, _ := os.Create("./test.pprof")
	pprof.StartCPUProfile(f)
	defer pprof.StopCPUProfile()
	for i := 0; i < 100000; i++ {
		LocalTz()
		DoSomething([]byte(`{"a": 1, "b": 2, "c": 3}`))
	}
}

func pprofHttp() {
	go func() {
		for {
			LocalTz()
			DoSomething([]byte(`{"a": 1, "b": 2, "c": 3}`))
		}
	}()
	time.Sleep(1)
	fmt.Println("start api server...")
	panic(http.ListenAndServe(":8081", nil))
}

func pprofDiyHttp() {
	var httpSvc *http.Server
	httpAddr := ":8081"
	mux := http.NewServeMux()

	mux.HandleFunc("/debug/pprof/", netpprof.Index)
	mux.HandleFunc("/debug/pprof/cmdline", netpprof.Cmdline)
	mux.HandleFunc("/debug/pprof/profile", netpprof.Profile)
	mux.HandleFunc("/debug/pprof/symbol", netpprof.Symbol)
	mux.HandleFunc("/debug/pprof/trace", netpprof.Trace)
	httpSvc = &http.Server{
		Addr:    httpAddr,
		Handler: mux,
	}
	if err := httpSvc.ListenAndServe(); err != nil && err != http.ErrServerClosed {
		fmt.Println(err)
	}
}

func DoSomething(s []byte) {
	var m map[string]interface{}
	err := json.Unmarshal(s, &m)
	if err != nil {
		panic(err)
	}

	s1 := make([]string, 0)
	s2 := ""
	for i := 0; i < 100; i++ {
		s1 = append(s1, string(s))
		s2 += string(s)
	}
}

func LocalTz() *time.Location {
	tz, _ := time.LoadLocation("Asia/Shanghai")
	return tz
}

2.1 在普通的程序中使用

  • 以上代码示例:pprofSingerProgram

2.2 在http server 中使用

  • 以上代码示例:pprofHttp
  • mac 安装 graphviz
    • brew install graphviz
    • 如果遇到报错,可以换成中科大的源,然后执行一下brew update
  • gin 框架中使用:go get "github.com/gin-contrib/pprof"

2.3 在自己定义的http server中 使用

  • 需要自己注册路由

2.3 获取各类数据的地址

  • 获取所有的数据:http://127.0.0.1:6060/debug/pprof/,以下列出其他的相关数据查看,如果你在对应的访问路径上新增 ?debug=1 的话,就可以直接在浏览器访问。否则就是直接下载文件
  • allocs:查看过去所有内存分配的样本,访问路径为 $HOST/debug/pprof/allocs。
  • block:查看导致阻塞同步的堆栈跟踪,访问路径为 $HOST/debug/pprof/block。
  • cmdline: 当前程序的命令行的完整调用路径。
  • goroutine:查看当前所有运行的 goroutines 堆栈跟踪,访问路径为 $HOST/debug/pprof/goroutine。
  • heap:查看活动对象的内存分配情况, 访问路径为 $HOST/debug/pprof/heap。
  • mutex:查看导致互斥锁的竞争持有者的堆栈跟踪,访问路径为 $HOST/debug/pprof/mutex。
  • profile: 默认进行 30s 的 CPU Profiling,得到一个分析用的 profile 文件,访问路径为 $HOST/debug/pprof/profile。
  • threadcreate:查看创建新 OS 线程的堆栈跟踪,访问路径为 $HOST/debug/pprof/threadcreate。

2.4 获取火焰图:

3. 火焰图怎么看?

  • 如下图,第一个是root,表示所有的函数的起点
  • 一行的数据中的各个函数是平行的,也就是说行元素之间
  • 一列的数据中的各个函数相当于上一行的子函数,向上负责的,也就是说列之间存在父子关系
    • 同时存在一列函数分为多个函数,长度代表他们的耗时

image.png

4. 参考链接