Go: 深入探讨pprof工具,全面解读

引言
Go语言中的pprof工具是一个强大的性能分析工具,能够帮助开发者诊断和优化程序性能。本文将详细介绍pprof工具的命令参数,帮助大家充分利用该工具的各种功能,提升Go程序的性能和稳定性。

pprof工具概述
pprof工具用于分析Go程序的性能数据,支持多种格式的输出和多种可视化工具。通过命令参数,可以灵活地控制pprof的输出格式和内容。下面我们将逐一介绍每个命令及其用途。
命令详解
callgrind
callgrind命令用于生成callgrind格式的图表。callgrind格式主要用于KCachegrind工具,可视化分析函数调用和执行情况。
示例:
sh
(pprof) callgrindGenerating report in profile001.callgraph.out
comments
comments命令输出所有的profile注释信息,帮助开发者了解和记录性能分析的元数据。
示例:
sh
(pprof) comments
disasm
disasm命令输出带有采样注释的汇编代码列表。此功能对于需要深入了解程序在汇编级别的性能表现非常有用。
示例:
sh
(pprof) disasm net/http.parsePatternTotal: 1MBROUTINE ======================== 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.parsePatterndigraph "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="httpparsePattern512.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="runtimemain0 of 512.05kB (50.00%)" id="node2" fontsize=8 shape=box tooltip="runtime.main (512.05kB)" color="#b22100" fillcolor="#edd9d5"]N3 [label="http(*ServeMux)register0 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(*ServeMux)registerErr0 of 512.05kB (50.00%)" id="node4" fontsize=8 shape=box tooltip="net/http.(*ServeMux).registerErr (512.05kB)" color="#b22100" fillcolor="#edd9d5"]N5 [label="httpHandleFunc0 of 512.05kB (50.00%)" id="node5" fontsize=8 shape=box tooltip="net/http.HandleFunc (512.05kB)" color="#b22100" fillcolor="#edd9d5"]N6 [label="pprofinit00 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="runtimedoInit0 of 512.05kB (50.00%)" id="node7" fontsize=8 shape=box tooltip="runtime.doInit (512.05kB)" color="#b22100" fillcolor="#edd9d5"]N8 [label="runtimedoInit10 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 (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 (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) eogexec: "eog": executable file not found in %PATH%
evince
evince命令通过evince工具可视化图表,与eog类似,但使用的是Evince文档查看器。
示例:
sh
(pprof) evinceexec: "evince": executable file not found in %PATH%
gif
gif命令生成GIF格式的图像,便于在网页和报告中嵌入性能分析图表。
示例:
sh
(pprof) gifGenerating report in profile001.gif(pprof) gif net/http.parsePatternGenerating report in profile002.gif
gv
gv命令通过gv工具可视化图表。gv是一个基于X11的PostScript和PDF查看器。
示例:
sh
(pprof) gvexec: "gv": executable file not found in %PATH%
kcachegrind
kcachegrind命令在KCachegrind工具中可视化报告。KCachegrind是一个强大的性能分析工具,特别适用于处理callgrind格式的文件。
示例:
sh
(pprof) kcachegrindexec: "kcachegrind": executable file not found in %PATH%
list
list命令输出与正则表达式匹配的函数的注释源代码,帮助开发者直接在源代码级别查看性能瓶颈。
示例:
sh
(pprof) list net/http.parsePatternTotal: 1MBROUTINE ======================== net/http.parsePattern in C:\Program Files\Go\srcet\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命令生成PDF格式的图表,便于打印和分享。
示例:
sh
(pprof) pdf net/http.parsePatternGenerating report in profile001.pdf
peek
peek命令输出与正则表达式匹配的函数的调用者和被调用者信息。
示例:
sh
(pprof) peek <regexp>(pprof) peek net/http.parsePatternShowing 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.parsePatternGenerating report in profile001.png
proto
proto命令以压缩protobuf格式输出profile数据。这种格式适用于数据交换和存储。
示例:
sh
(pprof) proto net/http.parsePatternGenerating report in profile001.pb.gz
ps
ps命令生成PostScript格式的图表,便于高质量打印。
示例:
sh
(pprof) ps net/http.parsePatternGenerating report in profile001.ps
raw
raw命令输出原始profile数据的文本表示,用于深入分析或自定义处理。
示例:
sh
(pprof) raw net/http.parsePatternPeriodType: space bytesPeriod: 524288Time: 2024-05-18 21:23:27.8127791 +0800 +08Samples: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) svgGenerating 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) textShowing nodes accounting for 1024.09kB, 100% of 1024.09kB totalShowing 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) topShowing nodes accounting for 1024.09kB, 100% of 1024.09kB totalShowing 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) topprotoGenerating report in profile002.pb.gz
traces
traces命令以文本形式输出所有的profile样本数据,适用于详细的逐样本分析。
示例:
sh
(pprof) traces net/http.parsePatternFile: app.exeBuild ID: C:\src\uml\2024\05\18\app.exe2024-05-18 20:48:58.1691483 +0800 +08Type: inuse_spaceTime: 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.parsePatternActive filters: focus=net/http.parsePatternShowing 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工具,提高程序的效率和稳定性。通过合理运用这些命令和选项,我们可以深入了解程序的性能瓶颈,制定有效的优化策略,为用户提供更高质量的应用程序。
到顶部