go 调试利器之pprof指标分析

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

文章目录

概要

Go语言原生支持对于程序运行时重要指标或特征进行分析。pprof是其中一种重要的工具其不仅可以分析程序运行时的错误内存泄漏、并发冲突、协程泄漏等也可以对程序进行优化比如定位cpu,内存异常逻辑。由于Go程序运行时不对外暴漏相关指标因此Go提供了runtime/pprofnet/http/pprof基础库来与外界交互其中net/http/pprof是对runtime/pprof的进一步封装让用户可以通过http获取相关指标。

一、指标类型

本章节我们结合源码来看看有哪些指标提供给我们。

1.1、堆栈指标

// profiles records all registered profiles.
var profiles struct {
	mu sync.Mutex
	m  map[string]*Profile
}
//	goroutine    - stack traces of all current goroutines
//	heap         - a sampling of memory allocations of live objects
//	allocs       - a sampling of all past memory allocations
//	threadcreate - stack traces that led to the creation of new OS threads
//	block        - stack traces that led to blocking on synchronization primitives
//	mutex        - stack traces of holders of contended mutexes
func lockProfiles() {
	profiles.mu.Lock()
	if profiles.m == nil {
		// Initial built-in profiles.
		profiles.m = map[string]*Profile{
			"goroutine":    goroutineProfile,//go协程堆栈分析
			"threadcreate": threadcreateProfile,//创建新系统级线程的堆栈跟踪
			"heap":         heapProfile,//活跃对象内存分析在应用程序进行堆分配时记录堆栈跟踪用于监视当前和历史内存使用情况以及检查内存泄漏
			"allocs":       allocsProfile,//过去所有内存分配的抽样heap的结果是包含它的
			"block":        blockProfile,//导致阻塞的同步原语堆栈追踪
			"mutex":        mutexProfile,//互斥锁分析争用互斥锁持有者的堆栈跟踪
		}
	}
}

示例

	saveFile, err := os.OpenFile("./goroutine.out", os.O_CREATE|os.O_APPEND, 0644)
	if err != nil {
		log.Println(err)
		return
	}
	err = pprof.Lookup("goroutine").WriteTo(saveFile, 0)
	if err != nil {
		log.Println(err)
	}

1.2、CPU指标分析

cpu指标分析并没有注册到全局变量到profiles.m中管理而是需要手动开启并在不需要采集时手动关闭。其以100hz的频率采集相关数据。

func StartCPUProfile(w io.Writer) error {
	//代码省略。。。
}
func StopCPUProfile() {
	//代码省略。。。
}

示例

	saveFile, err := os.OpenFile("./cpu.out", os.O_CREATE|os.O_APPEND, 0644)
	if err != nil {
		log.Println(err)
		return
	}
	if err = pprof.StartCPUProfile(saveFile); err != nil {
		log.Println("could not start CPU profile: ", err)
		return
	}
	//after sometime call StopCPUProfile
	defer pprof.StopCPUProfile()

runtime/pprof一般适合只跑一次的程序下面我们看看net/http/pprof如何使用的吧。

1.3、http-pprof

http模式是最常用的前面说过http就是对runtime/pprof的封装其本质也是调的runtime/pprof的函数。
下面是http模式提供的http接口。

func init() {
	http.HandleFunc("/debug/pprof/", Index)//runtime/pprof 的 profiles.m 里注册的指标
	http.HandleFunc("/debug/pprof/cmdline", Cmdline)//仅打印程序启动时的参数 
	http.HandleFunc("/debug/pprof/profile", Profile)//runtime/pprof 的StartCPUProfile/StopCPUProfile
	http.HandleFunc("/debug/pprof/symbol", Symbol)
	http.HandleFunc("/debug/pprof/trace", Trace)//runtime/trace进行事件追踪协程的创建开始结束。网络IO事件。协程阻塞事件等属于宏观视图具体细节还要要看pprof
}

示例

package main

import (
	"log"
	"net/http"
	_ "net/http/pprof"
	"sync"
	"time"
)

func main() {
	go testHttpPprof()
	err := http.ListenAndServe("0.0.0.0:8888", nil)
	if err != nil {
		log.Fatal(err)
	}
}
func testHttpPprof() {
	i := 0
	for {
		go Add(i)
		time.Sleep(time.Second)
		i++
	}
}

var (
	sum  = 0
	data []int
	lock sync.Mutex
)

func Add(x int) {
	defer lock.Unlock()
	if x&1 == 0 {
		time.Sleep(time.Second)
	} else {
		time.Sleep(2 * time.Second)
	}
	lock.Lock()
	sum += x
	data = append(data, sum)
}

只需要导入net/http/pprof库再起一个http服务就可以通过http访问相关指标了。

http://127.0.0.1:8888/debug/pprof/ #查看可用指标接口
在这里插入图片描述
http://127.0.0.1:8888/debug/pprof/heap #查看内存堆栈分析
http://127.0.0.1:8888/debug/pprof/goroutine?debug=1 #查看所有协程堆栈信息
http://127.0.0.1:8888/debug/pprof/goroutine?seconds=30 #查看30s内所有协程堆栈信息
http://127.0.0.1:8888/debug/pprof/profile?seconds=30 #查看未来30s内的CPU数据分析
依次类推…

当携带参数debug时是返回当前堆栈数据否则返回的是一个可下载的文件
获取到文件后可以用go tool pprof xxx来分析文件。

二、go tool pprof

这里以内存指标分析为例首先通过http://127.0.0.1:8888/debug/pprof/heap?seconds=30获取一个pprof文件。
go tool pprof -h 可以查看所有指令
go-pprof
常用的指令

  • top -cum #根据cum从大到小排序默认根据flat从大到小排序。在heap分析下cum是从当前函数开始累计内存占用。flat是当前函数分配的内存其他分析cpu,mutex等为维度不同的含义。
  • tree #函数调用链
  • list xxx #列出某个函数的信息

另外 heap分析有四种不同类型的内存分析维度alloc_objects、alloc_space、inuse_objects、inuse_space
alloc_objects和inuse_objects表示申请的对象和正在使用的对象
alloc_space和inuse_space表示申请的内存和正在使用的内存

默认是inuse_objects切换很简单只需输入 alloc_objects 就能切到alloc_objects维度。

2.1、可视化

pprof提供了强大的可视化功能可以将内容转化成图片或html,只不过需要先安装graphviz

这样在命令行中输入web,png,gif等命令就可以输出相应可视化结果。
go-pprof-ui
如图就会生成一张个png图片。

2.2、CPU火焰图

如同2.1节获取cpu数据文件后除了可以用go tool pprof生成png文件外还可以生成火焰图命令如下

go tool pprof -http :8889 http://127.0.0.1:8888/debug/pprof/profile?seconds=90

稍等一会就可以通过8889端口访问火焰图了通过VIEW菜单可以切换到不同可视化方式来查看
go-cpu火焰图
go-cpu-可视化

  • 箭头越粗代表当前路径越消耗资源内存,时间等
  • 箭头为虚线表示两个节点之间的某些节点已被忽略为间接调用
  • 节点颜色红色表示cum累计值为正数并且很大绿色表示cum累计值为负数并且很大灰色表示cum累计值可以忽略不计。
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: go