要监控Go程序的堆栈,CPU的耗时等性能信息,我们可以通过使用pprof包来实现。在代码中,pprof包有两种方式导入:
"net/http/pprof"
"runtime/prof"
其实net/http/pprof中只是使用runtime/pprof包来进行封装了一下,并在http端口上暴露出来,让我们可以在浏览器查看程序的性能分析。我们可以自行查看net/http/pprof中代码,只有一个文件pprof.go。
下面我们具体说说怎么使用pprof,首先我们讲讲在开发中取得pprof信息的三种方式:
一:Web 服务器程序
如果我们的Go程序是Web服务器,你想查看自己的Web服务器的状态。这个时候就可以选择net/http/pprof。你只需要引入包_"net/http/pprof",然后就可以在浏览器中使用http://localhost:port/debug/pprof/直接看到当前Web服务的状态,包括CPU占用情况和内存使用情况等。
这里port是8080,也就是我们Web服务器监听的端口。
package main
import (
"fmt"
"net/http"
_ "net/http/pprof" // 为什么用_ , 在讲解http包时有解释。
)
func myfunc(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hi")
}
func main() {
http.HandleFunc("/", myfunc)
http.ListenAndServe(":8080", nil)
}
访问http://localhost:8080/debug/pprof/
二:服务进程
如果你的Go程序不是Web服务器,而是一个服务进程,可以选择使用net/http/pprof包,然后开启一个goroutine来监听相应端口。
package main
import (
"fmt"
"log"
"net/http"
_ "net/http/pprof"
"time"
)
func main() {
// 开启pprof
go func() {
log.Println(http.ListenAndServe("localhost:8080", nil))
}()
go hello()
select {}
}
func hello() {
for {
go func() {
fmt.Println("hello word")
}()
time.Sleep(time.Millisecond * 1)
}
}
访问http://localhost:8080/debug/pprof/ 在前面这两种方式中,我们还可以在命令行分别运行以下命令:
- 利用这个命令查看堆栈信息:
go tool pprof http://localhost:8080/debug/pprof/heap
- 利用这个命令可以查看程序CPU使用情况信息:
go tool pprof http://localhost:8080/debug/pprof/profile
- 使用这个命令可以查看block信息:
go tool pprof http://localhost:8080/debug/pprof/block
这里需要先安装graphviz,http://www.graphviz.org/download/ ,windows平台直接下载zip包,解压缩后把bin目录放到 $path
中。我们可以通过执行命令 png 产生图片,还有svg,gif,pdf等命令,生成的图片自动命名存放在当前目录下,我们这里生成了png。其他命令使用可通过help查看。
三:应用程序
如果你的Go程序只是一个应用程序,那么你就不能使用net/http/pprof包了,你就需要使用到runtime/pprof。比如下面的例子:
package main
import (
"flag"
"fmt"
"log"
"os"
"runtime/pprof"
"time"
)
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
func Factorial(n uint64) (result uint64) {
if n > 0 {
result = n * Factorial(n-1)
return result
}
return 1
}
func main() {
flag.Parse()
if *cpuprofile != "" {
f, err := os.Create(*cpuprofile)
if err != nil {
log.Fatal(err)
}
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
}
go compute()
time.Sleep(10 * time.Second)
}
func compute() {
for i := 0; i < 100; i++ {
go func() {
fmt.Println(Factorial(uint64(40)))
}()
time.Sleep(time.Millisecond * 1)
}
}
编译后生成3.exe文件并运行:
3.exe --cpuprofile=cpu.prof
这里我们编译后可执行程序是3.exe , 程序运行完后的CPU信息就会记录到cpu.prof中。现在有了cpu.prof 文件,我们就可以通过go tool pprof 来看相应的信息了。在命令行运行:
go tool pprof 3.exe cpu.prof
这里要注意的是需要带上可执行的程序名以及prof信息文件。命令执行后会进入到:
命令界面和前面两种使用net/http/pprof包 一样。我们可以通过go tool pprof 生svg,png或者是pdf文件。
这是生成的png文件,和前面生成的png类似,前面我们生成的是block信息:
通过上面这三种情况的分析,我们可以知道,其实就是两种情况: go tool pprof http://localhost:8080/debug/pprof/profile
这种url方式,或者 go tool pprof 3.exe cpu.prof
这种文件方式来进行分析。
我们可以根据项目情况灵活使用。有关pprof,我们就讲这么多,在实际项目中,我们多使用就会发现这个工具还是蛮有用处的。