当前位置: 首页 > news >正文

【go】pprof 性能分析

前言

go pprof是 Go 语言提供的性能分析工具。它可以帮助开发者分析 Go 程序的性能问题,包括 CPU 使用情况、内存分配情况、阻塞情况等。

主要功能

CPU 性能分析

go pprof可以对程序的 CPU 使用情况进行分析。它通过在一定时间内对程序的执行进行采样,记录每个函数被调用的次数和执行时间。通过分析这些采样数据,可以确定程序中哪些函数占用了较多的 CPU 时间,从而帮助开发者找到性能瓶颈并进行优化。

例如,使用go tool pprof命令加上程序的 CPU 性能分析文件,可以启动一个交互式的分析界面。在这个界面中,可以使用各种命令查看不同函数的 CPU 使用情况,如top命令可以显示占用 CPU 时间最多的函数列表。

内存性能分析

这个工具可以分析程序的内存分配情况。它可以记录程序在运行过程中每个函数分配的内存大小和数量。通过分析这些数据,可以确定程序中哪些函数可能存在内存泄漏或过度分配内存的问题。

例如,使用go tool pprof命令加上程序的内存性能分析文件,可以查看内存分配的情况。可以使用list命令查看特定函数的内存分配情况,或者使用web命令生成一个可视化的内存分配报告。

阻塞分析

go pprof还可以分析程序中的阻塞情况。它可以检测程序在哪些地方出现了阻塞,如等待锁、通道通信或系统调用等。通过分析阻塞情况,可以帮助开发者找到程序中的并发问题并进行优化。

例如,使用go tool pprof命令加上程序的阻塞分析文件,可以查看程序中的阻塞情况。可以使用top命令查看最常见的阻塞点,或者使用list命令查看特定函数的阻塞情况。

优势

易于使用

go pprof是 Go 语言内置的工具,无需安装额外的软件即可使用。它的使用方法相对简单,只需要在程序中添加几行代码就可以生成性能分析文件,然后使用go tool pprof命令进行分析。

强大的分析功能

go pprof提供了丰富的分析功能,可以分析程序的 CPU 使用情况、内存分配情况、阻塞情况等。它还可以生成可视化的报告,帮助开发者更直观地了解程序的性能问题。

与 Go 语言紧密集成

由于go pprof是 Go 语言内置的工具,它与 Go 语言的其他工具和库紧密集成。例如,可以使用go test命令结合-cpuprofile-memprofile参数来生成性能分析文件,方便在测试过程中进行性能分析。

CPU profiling

pprof 使用非常简单。首先调用pprof.StartCPUProfile()启用 CPU profiling。它接受一个io.Writer类型的参数,pprof会将分析结果写入这个io.Writer中。为了方便事后分析,我们写到一个文件中。

在要分析的代码后调用pprof.StopCPUProfile()。那么StartCPUProfile()StopCPUProfile()之间的代码执行情况都会被分析。方便起见可以直接在StartCPUProfile()后,用defer调用StopCPUProfile(),即分析这之后的所有代码。

来个普通的demo,后面内存分析也用这段代码

import ("math/rand""os""runtime/pprof""strings""time"
)func generate(n int) []int {nums := make([]int, 0)for i := 0; i < n; i++ {nums = append(nums, rand.Int())}return nums
}func bubbleSort(nums []int) {for i := 0; i < len(nums); i++ {for j := 1; j < len(nums)-i; j++ {if nums[j] < nums[j-1] {nums[j], nums[j-1] = nums[j-1], nums[j]}}}
}type A struct {b *B
}type B struct {c *C
}type C struct {
}func (a *A) func_a() {a.b.func_b()
}func (b *B) func_b() {b.c.func_c()
}func (c *C) func_c() {nums := generate(10000)bubbleSort(nums)
}

使用 pprof 分析一下运行情况

func main() {f, _ := os.OpenFile("cpu.pprof", os.O_CREATE|os.O_RDWR, 0644)defer f.Close()pprof.StartCPUProfile(f)defer pprof.StopCPUProfile()a := &A{b: &B{c: &C{},},}a.func_a()time.Sleep(time.Second)
}

执行go run main.go,会生成一个cpu.pprof文件。这个文件记录了程序的运行状态。使用go tool pprof命令分析这个文件:

