引言
Go语言中的pprof工具是一个强大的性能分析工具,能够帮助开发者诊断和优化程序性能。本文将详细介绍pprof工具的命令参数,帮助大家充分利用该工具的各种功能,提升Go程序的性能和稳定性。
pprof工具概述
pprof工具用于分析Go程序的性能数据,支持多种格式的输出和多种可视化工具。通过命令参数,可以灵活地控制pprof的输出格式和内容。下面我们将逐一介绍每个命令及其用途。
命令详解
callgrind
callgrind
命令用于生成callgrind格式的图表。callgrind格式主要用于KCachegrind工具,可视化分析函数调用和执行情况。
示例:
sh
(pprof) callgrind
Generating report in profile001.callgraph.out
comments
comments
命令输出所有的profile注释信息,帮助开发者了解和记录性能分析的元数据。
示例:
sh (pprof) comments
disasm
disasm
命令输出带有采样注释的汇编代码列表。此功能对于需要深入了解程序在汇编级别的性能表现非常有用。
示例:
sh
(pprof) disasm net/http.parsePattern
Total: 1MB
ROUTINE ======================== net/http.parsePattern
512.05kB 512.05kB (flat, cum) 50.00% of Total
. . 625ba0: LEAQ 0xfffffeb0(SP), R12 ;pattern.go:84
. . 625ba8: CMPQ R12, 0x10(R14)
. . 625bac: JBE 0x626b66
. . 625bb2: PUSHQ BP
. . 625bb3: MOVQ SP, BP
. . 625bb6: SUBQ $0x1c8, SP
. . 625bbd: MOVQ AX, 0x1d8(SP)
. . 625bc5: MOVQ X15, 0x1c0(SP)
. . 625bcf: MOVB $0x0, 0x47(SP)
. . 625bd4: MOVQ $0x0, 0x88(SP)
. . 625be0: MOVUPS X15, 0xb8(SP)
. . 625be9: TESTQ BX, BX ;pattern.go:85
. . 625bec: JE 0x626143
. . 625bf2: MOVQ BX, 0x1e0(SP)
. . 625bfa: MOVQ AX, 0x1d8(SP)
. . 625c02: MOVQ $0x0, 0x60(SP) ;pattern.go:88
. . 625c0b: MOVUPS X15, 0x190(SP) ;pattern.go:89
. . 625c14: MOVQ $0x0, 0x1a0(SP)
. . 625c20: LEAQ net/http.parsePattern.func1(SB), DX
. . 625c27: MOVQ DX, 0x190(SP)
. . 625c2f: LEAQ 0xb8(SP), DX
. . 625c37: MOVQ DX, 0x198(SP)
dot
dot
命令生成DOT格式的图表。DOT格式是一种图形描述语言,可以用于Graphviz工具,进行复杂的图形可视化。
示例:
sh
(pprof) dot net/http.parsePattern
digraph "app.exe" {
node [style=filled fillcolor="#f8f8f8"]
subgraph cluster_L { "File: app.exe" [shape=box fontsize=16 label="File: app.exe\lBuild ID: C:\\src\\uml\\2024\\05\\18\\app.exe2024-05-18 20:48:58.1691483 +0800 +08\lType: inuse_space\lTime: May 18, 2024 at 9:23pm (+08)\lActive filters:\l focus=net/http.parsePattern\lShowing nodes accounting for 512.05kB, 50.00% of 1024.09kB total\l\lSee https://git.io/JfYMW for how to read the graph\l" tooltip="app.exe"] }
N1 [label="http\nparsePattern\n512.05kB (50.00%)" id="node1" fontsize=24 shape=box tooltip="net/http.parsePattern (512.05kB)" color="#b22100" fillcolor="#edd9d5"]
NN1_0 [label = "96B" id="NN1_0" fontsize=8 shape=box3d tooltip="512.05kB"]
N1 -> NN1_0 [label=" 512.05kB" weight=100 tooltip="512.05kB" labeltooltip="512.05kB"]
N2 [label="runtime\nmain\n0 of 512.05kB (50.00%)" id="node2" fontsize=8 shape=box tooltip="runtime.main (512.05kB)" color="#b22100" fillcolor="#edd9d5"]
N3 [label="http\n(*ServeMux)\nregister\n0 of 512.05kB (50.00%)" id="node3" fontsize=8 shape=box tooltip="net/http.(*ServeMux).register (512.05kB)" color="#b22100" fillcolor="#edd9d5"]
N4 [label="http\n(*ServeMux)\nregisterErr\n0 of 512.05kB (50.00%)" id="node4" fontsize=8 shape=box tooltip="net/http.(*ServeMux).registerErr (512.05kB)" color="#b22100" fillcolor="#edd9d5"]
N5 [label="http\nHandleFunc\n0 of 512.05kB (50.00%)" id="node5" fontsize=8 shape=box tooltip="net/http.HandleFunc (512.05kB)" color="#b22100" fillcolor="#edd9d5"]
N6 [label="pprof\ninit\n0\n0 of 512.05kB (50.00%)" id="node6" fontsize=8 shape=box tooltip="net/http/pprof.init.0 (512.05kB)" color="#b22100" fillcolor="#edd9d5"]
N7 [label="runtime\ndoInit\n0 of 512.05kB (50.00%)" id="node7" fontsize=8 shape=box tooltip="runtime.doInit (512.05kB)" color="#b22100" fillcolor="#edd9d5"]
N8 [label="runtime\ndoInit1\n0 of 512.05kB (50.00%)" id="node8" fontsize=8 shape=box tooltip="runtime.doInit1 (512.05kB)" color="#b22100" fillcolor="#edd9d5"]
N3 -> N4 [label=" 512.05kB" weight=51 penwidth=3 color="#b22100" tooltip="net/http.(*ServeMux).register -> net/http.(*ServeMux).registerErr (512.05kB)" labeltooltip="net/http.(*ServeMux).register -> net/http.(*ServeMux).registerErr (512.05kB)"]
N4 -> N1 [label=" 512.05kB" weight=51 penwidth=3 color="#b22100" tooltip="net/http.(*ServeMux).registerErr -> net/http.parsePattern (512.05kB)" labeltooltip="net/http.(*ServeMux).registerErr -> net/http.parsePattern (512.05kB)"]
N5 -> N3 [label=" 512.05kB\n (inline)" weight=51 penwidth=3 color="#b22100" tooltip="net/http.HandleFunc -> net/http.(*ServeMux).register (512.05kB)" labeltooltip="net/http.HandleFunc -> net/http.(*ServeMux).register (512.05kB)"]
N6 -> N5 [label=" 512.05kB" weight=51 penwidth=3 color="#b22100" tooltip="net/http/pprof.init.0 -> net/http.HandleFunc (512.05kB)" labeltooltip="net/http/pprof.init.0 -> net/http.HandleFunc (512.05kB)"]
N7 -> N8 [label=" 512.05kB" weight=51 penwidth=3 color="#b22100" tooltip="runtime.doInit -> runtime.doInit1 (512.05kB)" labeltooltip="runtime.doInit -> runtime.doInit1 (512.05kB)"]
N8 -> N6 [label=" 512.05kB" weight=51 penwidth=3 color="#b22100" tooltip="runtime.doInit1 -> net/http/pprof.init.0 (512.05kB)" labeltooltip="runtime.doInit1 -> net/http/pprof.init.0 (512.05kB)"]
N2 -> N7 [label=" 512.05kB\n (inline)" weight=51 penwidth=3 color="#b22100" tooltip="runtime.main -> runtime.doInit (512.05kB)" labeltooltip="runtime.main -> runtime.doInit (512.05kB)"]
}
eog
eog
命令通过eog(Eye of GNOME)工具可视化图表。此命令将生成的图表直接在eog中打开。
示例:
sh
(pprof) eog
exec: "eog": executable file not found in %PATH%
evince
evince
命令通过evince工具可视化图表,与eog
类似,但使用的是Evince文档查看器。
示例:
sh
(pprof) evince
exec: "evince": executable file not found in %PATH%
gif
gif
命令生成GIF格式的图像,便于在网页和报告中嵌入性能分析图表。
示例:
sh
(pprof) gif
Generating report in profile001.gif
(pprof) gif net/http.parsePattern
Generating report in profile002.gif
gv
gv
命令通过gv工具可视化图表。gv是一个基于X11的PostScript和PDF查看器。
示例:
sh
(pprof) gv
exec: "gv": executable file not found in %PATH%
kcachegrind
kcachegrind
命令在KCachegrind工具中可视化报告。KCachegrind是一个强大的性能分析工具,特别适用于处理callgrind格式的文件。
示例:
sh
(pprof) kcachegrind
exec: "kcachegrind": executable file not found in %PATH%
list
list
命令输出与正则表达式匹配的函数的注释源代码,帮助开发者直接在源代码级别查看性能瓶颈。
示例:
sh
(pprof) list net/http.parsePattern
Total: 1MB
ROUTINE ======================== net/http.parsePattern in C:\Program Files\Go\src\net\http\pattern.go
512.05kB 512.05kB (flat, cum) 50.00% of Total
. . 84:func parsePattern(s string) (_ *pattern, err error) {
. . 85: if len(s) == 0 {
. . 86: return nil, errors.New("empty pattern")
. . 87: }
. . 88: off := 0 // offset into string
. . 89: defer func() {
. . 90: if err != nil {
. . 91: err = fmt.Errorf("at offset %d: %w", off, err)
. . 92: }
. . 93: }()
. . 94:
. . 95: method, rest, found := strings.Cut(s, " ")
. . 96: if !found {
. . 97: rest = method
. . 98: method = ""
. . 99: }
. . 100: if method != "" && !validMethod(method) {
. . 101: return nil, fmt.Errorf("invalid method %q", method)
. . 102: }
. . 103: p := &pattern{str: s, method: method}
. . 104:
. . 105: if found {
. . 106: off = len(method) + 1
. . 107: }
. . 108: i := strings.IndexByte(rest, '/')
. . 109: if i < 0 {
. . 110: return nil, errors.New("host/path missing /")
. . 111: }
. . 112: p.host = rest[:i]
. . 113: rest = rest[i:]
. . 114: if j := strings.IndexByte(p.host, '{'); j >= 0 {
. . 115: off += j
. . 116: return nil, errors.New("host contains '{' (missing initial '/'?)")
. . 117: }
. . 118: // At this point, rest is the path.
. . 119: off += i
. . 120:
. . 121: // An unclean path with a method that is not CONNECT can never match,
. . 122: // because paths are cleaned before matching.
. . 123: if method != "" && method != "CONNECT" && rest != cleanPath(rest) {
. . 124: return nil, errors.New("non-CONNECT pattern with unclean path can never match")
. . 125: }
. . 126:
. . 127: seenNames := map[string]bool{} // remember wildcard names to catch dups
. . 128: for len(rest) > 0 {
. . 129: // Invariant: rest[0] == '/'.
. . 130: rest = rest[1:]
. . 131: off = len(s) - len(rest)
. . 132: if len(rest) == 0 {
. . 133: // Trailing slash.
. . 134: p.segments = append(p.segments, segment{wild: true, multi: true})
. . 135: break
. . 136: }
. . 137: i := strings.IndexByte(rest, '/')
. . 138: if i < 0 {
. . 139: i = len(rest)
. . 140: }
. . 141: var seg string
. . 142: seg, rest = rest[:i], rest[i:]
. . 143: if i := strings.IndexByte(seg, '{'); i < 0 {
. . 144: // Literal.
. . 145: seg = pathUnescape(seg)
512.05kB 512.05kB 146: p.segments = append(p.segments, segment{s: seg})
. . 147: } else {
. . 148: // Wildcard.
. . 149: if i != 0 {
. . 150: return nil, errors.New("bad wildcard segment (must start with '{')")
. . 151: }
pdf
命令生成PDF格式的图表,便于打印和分享。
示例:
sh
(pprof) pdf net/http.parsePattern
Generating report in profile001.pdf
peek
peek
命令输出与正则表达式匹配的函数的调用者和被调用者信息。
示例:
sh
(pprof) peek <regexp>
(pprof) peek net/http.parsePattern
Showing nodes accounting for 1024.09kB, 100% of 1024.09kB total
----------------------------------------------------------+-------------
flat flat% sum% cum cum% calls calls% + context
----------------------------------------------------------+-------------
512.05kB 100% | net/http.(*ServeMux).registerErr
512.05kB 50.00% 50.00% 512.05kB 50.00% | net/http.parsePattern
----------------------------------------------------------+-------------
png
png
命令生成PNG格式的图像,与GIF类似,但适用于需要高质量静态图像的场景。
示例:
sh
(pprof) png net/http.parsePattern
Generating report in profile001.png
proto
proto
命令以压缩protobuf格式输出profile数据。这种格式适用于数据交换和存储。
示例:
sh
(pprof) proto net/http.parsePattern
Generating report in profile001.pb.gz
ps
ps
命令生成PostScript格式的图表,便于高质量打印。
示例:
sh
(pprof) ps net/http.parsePattern
Generating report in profile001.ps
raw
raw
命令输出原始profile数据的文本表示,用于深入分析或自定义处理。
示例:
sh
(pprof) raw net/http.parsePattern
PeriodType: space bytes
Period: 524288
Time: 2024-05-18 21:23:27.8127791 +0800 +08
Samples:
alloc_objects/count alloc_space/bytes inuse_objects/count inuse_space/bytes
5461 524336 5461 524336: 23 24 25 26 27 28
bytes:[96]
Locations
1: 0x860205 M=1 net/textproto.readMIMEHeader C:/Program Files/Go/src/net/textproto/reader.go:571 s=487
2: 0x8a948d M=1 net/textproto.(*Reader).ReadMIMEHeader C:/Program Files/Go/src/net/textproto/reader.go:482 s=481
net/http.readRequest C:/Program Files/Go/src/net/http/request.go:1105 s=1051
3: 0x8b0927 M=1 net/http.(*conn).readRequest C:/Program Files/Go/src/net/http/server.go:1004 s=975
4: 0x8b4c18 M=1 net/http.(*conn).serve C:/Program Files/Go/src/net/http/server.go:1964 s=1888
5: 0x7f11b3 M=1 net.(*conn).Read C:/Program Files/Go/src/net/net.go:181 s=175
6: 0x8aeef6 M=1 net/http.(*connReader).backgroundRead C:/Program Files/Go/src/net/http/server.go:681 s=680
7: 0x6efe2c M=1 sync.runtime_notifyListWait C:/Program Files/Go/src/runtime/sema.go:554 s=544
8: 0x70f0c4 M=1 sync.(*Cond).Wait C:/Program Files/Go/src/sync/cond.go:70 s=66
9: 0x8af0e5 M=1 net/http.(*connReader).abortPendingRead C:/Program Files/Go/src/net/http/server.go:729 s=720
10: 0x8b4266 M=1 net/http.(*response).finishRequest C:/Program Files/Go/src/net/http/server.go:1671 s=1659
11: 0x8b4f0a M=1 net/http.(*conn).serve C:/Program Files/Go/src/net/http/server.go:2045 s=1888
12: 0x86a0af M=1 compress/flate.newDeflateFast C:/Program Files/Go/src/compress/flate/deflatefast.go:64 s=63
compress/flate.(*compressor).init C:/Program Files/Go/src/compress/flate/deflate.go:585 s=568
13: 0x873fa5 M=1 compress/flate.NewWriter C:/Program Files/Go/src/compress/flate/deflate.go:667 s=665
compress/gzip.(*Writer).Write C:/Program Files/Go/src/compress/gzip/gzip.go:191 s=139
14: 0x8fb558 M=1 runtime/pprof.(*profileBuilder).build C:/Program Files/Go/src/runtime/pprof/proto.go:390 s=348
15: 0x8f7444 M=1 runtime/pprof.profileWriter C:/Program Files/Go/src/runtime/pprof/pprof.go:863 s=845
16: 0x873f8c M=1 compress/flate.NewWriter C:/Program Files/Go/src/compress/flate/deflate.go:666 s=665
compress/gzip.(*Writer).Write C:/Program Files/Go/src/compress/gzip/gzip.go:191 s=139
17: 0x8f71ce M=1 runtime/pprof.StartCPUProfile C:/Program Files/Go/src/runtime/pprof/pprof.go:833 s=811
18: 0x9028e6 M=1 net/http/pprof.Profile C:/Program Files/Go/src/net/http/pprof/pprof.go:149 s=133
19: 0x8b6288 M=1 net/http.HandlerFunc.ServeHTTP C:/Program Files/Go/src/net/http/server.go:2166 s=2165
20: 0x8b810c M=1 net/http.(*ServeMux).ServeHTTP C:/Program Files/Go/src/net/http/server.go:2683 s=2669
21: 0x8b914d M=1 net/http.serverHandler.ServeHTTP C:/Program Files/Go/src/net/http/server.go:3137 s=3128
22: 0x8b4ec7 M=1 net/http.(*conn).serve C:/Program Files/Go/src/net/http/server.go:2039 s=1888
23: 0x8a631d M=1 net/http.parsePattern C:/Program Files/Go/src/net/http/pattern.go:146 s=84
24: 0x8b8335 M=1 net/http.(*ServeMux).registerErr C:/Program Files/Go/src/net/http/server.go:2748 s=2737
25: 0x8b81cf M=1 net/http.(*ServeMux).register C:/Program Files/Go/src/net/http/server.go:2732 s=2731
net/http.HandleFunc C:/Program Files/Go/src/net/http/server.go:2727 s=2723
26: 0x901e84 M=1 net/http/pprof.init.0 C:/Program Files/Go/src/net/http/pprof/pprof.go:95 s=93
27: 0x6ccdcc M=1 runtime.doInit1 C:/Program Files/Go/src/runtime/proc.go:7176 s=7147
28: 0x6be4c6 M=1 runtime.doInit C:/Program Files/Go/src/runtime/proc.go:7143 s=7141
runtime.main C:/Program Files/Go/src/runtime/proc.go:253 s=146
svg
svg
命令生成SVG格式的图像,适用于需要矢量图形的场景,如网页嵌入和缩放显示。
示例:
sh (pprof) svg Generating report in profile001.svg
tags
tags
命令输出profile中的所有标签信息,帮助开发者了解和筛选性能数据。
示例:
sh
(pprof) tags
bytes: Total 1.0MB
1.0MB ( 100%): 96B
0.0B ( 0%): 128kB
0.0B ( 0%): 136kB
0.0B ( 0%): 352B
0.0B ( 0%): 648kB
0.0B ( 0%): 80B
text
text
命令以文本形式输出主要的性能数据条目,便于快速查看和分析。
示例:
sh
(pprof) text
Showing nodes accounting for 1024.09kB, 100% of 1024.09kB total
Showing top 10 nodes out of 13
flat flat% sum% cum cum%
512.05kB 50.00% 50.00% 512.05kB 50.00% net/http.parsePattern
512.05kB 50.00% 100% 512.05kB 50.00% sync.runtime_notifyListWait
0 0% 100% 512.05kB 50.00% net/http.(*ServeMux).register (inline)
0 0% 100% 512.05kB 50.00% net/http.(*ServeMux).registerErr
0 0% 100% 512.05kB 50.00% net/http.(*conn).serve
0 0% 100% 512.05kB 50.00% net/http.(*connReader).abortPendingRead
0 0% 100% 512.05kB 50.00% net/http.(*response).finishRequest
0 0% 100% 512.05kB 50.00% net/http.HandleFunc
0 0% 100% 512.05kB 50.00% net/http/pprof.init.0
0 0% 100% 512.05kB 50.00% runtime.doInit
top
top
命令以文本形式输出性能数据的主要条目,类似于Linux中的top
命令,帮助开发者快速定位性能热点。
示例:
sh
(pprof) top
Showing nodes accounting for 1024.09kB, 100% of 1024.09kB total
Showing top 10 nodes out of 13
flat flat% sum% cum cum%
512.05kB 50.00% 50.00% 512.05kB 50.00% net/http.parsePattern
512.05kB 50.00% 100% 512.05kB 50.00% sync.runtime_notifyListWait
0 0% 100% 512.05kB 50.00% net/http.(*ServeMux).register (inline)
0 0% 100% 512.05kB 50.00% net/http.(*ServeMux).registerErr
0 0% 100% 512.05kB 50.00% net/http.(*conn).serve
0 0% 100% 512.05kB 50.00% net/http.(*connReader).abortPendingRead
0 0% 100% 512.05kB 50.00% net/http.(*response).finishRequest
0 0% 100% 512.05kB 50.00% net/http.HandleFunc
0 0% 100% 512.05kB 50.00% net/http/pprof.init.0
0 0% 100% 512.05kB 50.00% runtime.doInit
topproto
topproto
命令以压缩protobuf格式输出主要的性能数据条目,结合了top
和proto
命令的功能。
示例:
sh (pprof) topproto Generating report in profile002.pb.gz
traces
traces
命令以文本形式输出所有的profile样本数据,适用于详细的逐样本分析。
示例:
sh (pprof) traces net/http.parsePattern File: app.exe Build ID: C:\src\uml\2024\05\18\app.exe2024-05-18 20:48:58.1691483 +0800 +08 Type: inuse_space Time: May 18, 2024 at 9:23pm (+08) -----------+------------------------------------------------------- bytes: 96B 512.05kB net/http.parsePattern net/http.(*ServeMux).registerErr net/http.(*ServeMux).register (inline) net/http.HandleFunc net/http/pprof.init.0 runtime.doInit1 runtime.doInit (inline) runtime.main -----------+-------------------------------------------------------
tree
tree
命令以文本形式输出调用图,帮助开发者以树形结构查看函数调用关系。
示例:
sh
(pprof) tree net/http.parsePattern
Active filters:
focus=net/http.parsePattern
Showing nodes accounting for 512.05kB, 50.00% of 1024.09kB total
----------------------------------------------------------+-------------
flat flat% sum% cum cum% calls calls% + context
----------------------------------------------------------+-------------
512.05kB 100% | net/http.(*ServeMux).registerErr
512.05kB 50.00% 50.00% 512.05kB 50.00% | net/http.parsePattern
----------------------------------------------------------+-------------
512.05kB 100% | net/http.HandleFunc (inline)
0 0% 50.00% 512.05kB 50.00% | net/http.(*ServeMux).register
512.05kB 100% | net/http.(*ServeMux).registerErr
----------------------------------------------------------+-------------
512.05kB 100% | net/http.(*ServeMux).register
0 0% 50.00% 512.05kB 50.00% | net/http.(*ServeMux).registerErr
512.05kB 100% | net/http.parsePattern
----------------------------------------------------------+-------------
512.05kB 100% | net/http/pprof.init.0
0 0% 50.00% 512.05kB 50.00% | net/http.HandleFunc
512.05kB 100% | net/http.(*ServeMux).register (inline)
----------------------------------------------------------+-------------
512.05kB 100% | runtime.doInit1
0 0% 50.00% 512.05kB 50.00% | net/http/pprof.init.0
512.05kB 100% | net/http.HandleFunc
----------------------------------------------------------+-------------
512.05kB 100% | runtime.main (inline)
0 0% 50.00% 512.05kB 50.00% | runtime.doInit
512.05kB 100% | runtime.doInit1
----------------------------------------------------------+-------------
512.05kB 100% | runtime.doInit
0 0% 50.00% 512.05kB 50.00% | runtime.doInit1
512.05kB 100% | net/http/pprof.init.0
----------------------------------------------------------+-------------
0 0% 50.00% 512.05kB 50.00% | runtime.main
512.05kB 100% | runtime.doInit (inline)
----------------------------------------------------------+-------------
web
web
命令通过默认的网页浏览器可视化图表,使得性能分析结果更易于共享和展示。
示例:
sh (pprof) web
weblist
weblist
命令在网页浏览器中显示带注释的源代码,与list
命令类似,但提供了更友好的界面。
示例:
sh (pprof) weblist
结论
通过pprof工具的丰富命令,Go语言开发者可以全面地分析和优化程序性能。本文详细介绍了每个命令及其用途,希望能帮助大家更好地利用pprof工具,提高程序的效率和稳定性。通过合理运用这些命令和选项,我们可以深入了解程序的性能瓶颈,制定有效的优化策略,为用户提供更高质量的应用程序。