当前位置: 首页 > article >正文

Go怎么做性能优化工具篇之pprof

工欲善其事、必先利其器。这次我们来看看Go的性能优化工具有哪些吧

Go性能优化的工具

一、pprof 工具

pprof 是 Go 语言自带的性能分析工具,可以帮助开发者分析程序的 CPU 使用情况、内存使用情况、goroutine 调度情况等,从而定位性能瓶颈。通过 pprof,开发者可以生成各种性能报告,帮助进行代码优化。

1、pprof 如何使用

首先,你需要在 Go 程序中引入 net/http/pprof 包,这个包自动注册了 HTTP 端点,允许你查看性能数据。

1.1 启动 pprof 服务器

首先,你需要在 Go 程序中引入 net/http/pprof 包,这个包自动注册了 HTTP 端点,允许你查看性能数据。

package main

import (
	"fmt"
	"log"
	"net/http"
	_ "net/http/pprof" // 导入 pprof 包,它会自动注册 HTTP 路由
	"time"
	"math/rand"
	"sync"
	"os"
)

var wg sync.WaitGroup

// 模拟一个高负载的函数,进行大量计算
func heavyComputation(n int) int {
	time.Sleep(time.Millisecond * 10) // 模拟计算延迟
	return n * n
}

// 模拟一个程序
func startTasks() {
	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()
			// 模拟 CPU 密集型任务
			heavyComputation(rand.Intn(1000))
		}(i)
	}
}

func main() {
	// 启动 pprof HTTP 服务,监听 6060 端口
	go func() {
		log.Println("pprof listening on localhost:6060")
		log.Fatal(http.ListenAndServe("localhost:6060", nil))
	}()
	
	// 启动一些模拟任务
	go startTasks()
	
	// 等待任务完成
	wg.Wait()
	
	// 打印一些结果
	fmt.Println("All tasks completed")

	// 模拟一些其他处理
	time.Sleep(10 * time.Minute) // 让程序持续运行,供 pprof 分析
}
  • 通过导入 net/http/pprof 包,你不需要显式地调用它的函数,包会自动将相关的 HTTP 处理程序注册到默认的 HTTP 路由器上。
  • 可以通过访问 http://localhost:6060/debug/pprof/ 来获取性能分析数据。
    在这里插入图片描述
