Loading [MathJax]/jax/input/TeX/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Golang性能诊断

Golang性能诊断

原创
作者头像
iginkgo18
发布于 2022-03-13 03:56:03
发布于 2022-03-13 03:56:03
1.4K00
代码可运行
举报
文章被收录于专栏:devops_k8sdevops_k8s
运行总次数:0
代码可运行

1 简介

我们日常接触性能诊断问题;

一般分为两种情况:

一是线上应用真的出现性能问题、

二是我们需要对准备上线的系统进行性能预估,需要压力测试辅助进行。

针对Go应用,性能诊断工具主要分为两层:

OS层面

Go应用层面(go tool pprof / trace /gc)

2 OS诊断

系统诊断,我们一般关注三个方面: CPU, Memory, I/O。

2.1 CPU

CPU诊断主要关注平均负载(Load Average), CPU使用率,上下文切换(Context Switch), 常用的top命令查看cpu使用率以及服务器负载情况。

平均负载:0.14 0.07 0.06 分别表示过去1分钟、5分钟、15分钟的机器负载的平均值,根据经验,若负载数值小于0.7*CPU个数则正常,超过或者达到CPU核数的四五倍,则系统的负载就明显偏高。

CPU的上下文切换情况可通过vmstat命令可以查看,上下文切换发生的场景有如下几种:

  1. 时间片用完,CPU正常调度下一个任务
  2. 被其他优先级更高的任务抢占
  3. 执行任务碰到I/O阻塞,挂起当前任务,切换到下一个任务
  4. 用户代码主动挂起当前任务让出CPU
  5. 多任务抢占资源,因没抢到而被挂起
  6. 硬件中断

2.2 Memory

从操作系统角度,内存关注应用进程是否足够,可以使用 free –m 命令查看内存的使用情况。

通过 top 命令可以查看进程使用的虚拟内存 VIRT 和物理内存 RES,根据公式 VIRT = SWAP + RES 可以推算出具体应用使用的交换分区(Swap)情况,使用交换分区过大会影响 应用性能,可以将 swappiness 值调到尽可能小。

2.3 I/O

I/O 包括磁盘 I/O 和网络 I/O,一般情况下磁盘更容易出现 I/O 瓶颈。通过iostat可以查看磁盘的读写情况,通过 CPU 的 I/O wait 可以看出磁盘 I/O 是否正常。

如果磁盘 I/O 一直处于很高的状态,说明磁盘太慢或故障,成为了性能瓶颈,需要进行应用优化或者磁盘更换。

除了常用的 top、 ps、vmstat、iostat 等命令,还有其他 Linux 工具可以诊断系统问题,如 mpstat、tcpdump、netstat、pidstat、sar 等 更多Linux性能诊断工具如下图:

3 Go应用诊断

profile一般被称为性能分析,对程序而言,就是程序运行时的各种概况信息,包括cpu占用情况、内存情况、线程情况等。方便分析昂贵或频繁调用的程序场景。

3.1 profiling

如何使用?

1.首先profiling代码埋入

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import _ "net/http/pprof"

func main() {
    go func() {
        log.Println(http.ListenAndServe("0.0.0.0:9090", nil))
    }()
    ...
}

2.保存特定时间点的profile,例如保存heap信息

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
curl http://localhost:6060/debug/pprof/heap --output heap.tar.gz

3.使用go tool pprof 分析保存的profile快照,如分析上述heap信息

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
go tool pprof heap.tar.gz

3.2 CPU Profiling

pprof可以帮忙我们分析出函数执行缓慢问题 CPU占用过高问题

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
go tool pprof http://localhost:6060/debug/pprof/profile?second=10

命令行方式: 常用命令 top list traces

