pprof初探 | 青训营笔记

211 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 6 天

简介

pprof是GoLang程序性能分析工具,prof是profile(画像)的缩写,使用pprof可以分析如下图所示的9中数据:

1.jpeg

其中最常用的有:

profile—CPU分析,确定CPU在主动消耗CPU周期时花费时间的位置;

heap—内存分析,在应用程序进行堆分配时记录堆栈跟踪,用于监视当前历史内存使用情况,以及检查内存泄漏

goroutine—协程分析,主要是goroutine泄露导致内存泄漏

mutex—互斥锁分析,报告互斥锁的竞争情况

block—阻塞分析,记录 goroutine 阻塞等待同步(包括定时器通道)的位置

pprof工具所涉及到的内容如下图所示:

2.jpeg

下面从pprof获取数据的工具,结合具体代码进行性能分析三个方面展开。

数据获取工具

针对应用的类型不同,数据的获取工具主要有两种。

runtime/pprof

该工具主要应用于执行完任务就退出的应用类型。在应用执行过程中,通过调用合适的函数,将画像数据写入文件中,以供后面的分析使用。

package main

import (
	"fmt"
	"os"
	"runtime/pprof"
)

func main() {
	//CPU Profile
	f, err := os.Create("./cpuprofile")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()
	pprof.StartCPUProfile(f)
	defer pprof.StopCPUProfile()

	//Memory Profile
	fm, err := os.Create("./memoryprofile")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer fm.Close()
	pprof.WriteHeapProfile(fm)

	for i := 0; i < 100; i++ {
		fmt.Println("程序员麻辣烫")
	}
}

执行上述代码,会生成cpuprofile、memoryprofile文件,里面包含cpu、内存使用情况的画像。

net/http/pprof

对于一直运行的应用,如web服务等,可以使用该工具进行分析。

使用时,可以使用默认的ServerMux,并且在代码中直接使用http.ListenAndServe("0.0.0.0:端口号", nil)第二个参数赋值为nil表示使用默认的ServerMux。

实例分析

下面结合具体实例来介绍pprof一些常用的方法,代码的链接为github.com/wolfogre/go…

该工具常用的命令有:

http://localhost:端口号/debug/pprof

使用该命令可以在浏览器中看到代码运行过程中的CPU,内存,锁等数据的画像信息,如下图所示

3.jpeg

go tool pprof + 采样链接

该命令用于启动采样,并且还可以设置采样的时间,上图中通过右键点击profile,heap,mutex等便可以获得采样链接。

如下面所示的命令便是对CPU使用信息进行采样,采样时间为10s。

go toool pprof "http://localhost:6060/debug/pprof/profile?second=10"

采样结果形式如下所示: 4.jpeg

之后便可以输入具体命令来探查具体的CPU使用情况,比如:

top可以查看CPU使用最高的函数;

list+函数可以查看CPU使用高的函数具体是什么情况出现了问题

上述在命令行窗口进行操作不是很直观,可以使用go tool pprof -http:=8080 + 采样链接的方式打开pprof自带的Web UI,性能指标会以网页的方式呈现。

5.jpeg

上图便是以命令

go tool pprof -http=:8080"[<http://localhost:6060/debug/pprof/heap>](<http://localhost:6060/debug/pprof/heap>)"

所打开的。描述的是堆内存采样的结果。

view代表试图选项,常用的有Top,Graph,Flame Graph,上图中对应的便是Graph,Flame Graph是火焰图,对应的视图如下所示:

6.jpeg

Sample选项下有inuse_space,alloc_space分别表示正在使用的堆内存与程序运行至今分配过的堆内存,inuse_object,alloc_object分别表示正在使用的对象与程序运行至今分配过的对象

其余数据的分析(如mutex,gorutine等等)读者可以自己尝试。