>> go tool pprof cpu.pprof            
File: pprof2
Type: cpu
Time: Sep 11, 2024 at 5:40pm (CST)
Duration: 202.37ms, Total samples = 70ms (34.59%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 70ms, 100% of 70ms totalflat  flat%   sum%        cum   cum%70ms   100%   100%       70ms   100%  main.bubbleSort (inline)0     0%   100%       70ms   100%  main.(*A).func_a (inline)0     0%   100%       70ms   100%  main.(*B).func_b (inline)0     0%   100%       70ms   100%  main.(*C).func_c0     0%   100%       70ms   100%  main.main0     0%   100%       70ms   100%  runtime.main
(pprof) 

list 分析

上面用top命令查看耗时最高的 10 个函数。可以看到bubbleSort函数耗时最高,累计耗时 70ms,占了总耗时的 100%。我们也可以使用top 5top 20分别查看耗时最高的 5 个 和 20 个函数。

当找到耗时较多的函数,我们还可以使用list命令查看该函数是怎么被调用的,各个调用路径上的耗时是怎样的。list命令后跟一个表示方法名的模式:

(pprof) list bubbleSort
Total: 50ms
ROUTINE ======================== main.bubbleSort in /Users/jasper/work/gitee/test-go/src/pprof/pprof2.go50ms       50ms (flat, cum)   100% of Total.          .     58:   return nums.          .     59:}10ms       10ms     60:func bubbleSort(nums []int) {40ms       40ms     61:   for i := 0; i < len(nums); i++ {.          .     62:           for j := 1; j < len(nums)-i; j++ {.          .     63:                   if nums[j] < nums[j-1] {.          .     64:                           nums[j], nums[j-1] = nums[j-1], nums[j].          .     65:                   }.          .     66:           }
(pprof) %                                                

help 查看所有的命令

(pprof) helpCommands:callgrind        Outputs a graph in callgrind formatcomments         Output all profile commentsdisasm           Output assembly listings annotated with samplesdot              Outputs a graph in DOT formateog              Visualize graph through eogevince           Visualize graph through evincegif              Outputs a graph image in GIF formatgv               Visualize graph through gvkcachegrind      Visualize report in KCachegrindlist             Output annotated source for functions matching regexppdf              Outputs a graph in PDF formatpeek             Output callers/callees of functions matching regexppng              Outputs a graph image in PNG formatproto            Outputs the profile in compressed protobuf formatps               Outputs a graph in PS formatraw              Outputs a text representation of the raw profilesvg              Outputs a graph in SVG formattags             Outputs all tags in the profiletext             Outputs top entries in text formtop              Outputs top entries in text formtopproto         Outputs top entries in compressed protobuf formattraces           Outputs all profile samples in text formtree             Outputs a text rendering of call graphweb              Visualize graph through web browserweblist          Display annotated source in a web browsero/options        List options and their current valuesq/quit/exit/^D   Exit pprofOptions:call_tree        Create a context-sensitive call treecompact_labels   Show minimal headersdivide_by        Ratio to divide all samples before visualizationdrop_negative    Ignore negative differencesedgefraction     Hide edges below <f>*totalfocus            Restricts to samples going through a node matching regexphide             Skips nodes matching regexpignore           Skips paths going through any nodes matching regexpintel_syntax     Show assembly in Intel syntaxmean             Average sample value over first value (count)nodecount        Max number of nodes to shownodefraction     Hide nodes below <f>*totalnoinlines        Ignore inlines.normalize        Scales profile based on the base profile.output           Output filename for file-based outputsprune_from       Drops any functions below the matched frame.relative_percentages Show percentages relative to focused subgraphsample_index     Sample value to report (0-based index or name)show             Only show nodes matching regexpshow_from        Drops functions above the highest matched frame.source_path      Search path for source filestagfocus         Restricts to samples with tags in range or matched by regexptaghide          Skip tags matching this regexptagignore        Discard samples with tags in range or matched by regexptagleaf          Adds pseudo stack frames for labels key/value pairs at the callstack leaf.tagroot          Adds pseudo stack frames for labels key/value pairs at the callstack root.tagshow          Only consider tags matching this regexptrim             Honor nodefraction/edgefraction/nodecount defaultstrim_path        Path to trim from source paths before searchunit             Measurement units to displayOption groups (only set one per group):granularity      functions        Aggregate at the function level.filefunctions    Aggregate at the function level.files            Aggregate at the file level.lines            Aggregate at the source code line level.addresses        Aggregate at the address level.sort             cum              Sort entries based on cumulative weightflat             Sort entries based on own weight:   Clear focus/ignore/hide/tagfocus/tagignoretype "help <cmd|option>" for more information
(pprof) 

web 模式查看

在浏览器中分析CPU性能数据

go tool pprof -http=:8081 cpu.pprof

image

火焰图
image

Memory profiling

上面的CPU分析,内容换成字符串拼接

func (c *C) func_c() {concat(30000)
}const letterBytes = "abcdefghijklmnopqrstuvwxyz"func randomString(n int) string {b := make([]byte, n)for i := range b {b[i] = letterBytes[rand.Intn(len(letterBytes))]}return string(b)
}func concat(n int) string {var s = ""for i := 0; i < n; i++ {s += randomString(100)}return s
}

func main() {f, _ := os.OpenFile("mem.pprof", os.O_CREATE|os.O_RDWR, 0644)defer f.Close()a := &A{b: &B{c: &C{},},}a.func_a()pprof.WriteHeapProfile(f)time.Sleep(time.Second)
}

分析

分析的过程,与上面的CPU部分类似

>> go tool pprof mem.pprof
File: pprof2
Type: inuse_space
Time: Sep 11, 2024 at 5:55pm (CST)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top 
Showing nodes accounting for 674.18kB, 100% of 674.18kB totalflat  flat%   sum%        cum   cum%674.18kB   100%   100%   674.18kB   100%  main.concat0     0%   100%   674.18kB   100%  main.(*A).func_a (inline)0     0%   100%   674.18kB   100%  main.(*B).func_b (inline)0     0%   100%   674.18kB   100%  main.(*C).func_c (inline)0     0%   100%   674.18kB   100%  main.main0     0%   100%   674.18kB   100%  runtime.main
(pprof) list concat
Total: 674.18kB
ROUTINE ======================== main.concat in /Users/jasper/work/gitee/test-go/src/pprof/pprof2.go674.18kB   674.18kB (flat, cum)   100% of Total.          .     46:func concat(n int) string {.          .     47:   var s = "".          .     48:   for i := 0; i < n; i++ {674.18kB   674.18kB     49:           s += randomString(100).          .     50:   }.          .     51:   return s.          .     52:}.          .     53:.          .     54:func generate(n int) []int {
(pprof) 

+做字符串拼接是很耗内存的,各位可以试着用strings.Builder,然后观察内存占用的变化。

web 模式查看

在浏览器中分析CPU性能数据

go tool pprof -http=:8081 mem.pprof

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 什么是CPU、GPU、NPU?(包懂+会)
  • 为什么eBay的防IP关联很重要?
  • react | 自学笔记 | 持续更新
  • 深拷贝与数据扁平化封装打开即用
  • java --- 性能优化01
  • Linux:体系结构和操作系统管理
  • Flutter的升级和降级步骤
  • QMT软件怎么申请开通?QMT软件到底是谁在用啊?QMT量化软件K线驱动介绍
  • tensor连接和拆分
  • 搜维尔科技:ART光学空间定位虚拟交互工业级光学跟踪系统
  • sourcetree配置ssh连接gitee
  • 中国企业500强!最新名单揭晓→
  • JavaScript高级进阶(二)
  • IGNAV_NHC分析
  • 【深度学习】训练过程中一个OOM的问题,太难查了
  • 《Javascript高级程序设计 (第三版)》第五章 引用类型
  • 0x05 Python数据分析,Anaconda八斩刀
  • Angular4 模板式表单用法以及验证
  • Angular6错误 Service: No provider for Renderer2
  • CAP 一致性协议及应用解析
  • css的样式优先级
  • ES6系统学习----从Apollo Client看解构赋值
  • miniui datagrid 的客户端分页解决方案 - CS结合
  • mysql常用命令汇总
  • Nodejs和JavaWeb协助开发
  • PHP变量
  • Python代码面试必读 - Data Structures and Algorithms in Python
  • XML已死 ?
  • 从零开始的webpack生活-0x009:FilesLoader装载文件
  • 第十八天-企业应用架构模式-基本模式
  • 京东美团研发面经
  • 悄悄地说一个bug
  • 消息队列系列二(IOT中消息队列的应用)
  • 哈罗单车融资几十亿元,蚂蚁金服与春华资本加持 ...
  • ​数据结构之初始二叉树(3)
  • #在 README.md 中生成项目目录结构
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (Java入门)抽象类,接口,内部类
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (纯JS)图片裁剪
  • (分享)一个图片添加水印的小demo的页面,可自定义样式
  • (附源码)ssm高校升本考试管理系统 毕业设计 201631
  • (附源码)基于SSM多源异构数据关联技术构建智能校园-计算机毕设 64366
  • (含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
  • (十) 初识 Docker file
  • (十)c52学习之旅-定时器实验
  • (四)【Jmeter】 JMeter的界面布局与组件概述
  • (四)c52学习之旅-流水LED灯
  • (一)认识微服务
  • ****三次握手和四次挥手
  • ***监测系统的构建(chkrootkit )
  • .NET 8 中引入新的 IHostedLifecycleService 接口 实现定时任务
  • .NET 使用 XPath 来读写 XML 文件
  • .NET开源项目介绍及资源推荐:数据持久层 (微软MVP写作)
  • :not(:first-child)和:not(:last-child)的用法