企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] go中提供了pprof包来做代码的性能监控,在两个地方有包: * net/http/pprof * runtime/pprof 其实net/http/pprof中只是使用runtime/pprof包来进行封装了一下,并在http端口上暴露出来 ~~~ #web服务器: import ( "net/http" _ "net/http/pprof" ) #一般应用程序(实际应用无web交互) import ( "net/http" _ "runtime/pprof" ) ~~~ # 使用 net/http/pprof 做WEB服务器的性能监控 如果你的go程序是用http包启动的web服务器,想要查看自己的web服务器的状态。这个时候就可以选择net/http/pprof。 ~~~ import _ "net/http/pprof" ~~~ 然后就可以在浏览器中使用http://localhost:port/debug/pprof/ 直接看到当前web服务的状态,包括CPU占用情况和内存使用情况等。 当然,非WEB的也可以用下面方式启动WEB。 在 main 方法中增加 ~~~ func main() {     go func() {         http.ListenAndServe("localhost:6060", nil)     }() ~~~ ![](https://box.kancloud.cn/71f311da85b2a3abcf80eb071174d337_356x266.png) # CPU消耗分析 **使用 runtime/pprof 做应用程序性能监控** 关键代码: ~~~ import  "runtime/pprof" func main() {     f, err := os.OpenFile("./tmp/cpu.prof", os.O_RDWR|os.O_CREATE, 0644)     if err != nil {         log.Fatal(err)     }     defer f.Close()     pprof.StartCPUProfile(f)     defer pprof.StopCPUProfile() ~~~ 注意,有时候 defer f.Close(), defer pprof.StopCPUProfile() 会执行不到,这时候我们就会看到 prof 文件是空的, 我们需要在自己代码退出的地方,增加上下面两行,确保写文件内容了。 ~~~ pprof.StopCPUProfile() f.Close() ~~~ # 对产生的文件进行分析: 我们可以使用 go tool pprof (应用程序) (应用程序的prof文件) 方式来对这个 prof 文件进行分析。 ~~~ $ go tool pprof HuaRongDao ./tmp/cpu.prof Entering interactive mode (type "help" for commands) (pprof) ~~~ 一些常用 pprof 的命令: # top 在默认情况下,top命令会输出以本地取样计数为顺序的列表。我们可以把这个列表叫做本地取样计数排名列表。 ~~~ (pprof) top 2700ms of 3200ms total (84.38%) Dropped 58 nodes (cum <= 16ms) Showing top 10 nodes out of 111 (cum >= 80ms)       flat  flat%   sum%        cum   cum%      670ms 20.94% 20.94%      670ms 20.94%  runtime.mach\_semaphore\_signal      580ms 18.12% 39.06%      590ms 18.44%  runtime.cgocall      370ms 11.56% 50.62%      370ms 11.56%  runtime.mach\_semaphore\_wait      360ms 11.25% 61.88%      360ms 11.25%  runtime.memmove      210ms  6.56% 68.44%      580ms 18.12%  golang.org/x/mobile/gl.(\*context).DoWork      120ms  3.75% 72.19%      120ms  3.75%  runtime.usleep      110ms  3.44% 75.62%      110ms  3.44%  image/png.filterPaeth      100ms  3.12% 78.75%      160ms  5.00%  compress/flate.(\*decompressor).huffSym      100ms  3.12% 81.88%      100ms  3.12%  image/draw.drawNRGBASrc       80ms  2.50% 84.38%       80ms  2.50%  runtime.memclr (pprof) ~~~ 参考:[https://github.com/hyper-carrot/go\_command\_tutorial/blob/master/0.12.md](https://github.com/hyper-carrot/go_command_tutorial/blob/master/0.12.md "https://github.com/hyper-carrot/go_command_tutorial/blob/master/0.12.md")  默认情况下top命令会列出前10项内容。但是如果在top命令后面紧跟一个数字,那么其列出的项数就会与这个数字相同 # web 与gv命令类似,web命令也会用图形化的方式来显示概要文件。但不同的是,web命令是在一个Web浏览器中显示它。如果你的Web浏览器已经启动,那么它的显示速度会非常快。如果想改变所使用的Web浏览器,可以在Linux下设置符号链接/etc/alternatives/gnome-www-browser或/etc/alternatives/x-www-browser,或在OS X下改变SVG文件的关联Finder。 mac 下 修改默认打开方式: 右键一个想处理的文件,按alt 键(lion)出现always open with,然后打开,整个过程中, 先右键,然后一直按 alt, 一直到打开为止 ![](https://box.kancloud.cn/177413990fa2d80b70794c904d6b27e8_759x426.png) 参考资料: go tool pprof [https://github.com/hyper-carrot/go\_command\_tutorial/blob/master/0.12.md](https://github.com/hyper-carrot/go_command_tutorial/blob/master/0.12.md "https://github.com/hyper-carrot/go_command_tutorial/blob/master/0.12.md")  Go的pprof使用 [http://www.cnblogs.com/yjf512/archive/2012/12/27/2835331.html](http://www.cnblogs.com/yjf512/archive/2012/12/27/2835331.html "http://www.cnblogs.com/yjf512/archive/2012/12/27/2835331.html")  Profiling Go Programs [https://blog.golang.org/profiling-go-programs](https://blog.golang.org/profiling-go-programs "https://blog.golang.org/profiling-go-programs") # 内存泄漏或消耗分析 关键代码 ~~~ fm, err := os.OpenFile("./tmp/mem.out", os.O_RDWR|os.O_CREATE, 0644) if err != nil {     log.Fatal(err) } pprof.WriteHeapProfile(fm) fm.Close() ~~~ 在我们需要生成当时的内存情况时,只需要执行上面代码即可。 触发的条件可以通过 http 的一个接口,或者退出时,或者接收到某个特殊信号,这些逻辑就需要自己实现了。 分析方法,跟之上CPU的分析方法一致 ![](https://box.kancloud.cn/9d485d5531680fcdfbfe4f64733f4b84_608x350.png) \[golang\]内存不断增长bytes.makeSlice [http://studygolang.com/articles/2763](http://studygolang.com/articles/2763 "http://studygolang.com/articles/2763") # graphviz可视化 下面是一个使用pprof长时间运行的例子: ![](https://box.kancloud.cn/99c7e1874b7bae84627548fa7bab9581_655x307.png) pprof能够借助grapgviz产生程序的调用图。默认情况下pprof基于对程序的30秒采样产生调用图。 * 图中的连线代表对方法的调用, 连线上的标签代表指定的方法调用的采样值(译者注:go tool pprof显示的是调用时间)。 * 方框的大小与方法运行的采样值的大小有关。 * 每个方框由两个标签:一个是方法运行的时间占比,一个是它在采样的堆栈中出现的时间占比(译者注: 前者你可以看成flat时间,后者看成cumulate时间) **在Mac上安装工具**: ~~~ brew install gperftools$ brew install graphviz ~~~ ~~~ pprof --web localhost:6060/debug ~~~ 我并没有使用上面的工具,因为Go开发环境已经集成了pprof工具,所以你不需要安装gperftools工具,而且使用的命令和上面的命令不一样。 当然graphviz是必装的。 你可以通过下面的命令采集30s的数据并生成SVG调用图: ~~~ go tool pprof -web http://127.0.0.1:6060/debug/pprof/profile ~~~ Heap profile: ~~~ go tool pprof --text http://localhost:8080/debug/pprof/heap ~~~ CPU profile: ~~~ go tool pprof --text http://localhost:8080/debug/pprof/profile ~~~ Goroutine blocking profile: ~~~ go tool pprof --text http://localhost:8080/debug/pprof/block ~~~ # go-torch 和pprof一样,它也采用30秒的采样数据生成火焰图。 * 栈帧(Stack frame,调用链)垂直堆叠,显示栈的深度 * 帧的宽度代表一个方法的运行的时间占比 * 如果一个方法被调用者调用,它会显示多次,分列在不同的调用者的堆栈上。(译者注:这点和pprof工具不同,pprof至显示一个方法的框,上面的时间标签是所有的调用者调用的时间) * 颜色是任意的(arbitrary), 横坐标根据字母顺序排列 需要安装go-torch工具和brandangregg的火焰图生成脚本: ~~~ go get github.com/uber/go-torch git clone git@github.com:brendangregg/FlameGraph.git export PATH-$PATH:/path/to/FlameGraph go-torch --file "torch.svg" --url http://localhost:6060 ~~~