Golang性能分析

Golang性能分析

1、通过pprof实时分析

性能分析的场景主要有:CPU、Memory、IO、Goroutine、死锁几种。

下面是主要两种类型的应用:

1.1 服务型应用

_ "net/http/pprof" 包,专用于采集 web 服务运行数据的分析,即在运行的服务中通过 API 调用取数据。服务

型应用场景中因为应用要一直提供服务,所以 pprof 是通过 API 访问来获取,pprof 使用了默认的

http.DefaultServeMux 挂载这些 API 接口。

package main

import (
	"net/http"
	_ "net/http/pprof"
)

func main() {
	// 服务资源分析时使用
	// 访问路径: http://localhost:23300/debug/pprof/
	listenAddress := ":23300"
	err := http.ListenAndServe(listenAddress, nil)
	if err != nil {
		panic("启动服务失败")
	}
}

1.2 工具型应用

"runtime/pprof" 包,专用于采集应用程序运行数据的分析,通过代码手动添加收集命令。工具型应用是一个提

供特定功能使用的工具,使用完就会退出进程的应用,开发者手动控制把 profile 文件保存到报告文件中。封装的

接口可以调用,如要进行 CPU Profiling,则调用 pprof.StartCPUProfile(w io.Writer) 写入到 w 中,停止时调用

StopCPUProfile();要获取内存数据,直接使用 pprof.WriteHeapProfile(w io.Writer) 函数则可。

package main

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

func main() {
	// 创建CPU性能分析文件
	f, err := os.Create("cpu.prof")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()

	// 开始CPU性能分析
	if err := pprof.StartCPUProfile(f); err != nil {
		fmt.Println(err)
		return
	}
	defer pprof.StopCPUProfile()

	// 模拟CPU密集型任务
	for i := 0; i < 1000000; i++ {
		rand.Intn(100000)
	}
}
package main

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

func main() {
	f, err := os.Create("mem.pprof")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()

	// 这里放需要进行性能分析的代码
	for i := 0; i < 1000000; i++ {
		rand.Intn(100000)
	}

	// 手动GC
	var ms runtime.MemStats
	runtime.GC()
	runtime.ReadMemStats(&ms)

	err = pprof.WriteHeapProfile(f)
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println("分析完成,请使用go tool pprof mem.pprof命令进行分析")
}

2、功能介绍

CPU 分析(profile):每秒采集99次。

内存分配(allocs):堆栈等空间上的内存分配采样,每分配512K字节时取样一次。

阻塞(block):堆栈跟踪导致阻塞的同步原语。

命令行调用(cmdline):命令行调用的程序。

goroutine:当前 goroutine 的堆栈信息。

堆(heap):堆上内存分配的抽样,每分配512K字节时取样一次。

互斥锁(mutex):堆栈跟踪竞争状态互斥锁的持有者。

系统线程的创建(threadcreate):堆栈跟踪系统新线程的创建。

trace:追踪当前程序的执行状况,你可以用 seconds 参数指定抽样持续时间,你获取到 trace 概览后可以用 go

tool trace命令调查这个 trace。

3、下载pprof文件

$ curl -o cpu_profile http://127.0.0.1:23300/debug/pprof/profile?seconds=60 || http://127.0.0.1:23300/debug/pprof/heap?seconds=60 ||http://127.0.0.1:23300/debug/pprof/allocs?seconds=60 || http://127.0.0.1:23300/debug/pprof/block || http://127.0.0.1:23300/debug/pprof/groutines?seconds=60
# k8s
$ kubectl cp <ns-name>/<pod_name>:cpu_profile /root/fourier/tmp/cpu_profile

4、命令行工具(go tool pprof)

注意:go tool 与生成pprof的go版本应一致,否则可能报错 unrecognized profile format。

$ go tool pprof 文件|链接
$ go tool pprof http://localhost:23300/debug/pprof/goroutine
$ go tool pprof cpu.prof

5、top命令