1.2 proof 字段分析
  • allocs(内存分配采样)
    描述:记录程序中所有过去的内存分配。allocs 不是针对某个特定时间点的快照,而是通过定期采样程序的内存分配来获取信息。
    用途:帮助分析程序的内存使用情况,找出高频的内存分配和可能的内存泄漏。可以通过查看分配的内存块,了解哪些部分的代码导致了过多的内存分配。
    示例:通过 pprof 你可以获取内存分配的历史采样数据,找到内存使用的瓶颈。

  • block(阻塞分析)
    描述:记录导致阻塞的栈跟踪信息,通常与同步原语(如 sync.Mutex、sync.Cond 等)相关。阻塞是指某个 goroutine 因等待锁、条件变量等原因无法继续执行。
    用途:帮助分析程序中阻塞的 goroutine,尤其是锁争用和并发问题。通过分析 block profile,你可以查看哪些同步操作导致了程序性能下降。
    示例:如果程序存在多个 goroutine 并发访问共享资源且存在锁竞争,block profile 会显示这些锁争用和阻塞的堆栈信息。

  • cmdline(命令行)
    描述:记录当前程序的命令行启动参数。包括程序的所有命令行参数。
    用途:有助于了解当前运行的程序是如何启动的,哪些命令行参数被传递给程序。这对分析程序执行环境和上下文非常重要。
    示例:可以帮助你识别程序的启动方式,比如使用了哪些配置文件、环境变量或特定的运行参数。

  • goroutine(goroutine栈分析)
    描述:记录当前所有 goroutine 的栈跟踪信息。每个 goroutine 可能处于不同的状态(例如:运行中、等待中或阻塞中)。
    用途:帮助分析程序中的并发行为,尤其是追踪那些长时间运行或阻塞的 goroutine。可以帮助发现死锁、锁竞争等并发问题。
    示例:当程序有大量 goroutine 时,通过查看 goroutine profile,你可以看到所有 goroutine 的调用栈,并找出哪些 goroutine 在等待、阻塞或占用大量资源。

  • heap(堆内存分析)
    描述:对程序中当前存活的对象进行内存分配采样。heap profile 给出了程序在某一时刻堆上所有活跃对象的内存使用情况。
    用途:用于分析堆内存的使用情况,特别是帮助识别内存泄漏或不必要的内存分配。通过 heap profile,开发者可以找出程序中使用最多内存的对象。
    示例:如果程序内存消耗过高,使用 heap profile 可以帮助找出内存使用最多的地方,或者确认是否存在未被释放的内存。

  • mutex(互斥锁分析)
    描述:记录持有并争用互斥锁的 goroutine 栈跟踪。mutex profile 显示了锁争用情况,包括哪些 goroutine 当前持有锁,哪些 goroutine 在等待锁。
    用途:帮助分析程序中的锁竞争和同步问题。对于性能瓶颈,特别是锁争用较为严重的程序,可以使用 mutex profile 来找出锁的争用点。
    示例:如果有多个 goroutine 在争夺同一个锁,mutex profile 会显示哪个 goroutine 持有锁,哪些正在等待,从而帮助开发者优化锁的使用。

  • profile(CPU分析)
    描述:记录程序的 CPU 性能分析数据。可以指定采样的持续时间(通过 GET 参数中的 duration),profile 是常用的性能分析工具,帮助定位 CPU 的瓶颈。
    用途:用于分析程序的 CPU 使用情况,找出消耗大量 CPU 时间的函数或代码路径。常见的用途是分析程序中消耗最多时间的部分,并进行性能优化。
    示例:通过 profile,你可以获得一个 CPU profile 文件,并使用 go tool pprof 命令来分析哪个函数消耗了最多的 CPU 时间。

  • threadcreate(线程创建分析)
    描述:记录导致创建新操作系统线程的栈跟踪。操作系统线程是由 Go 运行时系统管理的线程,Go 会根据需要动态创建操作系统线程。
    用途:帮助分析程序中是否存在大量的线程创建,可能影响性能。过多的线程创建可能导致上下文切换频繁,从而影响程序的整体性能。
    示例:通过 threadcreate profile,你可以发现哪些操作会触发新的线程创建,并查看线程的堆栈信息。

  • trace(程序执行追踪)
    描述:记录程序的执行轨迹。通过 trace,可以跟踪程序的所有执行过程,详细记录 goroutine 的调度、阻塞等事件。
    用途:帮助分析程序的执行流程,查看 goroutine 的调度情况,尤其是在并发程序中,分析并发和同步的问题。
    示例:使用 trace 你可以查看程序在特定时间段内的所有调度事件,包括 goroutine 的启动、调度、阻塞等情况。

allocs、heap 和 profile 主要用于内存和 CPU 性能分析,帮助找出内存泄漏、过度分配和 CPU 密集型操作。
block、mutex 和 threadcreate 主要用于并发分析,帮助找出锁竞争、阻塞和线程创建问题。
goroutine 和 trace 则帮助分析程序的并发行为和执行过程。

我们也可以不通过上面的页面触发性能数据采集,而是直接访问 url 并添加参数来控制采集的时长,就像下面这样

 curl "http://127.0.0.1:6060/debug/pprof/profile?seconds=30" > profile.pprof

在这些采样类型里,常用的有下面两类:

profile 采样,也就是 cpu 采样,用于确定程序中哪些函数或代码片段在运行时消耗了大量的 CPU 时间,帮助定位 CPU 性能瓶颈。

内存分配采样,具体包括 allocs 采样和 heap 采样。其中,allocs 采样侧重于定位那些频繁进行内存分配的函数,而 heap 采样用于查看存活对象的内存分配情况,侧重于定位内存泄漏问题。

1.3 火焰图

火焰图(Flame Graph)是性能分析的一个可视化工具,能够帮助你快速识别程序中最耗时的部分。在 Go 中,火焰图常常与 pprof 配合使用,用于分析程序的 CPU 性能。通过火焰图,你可以轻松地看到程序的函数调用栈,查看每个函数的执行时间,从而发现性能瓶颈。

  • 使用 pprof 收集 CPU 配置