top: 查看按照占用内存或cpu多少排序的前10的函数信息

  • flat:当前函数占用的CPU时长(不包含其调用的其他函数
  • flat%:当前函数使用CPU占总CPU时长的百分比
  • sum%:前面每一行flat百分比的和
  • cum: 累计量,当前函数及其子函数占用CPU时长
  • cum%:累计量占总量的百分比

cum>=flat

list: 查看某个函数的代码 以及该函数每行代码的指标信息

traces:打印所有函数调用栈 以及调用栈的指标信息

UI界面方式:从服务器download下生成的sample文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
go tool pprof -http=:8080 pprof.xxx.samples.cpu.001.pb.gz

Flame graph很清晰得可以看到当前CPU被哪些函数执行栈占用

Heap Profiling

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
go tool pprof http://localhost:6060/debug/pprof/heap?second=10

命令行 UI查看方式 同理

graph中方框越大 占用内存越多 火焰图 宽度越大 占用内存越多

SAMPLE->inuse_objects可以查看当前的对象数量 这个参数对于分析gc线程占用较高cpu时很有用处 它侧重查看对象数量

inuse_space图可以查看具体的内存占用

毕竟对于10个100m的对象和1亿个10字节的对象占用内存几乎一样大,但是回收起来一亿个小对象肯定比10个大对象要慢很多。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
go tool pprof -inuse_space http://localhost:6060/debug/pprof/heap : 分析应用程序的常驻内存占用情况 (默认)
go tool pprof -alloc_objects http://localhost:6060/debug/pprof/heap: 分析应用程序的内存临时分配情况

并发请求问题 查看方式跟上面类似。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
go tool pprof http://localhost:6060/debug/pprof/goroutine
go tool pprof http://localhost:6060/debug/pprof/block
go tool pprof http://localhost:6060/debug/pprof/mutex

3.3 Tracing

trace并不是万能的,它更侧重于记录分析 采样时间内运行时系统具体干了什么。

收集trace数据的三种方式:

1. 使用runtime/trace包 调用trace.Start()和trace.Stop()

2. 使用go test -trace=<file>测试标识

3. 使用debug/pprof/trace handler 获取运行时系统最好的方法

例如,通过

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
go tool pprof http://localhost:6060/debug/pprof/trace?seconds=20 > trace.out

获取运行时服务的trace信息,使用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
go tool trace trace.out

其中trace view 只能使用chrome浏览器查看,这里go截止1.14版本存在一个 bug,解决办法如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
go tool trace trace.out 无法查看trace view
go bug:https://github.com/golang/go/issues/25151
mac 解决版本:安装gotip
go get golang.org/dl/gotip
gotip download
then  使用 gotip tool trace trace.out即可

获取的trace.out 二进制文件也可以转化为pprof格式的文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
go tool trace -pprof=TYPE trace.out > TYPE.pprof
Tips:生成的profile文件 支持 network profiling、synchronization profiling、syscall profiling、scheduler profiling
go tool pprof TYPE.pprof

使用gotip tool trace trace.out可以查看到trace view的丰富操作界面:

操作技巧:

ctrl + 1 选择信息

ctrl + 2 移动选区

ctrl + 3 放大选区

ctrl + 4 指定选区区间

shift + ? 帮助信息

AWSD跟游戏快捷键类似 玩起来跟顺手

整体的控制台信息 如下图:

  • 时间线: 显示执行的时间单元 根据时间的纬度不同 可以调整区间
  • 堆: 显示执行期间内存的分配和释放情况
  • 协程(Goroutine): 显示每个时间点哪些Goroutine在运行 哪些goroutine等待调度 ,其包含 GC 等待(GCWaiting)、可运行(Runnable)、运行中(Running)这三种状态。

goroutine区域选中时间区间

  • 虚拟处理器Processor: 每个虚拟处理器显示一行,虚拟处理器的数量一般默认为系统内核数。数量由环境变量GOMAXPROCS控制
  • 协程和事件: 显示在每个虚拟处理器上有什么 Goroutine 正在运行,而连线行为代表事件关联。

每个Processor分两层,上一层表示Processor上运行的goroutine的信息,下一层表示processor附加的事件比如SysCall 或runtime system events

ctrl+3 放大选区,选中goroutine 可以查看,特定时间点 特定goroutine的执行堆栈信息以及关联的事件信息

点击goroutine的id 可以跳到trace view 详细查看goroutine具体干了什么

名称

含义

Execution

执行时间

Network wait

网络等待时间

Sync Block

同步阻塞时间

Blocking syscall

系统调用阻塞时间

Scheduler wait

调度等待时间

GC Sweeping

GC清扫时间

GC Pause

GC暂停时间

实践 一个延迟问题诊断

当我们一个执行关键任务的协程从运行中被阻塞。这里可能的原因:被syscall阻塞 、阻塞在共享内存(channel/mutex etc)、阻塞在运行时(如 GC)、甚至有可能是运行时调度器不工作导致的。这种问题使用pprof很难排查,

使用trace只要我们确定了时间范围就可以在proc区域很容易找到问题的源头

上图可见,GC 的MARK阶段阻塞了主协程的运行

3.4 GC

golang的gc算法是根据标记清除改进的三色标记法,大概流程:

初始所有对象都是白色

  1. Stack scan阶段:从root出发扫描所有可达对象,标记为灰色并放入待处理队列;root包括全局指针和goroutine栈上的指针
  2. Mark阶段:1.从待处理队列取出灰色对象,将其引用的对象标记为灰色并放入队列,自身标记为黑色 2. re-scan全局指针和栈,因为mark和用户程序并行运行,故过程1的时候可能会有新的对象分配,这时需要通过写屏障(write barrier)记录下来;re-scan再完成检查;
  3. 重复步骤Mark阶段,直到灰色对象队列为空,执行清扫工作(白色即为垃圾对象)

go的三色标记法也存在STW(Stop The World),大致有两个场景

  1. GC即将开始时,需要STW 做一些准备工作, 如enable write barrier
  2. re-scan也需要STW,否则上面Mark阶段的re-scan无法终止

通过GODEBUG=gctrace=1可以开启gc日志,查看gc的结果信息

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ GODEBUG=gctrace=1 go run main.go   
gc 1 @0.001s 19%: 0.014+3.7+0.015 ms clock, 0.11+2.8/5.7/3.2+0.12 ms cpu, 5->6->6 MB, 6 MB goal, 8 P
gc 2 @0.024s 6%: 0.004+3.4+0.010 ms clock, 0.032+1.4/4.5/5.3+0.085 ms cpu, 13->14->13 MB, 14 MB goal, 8 P
gc 3 @0.093s 3%: 0.004+6.1+0.027 ms clock, 0.032+0.19/11/15+0.22 ms cpu, 24->25->22 MB, 26 MB goal, 8 P
scvg: 0 MB released
scvg: inuse: 4, idle: 58, sys: 63, released: 58, consumed: 4 (MB)
scvg: 0 MB released
scvg: inuse: 4, idle: 58, sys: 63, released: 58, consumed: 4 (MB)
scvg: 0 MB released
scvg: inuse: 4, idle: 58, sys: 63, released: 58, consumed: 4 (MB)
scvg: 0 MB released
scvg: inuse: 4, idle: 58, sys: 63, released: 58, consumed: 4 (MB)

格式

gc # @#s #%: #+#+# ms clock, #+#/#/#+# ms cpu, #->#-># MB, # MB goal, # P

含义

gc#:GC 执行次数的编号,每次叠加。

@#s:自程序启动后到当前的具体秒数。

#%:自程序启动以来在GC中花费的时间百分比。

#+...+#:GC 的标记工作共使用的 CPU 时间占总 CPU 时间的百分比。

#->#-># MB:分别表示 GC 启动时, GC 结束时, GC 活动时的堆大小.

#MB goal:下一次触发 GC 的内存占用阈值。

#P:当前使用的处理器 P 的数量。

4 扩展

当我们的程序陷入CPU 和IO混和负载过高时,我们使用pprof profile只能检测出CPU耗时的函数,但是屏蔽了IO等待过长的函数。

https://github.com/felixge/fgprof 给出了一个解决方案:

https://github.com/felixge/fgprof 给出了一个解决方案:neProfile,返回的结果忽略了协程当时消耗CPU还是非消耗CPU的区别 进行统计,保存在内存中的map中,可导出转化为pprof

具体用法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main
 
import(
    _ "net/http/pprof"
    "github.com/felixge/fgprof"
)
 
func main() {
    http.DefaultServeMux.Handle("/debug/fgprof", fgprof.Handler())
    go func() {
        log.Println(http.ListenAndServe(":6060", nil))
    }()
 
    // <code to profile>
}
 
git clone https://github.com/brendangregg/FlameGraph
cd FlameGraph
curl -s 'localhost:6060/debug/fgprof?seconds=3' > fgprof.fold
./flamegraph.pl fgprof.fold > fgprof.svg

如果遇到这种CPU消耗型和非CPU消耗型混合的情况下 可以试试排查下。

文章来源于光华路程序猿 ,作者Leo

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
golang性能诊断看这篇就够了
我们日常接触性能诊断问题,一般分为两种情况,一是线上应用真的出现性能问题;二是我们需要对准备上线的系统进行性能预估;后者需要压力测试辅助进行,此处不表。
用户3904122
2022/06/29
1.8K0
golang性能诊断看这篇就够了
Go语言之性能分析工具pprof
pprof:是Go的性能分析工具,在程序运行过程中,可以记录程序的运行信息,可以是CPU使用情况、内存使用情况、goroutine运行情况等,Go语言已经将pprof 封装在包net/http/pprof中。
灰子学技术
2020/04/02
2.5K0
Golang 大杀器之性能剖析 PProf
想要进行性能优化,首先瞩目在 Go 自身提供的工具链来作为分析依据,本文将带你学习、使用 Go 后花园,涉及如下:
前端教程
2018/10/25
2.4K0
Golang 大杀器之性能剖析 PProf
记一次线上GoLang项目OOM排查过程
在Go语言中使用了gin web框架,我们有一个接口是文件下载服务,用户下载超过100M文件就会OOM导致重启服务,本文主要记录通过Golang内置的pprof服务来排查OOM问题的过程。
莲子心
2025/07/14
650
Golang使用pprof监控性能及GC调优
作者:峰云就她了 链接:http://xiaorui.cc/?p=3000 來源:个人博客 共 8809 字,阅读需 22 分钟 这两天用golang在写一个监控的agent,发现长时间运行后会有内存
李海彬
2018/07/26
4K0
Golang使用pprof监控性能及GC调优
浅谈pprof
对于大多数 Gopher 而言,一般平时最主要的工作内容除了实现各种无聊的业务逻辑之外,剩下的就是解决各种琐碎的问题。比如:查询性能瓶颈在哪里?查询内存泄漏在哪里?好在 pprof 是处理此类问题的利器,共有两套标准库,分别适用于不同的场景:
LA0WAN9
2021/12/14
8370
浅谈pprof
Go GC 20 问
本文作者欧长坤,德国慕尼黑大学在读博士,Go/etcd/Tensorflow contributor,开源书籍《Go 语言原本》作者,《Go 夜读》SIG 成员/讲师,对 Go 有很深的研究。Github:@changkun,https://changkun.de。
梦醒人间
2020/02/13
1.4K0
Go GC 20 问
实战Go内存泄露
最近解决了我们项目中的一个内存泄露问题,事实再次证明pprof是一个好工具,但掌握好工具的正确用法,才能发挥好工具的威力,不然就算你手里有屠龙刀,也成不了天下第一,本文就是带你用pprof定位内存泄露问题。
大彬
2019/05/28
5.2K0
从0到1上手硬核性能分析(多图文)
有个服务调用了底层的lua脚本库,最后导致机器疯狂扩容,翻了3倍左右,cpu负载很高,当流量上涨时cpu可以达到60%以上,平均都在35%以上。
公众号guangcity
2022/04/27
3200
从0到1上手硬核性能分析(多图文)
从实例出发,深入理解pprof原理与应用
内存泄漏是指在计算机程序中,由于程序未能正确释放已经申请的内存空间,导致系统的可用内存持续减少,最终可能导致程序性能下降甚至崩溃的问题。
Michel_Rolle
2023/12/11
3.1K9
Golang程序性能分析(一)pprof和go-torch
最近计划用三篇文章讲述一下Golang应用性能分析,本文是第一篇,先来介绍Go语言自带的性能分析库pprof怎么使用,后面两篇会讲解怎么用pprof对Echo或者Gin框架开发的应用进行性能分析以及如何使用pprof对gRPC 服务进行性能分析。
KevinYan
2020/11/26
1.2K1
go pprof实战
1 为什么要进行性能优化 1.1 哪些情况需要进行性能优化 其实关于性能优化的主题,网上已经讨论很多次,这里谈一下我的理解,那么其实核心就是2个点: 服务一直高负载,业务增长需要经常扩容 架构不能满足业务发展,需要重构,与此同时需要进行服务的压测&性能优化 1.2 性能优化的一般步骤 准备阶段:发现系统性能问题,明确优化方向 分析阶段:通过各种工具和手段,初步定位瓶颈点 调优阶段:根据定位到的瓶颈点,进行性能调优 测试阶段:实际验证调优效果,如果不能满足期望要求,那么可能需要重复2-3步骤(如果还不行可能
QQ音乐技术团队
2021/05/14
1.9K0
每个程序员都应该掌握的Golang性能优化秘技
Golang 作为一门“现代化”的语言,原生就包含了强大的性能分析工具 pprof 和 trace。pprof 工具常用于分析资源的使用情况,可以采集程序运行时的多种不同类型的数据(例如 CPU 占用、内存消耗和协程数量等),并对数据进行分析聚合生成的报告。trace 工具则关注程序运行时的事件(例如协程状态切换,GC 的开始和结束、系统调用等等),常用于分析延迟、阻塞和调度等问题。掌握了这两个工具就足以满足大部分 Golang 程序的性能分析需求。
腾讯云开发者
2024/05/22
2.1K0
每个程序员都应该掌握的Golang性能优化秘技
Golang pprof 性能问题分析优化和实战经验
Go 自带了一个 pprof 的性能优化和分析的工具,这个工具包括 cpuprof 、memprof ,并且还提供了 Lookup 功能用于获取堆状态信息、线程状态信息、 goroutine 状态信息等。官方的博客有一篇文章介绍用法:《Profiling Go Programs》[1]
Allen.Wu
2023/03/01
3K0
Golang pprof 性能问题分析优化和实战经验
性能分析工具
profiling这词比较难翻译,有译成画像,我将其译为资料收集、剖析研究, 用于对程序指标或特征的分析,很多软件中都内置或有第三方的profiling工具,如Linux(比较知名的如Perf),MySQL,JAVA,Go等。
fliter
2023/06/18
7320
性能分析工具
go的性能分析:pprof工具
pprof是GoLang程序性能分析工具,prof是profile(画像)的缩写 .通过pprof,我们可以得到程序执行的以下数据:
仙士可
2022/11/28
2.5K0
go的性能分析:pprof工具
Golang程序性能分析
程序性能分析我相信是每个程序员都会遇到的问题,比如说一个程序的CPU为什么占用这么高?有没有优化的空间?又比如程序出现了内存泄漏如何排查等等。如果是C++程序会借助于Google pprof c++ profile,java程序会依赖于jstack等工具,幸运的是Golang语言本身就集成了性能分析工具pprof包,可以有效的分析程序CPU,MEM,Metux等指标。其中还可以通过第三方图形应用来更加直观的显示每个调用关系和指标占用情况。
用户2937493
2019/09/11
2.1K0
Golang程序性能分析
Go语言中常见100问题-#98 Not using Go diagnostics tooling
Go语言提供了一些优秀的分析工具,可以帮助我们定位程序的性能问题。本文关注最关键的两个工具:pprof和trace。pprof和trace都是Go语言自带的性能分析工具,pprof可以采集内存分配、goroutine等信息,使用trace可以分析并发、阻塞事件以及GC情况。
数据小冰
2024/02/23
2710
Go语言中常见100问题-#98 Not using Go diagnostics tooling
go pprof使用
工欲善其事必先利其器, java 中有 async-profile、 arthas、jstack/jmap/jstat 等一系列工具来辅助排查性能问题
leobhao
2024/04/01
2250
Golang包——pprof
pprof 是用于可视化和分析性能分析数据的工具 CPU Profiling:CPU 分析,按照一定的频率采集所监听的应用程序 CPU(含寄存器)的使用情况,可确定应用程序在主动消耗 CPU 周期时花费时间的位置 Memory Profiling:内存分析,在应用程序进行堆分配时记录堆栈跟踪,用于监视当前和历史内存使用情况,以及检查内存泄漏 Block Profiling:阻塞分析,记录 goroutine 阻塞等待同步(包括定时器通道)的位置 Mutex Profiling:互斥锁分析,报告互斥锁的竞争情况
羊羽shine
2019/05/29
5340
相关推荐
golang性能诊断看这篇就够了
更多 >
交个朋友
加入HAI高性能应用服务器交流群
探索HAI应用新境界 共享实践心得
加入云原生工作实战群
云原生落地实践 技术难题攻坚探讨
加入腾讯云技术交流站
洞悉AI新动向 Get大咖技术交流群
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档