$ C:\Users\zhangshixing\Desktop\新建文件夹>go tool pprof http://localhost:23300/debug/pprof/goroutine
Fetching profile over HTTP from http://localhost:23300/debug/pprof/goroutine
Saved profile in C:\Users\zhangshixing\pprof\pprof.goroutine.002.pb.gz
Type: goroutine
Time: Feb 5, 2024 at 3:43pm (CST)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top5
Showing nodes accounting for 5, 100% of 5 total
Showing top 5 nodes out of 37
      flat  flat%   sum%        cum   cum%
         4 80.00% 80.00%          4 80.00%  runtime.gopark
         1 20.00%   100%          1 20.00%  runtime/pprof.runtime_goroutineProfileWithLabels
         0     0%   100%          2 40.00%  bufio.(*Reader).ReadLine
         0     0%   100%          2 40.00%  bufio.(*Reader).ReadSlice
         0     0%   100%          2 40.00%  bufio.(*Reader).fill
  • flat:在给定函数上运行耗时。

  • flat%:在给定函数上运行耗时总比例。

  • sum%:给定函数累计使用 CPU 总比例。

  • cum:当前函数以及包含子函数的调用运行总耗时。

  • cum%:同上的 CPU 运行耗时总比例。

  • 最后一列为函数名称,详细见后续指标介绍。

6、list命令

# list [funcName]
(pprof) list Accept
Total: 3
ROUTINE ======================== internal/poll.(*FD).Accept in D:\OwnerSoftwareInstall\Go\src\internal\poll\fd_windows.go
         0          1 (flat, cum) 33.33% of Total
         .          .    971:           s, err := sysSocket()
         .          .    972:           if err != nil {
         .          .    973:                   return syscall.InvalidHandle, nil, 0, "", err
         .          .    974:           }
         .          .    975:
         .          1    976:           errcall, err := fd.acceptOne(s, rawsa[:], o)
         .          .    977:           if err == nil {
         .          .    978:                   return s, rawsa[:], uint32(o.rsan), "", nil
         .          .    979:           }
         .          .    980:
         .          .    981:           // Sometimes we see WSAECONNRESET and ERROR_NETNAME_DELETED is
ROUTINE ======================== net.(*TCPListener).Accept in D:\OwnerSoftwareInstall\Go\src\net\tcpsock.go
         0          1 (flat, cum) 33.33% of Total
         .          .    283:// waits for the next call and returns a generic Conn.
         .          .    284:func (l *TCPListener) Accept() (Conn, error) {
         .          .    285:   if !l.ok() {
         .          .    286:           return nil, syscall.EINVAL
         .          .    287:   }
         .          1    288:   c, err := l.accept()
         .          .    289:   if err != nil {
         .          .    290:           return nil, &OpError{Op: "accept", Net: l.fd.net, Source: nil, Addr: l.fd.laddr, Err: err}
         .          .    291:   }
         .          .    292:   return c, nil
         .          .    293:}


# list `*$ 查看所有函数

7、查看堆情况

$ go tool pprof http://localhost:23300/debug/pprof/heap

# -inuse_space:分析应用程序的常驻内存占用情况
$ go tool pprof -inuse_space http://localhost:23300/debug/pprof/heap

# -alloc_objects: 分析应用程序的内存临时分配情况
$ go tool pprof -alloc_objects http://localhost:23300/debug/pprof/heap

8、web界面

需要安装需安装 Graphviz,下载地址:

https://graphviz.gitlab.io/download/

下载如下安装包:

https://gitlab.com/api/v4/projects/4207231/packages/generic/graphviz-releases/9.0.0/windows_10_cmake_Release_graphviz-install-9.0.0-win64.exe

进入windows命令行界面,输入dot -version,然后按回车,如果显示graphviz的相关版本信息,则安装配置成

功。

启动:

$ go tool pprof -http=:8080 cpu.prof

访问:http://localhost:8080/ui

你可能感兴趣的:(golang,golang)