初入golang pprof
pprof 是 Go 语言中一个用来检查和分析程序性能的工具。通过它,你可以看到你的程序在运行时,CPU、内存、goroutine 等资源的使用情况,从而找出可能的问题,比如程序变慢、内存消耗过大,或者是某些地方的代码阻塞等。
1. allocs(内存分配):
- 这个报告告诉你,程序中哪些地方分配了内存(比如创建了变量、数组等)。它记录了程序过去的所有内存分配情况,帮助你找到是否有不必要的内存分配,或者是否内存泄漏。
2. block(阻塞):
- 当程序的某个部分因为等待锁、等待同步等原因被暂停时,就会发生阻塞。这个报告帮助你查找程序中哪些地方因为等待某些资源而阻塞了执行(比如一个 goroutine 等待另一个 goroutine 完成)。
3. cmdline(命令行):
- 这个报告会显示你启动程序时用的命令行参数。这对于调试程序的启动方式有帮助。
4. goroutine(协程):
- Go 程序是通过goroutine来并发执行任务的。这个报告显示了所有正在运行的 goroutine 的信息,包括它们在做什么、运行到哪里了。如果加上某些参数,它甚至会显示出 goroutine 在崩溃时的详细堆栈信息,这有助于分析程序出错时的状态。
5. heap(堆内存):
- 这个报告展示了程序中所有活跃的内存对象(比如内存中的数据结构等)。它告诉你这些对象占用了多少内存,可以帮助你发现程序中是否有不再使用但没有释放的内存(即“内存泄漏”)。
6. mutex(锁竞争):
- 当多个 goroutine 需要访问同一个资源时,就会使用锁来保证只有一个 goroutine 可以访问该资源。这个报告会告诉你哪些地方存在锁的竞争,可能会导致程序的执行速度变慢。
7. profile(CPU 性能分析):
- 这个报告是用来分析程序的 CPU 使用情况的。它会告诉你程序哪些地方消耗了大量的 CPU 时间,可以帮助你找出程序中性能瓶颈的地方(比如某个循环或函数调用太频繁,占用了太多 CPU)。
8. threadcreate(线程创建):
- 这个报告记录了程序创建新的操作系统线程的情况。当你的程序需要更多的计算资源时,它可能会创建新的线程来执行任务。这个报告可以帮助你了解程序中线程创建的情况,是否有不必要的线程创建。
9. trace(程序执行追踪):
- 这个报告是用来追踪程序执行过程的,能够详细记录程序每一行代码的执行情况。它帮助你看到程序在运行时的“时间轴”,找出哪些部分的代码执行时间过长或者有性能问题。
快速开始
package main  
  
import (  
    "log"  
    "net/http"    "net/http/pprof"    "time")  
  
func workMultiply() {  
    x := 1  
    for {  
       for i := 0; i < 1000; i++ { // 增加循环次数  
          x = x * 2  
          if x > 1000000 {  
             x = 1  
          }  
       }  
    }  
}  
  
func workAdd() {  
    x := 1  
    for {  
       for i := 0; i < 1000; i++ { // 增加循环次数  
          x = x + 1  
          if x > 1000000 {  
             x = 1  
          }  
       }  
    }  
}  
  
func workDivide() {  
    x := 1000000  
    for {  
       x = x / 2  
       if x == 0 {  
          x = 1000000  
       }  
    }  
}  
  
func main() {  
    mux := http.NewServeMux()  //注册路由
    mux.HandleFunc("/debug/pprof/", pprof.Index)  
    mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)  
    mux.HandleFunc("/debug/pprof/profile", pprof.Profile)  
    mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)  
    mux.HandleFunc("/debug/pprof/trace", pprof.Trace)  
    go func() { log.Fatal(http.ListenAndServe(":8080", mux)) }()  
  
    // 启动多个 goroutine,制造负载  
    go workMultiply()  
    go workAdd()  
    go workAdd() // 2个加法,占的CPU多一点  
    go workDivide()  
    go workDivide()  
    go workDivide() // 3个除法,占最多  
  
    time.Sleep(time.Hour)  
}```
接下来我们只需go run 然后访问localhost:8080/debug/pprof即可。
我们会得到这样一个页面:
![[Pasted image 20250427180331.png]]
通过点击对应的蓝色条目,浏览器就会自动为我们下载相应的条目分析数据,默认是采集30s。你可以通过http://localhost:8080/debug/pprof/profile?seconds=xxx来更改默认采集时间,这会为你下载一个二进制文件,那我要怎么分析他呢?
1) 步骤:
1. **运行 `go tool pprof`**:
    
    - 假设你已经下载了 `profile` 文件,接下来在终端运行以下命令
        
        `go tool pprof profile`
        
    
    这时,`go tool pprof` 会进入交互式的命令行界面,让你可以分析这个分析文件。
    
2. **常用命令**:
    
    - **查看函数占用的 CPU 时间**:
        
        `top`
        
        这会列出占用最多 CPU 时间的函数,类似于一个“排名榜”,让你能一眼看到瓶颈。
        
    - **查看函数调用图**(栈图):
        
        `web`
        
        这个命令会生成一个 `.svg` 文件(浏览器可以打开的图像文件),它以图形化的形式展示你的程序中各个函数的调用关系,帮助你更直观地理解哪些函数耗时最多。
        
    - **查看特定函数的调用详情**:
        
        `list 函数名`
        
        这会列出该函数源代码,并标注出哪些行占用了较多的 CPU 时间。
        
    - **退出 `pprof`**: 在命令行输入 `quit` 或 `exit` 就可以退出分析模式。
如图:![[Pasted image 20250427183207.png]]
进阶用法:
```go
package main  
  
import (  
    "os"  
    "runtime/pprof"    "time")  
  
func workMultiply() {  
    x := 1  
    for {  
       for i := 0; i < 1000; i++ { // 增加循环次数  
          x = x * 2  
          if x > 1000000 {  
             x = 1  
          }  
       }  
    }  
}  
  
func workAdd() {  
    x := 1  
    for {  
       for i := 0; i < 1000; i++ { // 增加循环次数  
          x = x + 1  
          if x > 1000000 {  
             x = 1  
          }  
       }  
    }  
}  
  
func workDivide() {  
    x := 1000000  
    for {  
       x = x / 2  
       if x == 0 {  
          x = 1000000  
       }  
    }  
}  
  
func main() {  
  
    // 启动多个 goroutine,制造负载  
    go workMultiply()  
    go workAdd()  
    go workAdd() // 2个加法,占的CPU多一点  
    go workDivide()  
    go workDivide()  
    go workDivide() // 3个除法,占最多  
    f, _ := os.Create("cpu.pprof")  
    pprof.StartCPUProfile(f)  
    time.Sleep(30 * time.Second)  
    pprof.StopCPUProfile()  
}
这会直接把分析数据放在文件。
你还可以下载Graphviz来生成火焰图。
go tool pprof -http=:8081 cpu.pprof 
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号