go语言学习笔记 — 基础 — go工具:性能分析,发现代码性能问题的具体位置 —— go pprof

Posted Locutus

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了go语言学习笔记 — 基础 — go工具:性能分析,发现代码性能问题的具体位置 —— go pprof相关的知识,希望对你有一定的参考价值。

go pprof可以帮助开发者快速定位与分析各种go程序的性能问题,如CPU消耗、内存分配和阻塞分析。

性能分析使用runtime.pprof包,嵌入到待分析go程序的入口和结尾处。runtime.pprof包在程序运行时进行每秒100次采样,最少采样1秒,然后把生成的数据导出,让开发者写入文件或在其他媒介上分析。

go pprof配合Graphviz图形化工具,可以把runtime.pprof包生成的数据转换成PDF,来展示程序性能分析报告。

安装第三方图形化显式分析工具(graphviz)

官网:www.graphviz.org

macOS下安装

# brew install graphviz

安装第三方性能分析来分析代码包

runtime.pprof提供基础的go程序运行时性能分析,这套接口用起来不太方便:使用io.Writer接口,虽然扩展性很强,但是实际使用不太方便,不支持持续写入文件;默认配置项复杂

第三方profile包对系统包runtime.pprof技术上进行封装,使整个测试过程更方便。

# go get github.com/pkg/profile

性能分析代码

package main

import (
	"time"

	"github.com/pkg/profile" // 在设置好GOPATH条件下,第三方包需要使用go get下载到本地才能用,引用路径从$GOPATH/src/之后开始
)

func joinSlice() []string {
	var arr []string

	for i := 0; i < 100000; i++ {
		arr = append(arr, "arr") // 向arr切片中,不停的添加元素。o(n),性能较低
	}
	return arr
}

func main() {
	// 使用profile.Start调用github.com/pkg/profile开始性能分析,返回一个stopper.stop接口,方便在程序结束时,结束性能分析
	stopper := profile.Start(profile.CPUProfile, profile.ProfilePath(".")) // 这里使用profile.CPUProfile(CPU耗用)作为分析项,使用profile.ProfilePath(".")指定输出程序性能分析报告到当前路径

	// 在main()函数结束时,结束性能分析
	defer stopper.Stop()

	// 性能分析核心逻辑
	joinSlice()

	// 程序性能分析最短时间为1秒,在main()函数结束前等待1秒,如果你的程序默认运行1秒以上,可以去掉这句
	time.Sleep(time.Second)
}

编译上述代码,产生可执行文件cpu,运行cpu后生成.pprof文件,并用go tool工具转换成.pdf文件。

# go build -o cpu profile_cpu.go 

# ./cpu

# ls 
cpu.pprof cpu profile_cpu.go 

# go tool pprof --pdf cpu cpu.pprof > cpu.pdf

# ls 

cpu.pprof cpu profile_cpu.go cpu.pdf

从pdf文件中,我们可以看到每一个函数调用的路径,从而找到耗费CPU时间最多的操作,joinSlice()中有o(n)的时间复杂度,存在性能瓶颈,需要重构代码。在已知切片数量情况下,直接分配内存。代码如下:

func joinSlice() []string {
    const count = 100000
    
    arr := make([]string, count)

    for i := 0; i < count; i++ {
        arr[i] = "arr" // 向arr切片中,不停的添加元素
    }
    return arr
}

以上是关于go语言学习笔记 — 基础 — go工具:性能分析,发现代码性能问题的具体位置 —— go pprof的主要内容,如果未能解决你的问题,请参考以下文章

go语言学习笔记 — 基础 — go工具:go工具

go语言学习笔记 — 基础 — go工具:编译 —— go build

go语言学习笔记 — 基础 — go工具:编译并安装 —— go install

go语言学习笔记 — 基础 — go工具:编译后运行 —— go run

go语言学习笔记 — 基础 — go工具:一键获取源代码,编译并安装 —— go get

go语言学习笔记 — 基础 — go工具(5.1):单元测试 —— 测试和验证代码的框架