在 Go 中,你可以通过 net/http/pprof 包来生成性能分析数据。首先确保你的 Go 程序包含了 pprof。

导入 net/http/pprof 包

package main

import (
	"fmt"
	"math/rand"
	"net/http"
	_ "net/http/pprof" // 引入pprof包来启用性能分析
	"os"
	"time"
)

func main() {
	// 启动pprof HTTP server
	go func() {
		fmt.Println("Starting pprof server on :6060...")
		if err := http.ListenAndServe(":6060", nil); err != nil {
			fmt.Println("Error starting pprof server:", err)
		}
	}()

	// 模拟一些计算任务
	for {
		// 模拟一些负载
		rand.Seed(time.Now().UnixNano())
		n := rand.Intn(100000)
		_ = fib(n) // 调用一个计算密集型函数
		time.Sleep(time.Second) // 稍作等待
	}
}

// fib 是一个计算 Fibonacci 数列的函数,模拟计算密集型任务
func fib(n int) int {
	if n <= 0 {
		return 0
	}
	if n == 1 {
		return 1
	}
	return fib(n-1) + fib(n-2)
}


  • 获取 CPU 配置数据

要生成火焰图,首先需要从程序中获取 CPU 配置数据。你可以通过向 pprof 提供一个请求来获取 CPU 配置:

访问 URL http://localhost:6060/debug/pprof/profile?seconds=30,这里的 seconds=30 表示你希望记录 30 秒的 CPU 样本。

wget http://localhost:6060/debug/pprof/profile?seconds=30 -O cpu.pprof

这会将 CPU 配置样本保存到一个文件中,名为 cpu.pprof。

  • 安装 graphviz 工具

  • 生成火焰图

使用 go tool pprof 来处理 cpu.pprof 文件,并将其转换为火焰图。首先安装 go tool pprof:

go get github.com/google/pprof

然后,使用 go tool pprof 生成一个 .svg 格式的火焰图。

在命令行中使用 go tool pprof 进行分析:

go tool pprof cpu.pprof

你会进入一个交互式的 pprof shell,在这个 shell 中,你可以使用 svg 命令(需要先安装graphviz 工具)来生成火焰图:

(pprof) svg

这将生成一个 .svg 文件,保存为 profile.svg。你可以用浏览器打开它查看火焰图。

我们也可以使用可视化界面来查看。Golang 提供了可视化展示工具 pprof,我们可以通过下面的命令,启动一个 Web 界面查看(可视化界面需要提前安装 graphviz)。

go tool pprof -http :8889 cpu.pprof

在这里插入图片描述
通过这里可以查看具体的代码。
在这里插入图片描述

二、benchmark 功能(下篇继续)
三、trace 工具

http://www.kler.cn/a/444025.html

相关文章:

  • Day50 图论part01
  • Unity全局雾效
  • Chapter 19 Layout and Packaging
  • ScottPlot学习的常用笔记-02
  • 小红书关键词搜索采集 | AI改写 | 无水印下载 | 多维表格 | 采集同步飞书
  • C# 6.0 连接elasticsearch数据库
  • C# 文件系统I/O操作--File类与FileInfo类
  • 【Tomcat】第三站:注解
  • 两款轻量级数据库SQLite 和 TinyDB,简单!实用!
  • thinkphp5验证码captcha无法显示
  • 字符串类算法
  • Connection lease request time out 问题分析
  • 基于java的CRM客户关系管理系统的设计与实现
  • 计算机必背单词——云计算和虚拟化
  • 数据结构:双向带头循环链表的增删查改
  • 使用Maven打包javaagent.jar
  • 关于解决VScode中python解释器中的库Not Found的问题
  • C# 开发应用篇——C# 基于WPF实现数据记录导出excel详解
  • Unity添加newtonsoft-json
  • 着色器 (三)
  • 游戏《姆吉拉的假面》启动时提示“xinput1_3.dll丢失”怎么办?“xinput1_3.dll丢失”要怎么解决?
  • 三、ubuntu18.04安装docker
  • 【openssl】 version `OPENSSL_3.0.3‘ not found 问题
  • conda-pack迁移虚拟环境
  • 【Qt】qt安装
  • 计算机网络知识点全梳理(三.TCP知识点总结)