准备工作
-
在对 go 的性能进行分析之前,我们需要做一些准备工作,具体如下
image.png
在代码中嵌入性能分析的 API
![](https://img.haomeiwen.com/i13450341/a8b5c472847d2a42.png)
- 你可以分析程序在执行时的 CPU
- 你可以分析内存
- 还有很多内容,你都可以选择监控
package main
import (
"log"
"math/rand"
"os"
"runtime/pprof"
"time"
)
const (
col = 10000
row = 10000
)
func fillMatrix(m *[row][col]int) {
s := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < row; i++ {
for j := 0; j < col; j++ {
m[i][j] = s.Intn(100000)
}
}
}
func calculate(m *[row][col]int) {
for i := 0; i < row; i++ {
tmp := 0
for j := 0; j < col; j++ {
tmp += m[i][j]
}
}
}
func main() {
//创建输出文件
f, err := os.Create("cpu.prof") // 创建一个文件句柄,这个会收集程序在执行的时候的 CPU 状态
if err != nil {
log.Fatal("could not create CPU profile: ", err)
}
// 获取系统信息
if err := pprof.StartCPUProfile(f); err != nil { // 监控开始
log.Fatal("could not start CPU profile: ", err)
}
defer pprof.StopCPUProfile() // 在程序结束的时候结束监控
// 主逻辑区,进行一些简单的代码运算
x := [row][col]int{}
fillMatrix(&x)
calculate(&x)
f1, err := os.Create("mem.prof") // 做一个句柄,用于收集程序的内存状态
if err != nil {
log.Fatal("could not create memory profile: ", err)
}
//runtime.GC() // GC,获取最新的数据信息
if err := pprof.WriteHeapProfile(f1); err != nil { // 写入内存信息
log.Fatal("could not write memory profile: ", err)
}
f1.Close() // 关闭内存监控
f2, err := os.Create("goroutine.prof") // 打开一个句柄,用于收集其他信息
if err != nil {
log.Fatal("could not create groutine profile: ", err)
}
if gProf := pprof.Lookup("goroutine"); gProf == nil { // 使用 lookup 可以选择你想要监控的类型,这里选择的是协程
log.Fatal("could not write groutine profile: ")
} else {
gProf.WriteTo(f2, 0)
}
f2.Close()
}
- 如果你想了解其他可以监控的内容,可以在下面寻找
![](https://img.haomeiwen.com/i13450341/2d3c811a8093c846.png)
- go build prof.go 创建二进制文件
- 执行这个二进制文件,在目录中会出现相关的分析文件
- 使用 go tool pprof pro xxx.prof ,可以进入相关文件的控制台
- 在控制台中,使用 top 、list 等命令可以查看详细内容
- 使用 svg 可以生成图,你可以用浏览器打开
使用火炬图 go-torch
- 在目录下使用 go-torch xxx.prof ,可以生成火炬图
使用 http 持续监控
![](https://img.haomeiwen.com/i13450341/86b7d19707ff6e8d.png)
- 使用斐波那契数列的代码作为例子
package main
import (
"fmt"
"log"
"net/http"
_ "net/http/pprof"
)
func GetFibonacciSerie(n int) []int {
ret := make([]int, 2, n)
ret[0] = 1
ret[1] = 1
for i := 2; i < n; i++ {
ret = append(ret, ret[i-2]+ret[i-1])
}
return ret
}
func index(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Welcome!"))
}
func createFBS(w http.ResponseWriter, r *http.Request) {
var fbs []int
for i := 0; i < 1000000; i++ {
fbs = GetFibonacciSerie(50)
}
w.Write([]byte(fmt.Sprintf("%v", fbs)))
}
func main() {
http.HandleFunc("/", index)
http.HandleFunc("/fb", createFBS)
log.Fatal(http.ListenAndServe(":8081", nil))
}
- 你只需要 run 这个文件,然后可以正常访问他
- 进入 http://127.0.0.1:8081/debug/pprof/ 可以进入一个新能分析的网页
- 如果你觉得这样并不好,可以使用命令 go tool pprof http://127.0.0.1:8081/debug/pprof/profile,这样会分析接下来三十秒之内的新能变化
- 使用 go-torch http://127.0.0.1:8801/debug/pprof/profile 可以生成火炬图
网友评论