使用go pprof进行golang程序内存分析

news2025/8/7 14:47:34

引言

日常项目,有时会出现oom的情况,这时候我们光依靠code review进行问题定位是很困难的。这里我们需要一个排查工具,来定位是哪里的代码导致内存溢出的,这个工具就是pprof

前提

如果是非http(s)服务类的,需要在代码中嵌入如下几行代码
import _ "net/http/pprof"

go func() {
    http.ListenAndServe("0.0.0.0:8899", nil)
}()

如果是http(s)类的的服务,可以添加上所使用的pprof第三方库,如gin

import "github.com/gin-contrib/pprof"

//StartHttp 新建HTTP服务
func StartHttp() error {
	router := gin.New()
	...
	pprof.Register(router)
	
	addr := fmt.Sprintf(":%d", 8899)
	if err := router.Run(addr); err != nil {
		return err
	}
	return nil
}

使用

在浏览器中输入http://ip:8899/debug/pprof/可以看到一个汇总页面
在这里插入图片描述
其中heap项是我们需要关注的信息,可以点进去看下,但信息比较分散,没啥大用
在这里插入图片描述
更有用的信息我们需要借助go tool pprof来进行分析

go tool pprof -alloc_space/-inuse_space http://ip:8899/debug/pprof/heap
# 注意 -alloc_space 和 -inuse_space 是两个可选项, 选一个

这里有两个选项,-alloc_space和-inuse_space,从名字应该能看出二者的区别,不过条件允许的话,我们优先使用-inuse_space来分析,因为直接分析导致问题的现场比分析历史数据肯定要直观的多,一个函数alloc_space多不一定就代表它会导致进程的RSS高,因为我们比较幸运可以在线下复现这个OOM的场景,所以直接用-inuse_space

进入后是一个交互界面

输入top命令可以前10大的内存分配
like this

(pprof) top
Showing nodes accounting for 3.73GB, 99.78% of 3.74GB total
Dropped 5 nodes (cum <= 0.02GB)
Showing top 10 nodes out of 16
      flat  flat%   sum%        cum   cum%
    3.70GB 98.94% 98.94%     3.70GB 98.94%  bytes.makeSlice /usr/local/go/src/bytes/buffer.go
    0.03GB  0.83% 99.78%     0.03GB  0.83%  main.(*cmdRestore).Main /usr/local/go/src/bufio/bufio.go
         0     0% 99.78%     3.70GB 98.94%  bytes.(*Buffer).Write /usr/local/go/src/bytes/buffer.go
         0     0% 99.78%     3.70GB 98.94%  bytes.(*Buffer).grow /usr/local/go/src/bytes/buffer.go
         0     0% 99.78%     3.70GB 98.94%  github.com/CodisLabs/redis-port/pkg/rdb.(*Loader).NextBinEntry go_workspace/src/github.com/CodisLabs/redis-port/pkg/rdb/loader.go
         0     0% 99.78%     3.70GB 98.94%  github.com/CodisLabs/redis-port/pkg/rdb.(*rdbReader).Read go_workspace/src/github.com/CodisLabs/redis-port/pkg/rdb/reader.go
         0     0% 99.78%     3.70GB 98.94%  github.com/CodisLabs/redis-port/pkg/rdb.(*rdbReader).ReadBytes go_workspace/src/github.com/CodisLabs/redis-port/pkg/rdb/reader.go
         0     0% 99.78%     3.70GB 98.94%  github.com/CodisLabs/redis-port/pkg/rdb.(*rdbReader).ReadString go_workspace/src/github.com/CodisLabs/redis-port/pkg/rdb/reader.go
         0     0% 99.78%     3.70GB 98.94%  github.com/CodisLabs/redis-port/pkg/rdb.(*rdbReader).readFull go_workspace/src/github.com/CodisLabs/redis-port/pkg/rdb/reader.go
         0     0% 99.78%     3.70GB 98.94%  github.com/CodisLabs/redis-port/pkg/rdb.(*rdbReader).readObjectValue go_workspace/src/github.com/CodisLabs/redis-port/pkg/rdb/reader.go

top + num 可以指定前几
然后使用tree $num $target找到主要占用内存的调用关系,找到最终代码位置

在这里插入图片描述

指标

allocs:查看过去所有内存分配的样本。
block:查看导致阻塞同步的堆栈跟踪。
cmdline: 当前程序的命令行的完整调用路径。
goroutine:查看当前所有运行的 goroutines 堆栈跟踪。
heap:查看活动对象的内存分配情况。
mutex:查看导致互斥锁的竞争持有者的堆栈跟踪。
profile: 默认进行 30s 的 CPU Profiling,得到一个分析用的 profile 文件。
threadcreate:查看创建新 OS 线程的堆栈跟踪。
trace:略,trace可以单独写一篇文章来介绍。

注意,默认情况下是不追踪block和mutex的信息的,如果想要看这两个信息,需要在代码中加上两行:

runtime.SetBlockProfileRate(1) // 开启对阻塞操作的跟踪,block  
runtime.SetMutexProfileFraction(1) // 开启对锁调用的跟踪,mutex

flat flat%

一个函数内的directly操作的物理耗时。例如

func foo(){
    a()                                        // step1
    largeArray := [math.MaxInt64]int64{}       // step2
    for i := 0; i < math.MaxInt64; i++ {       // step3
            c()                                    // step4
    }
}

flat只会记录step2和step3的时间;flat%即是flat/总运行时间。内存等参数同理。

所有的flat相加即是总采样时间,所有的flat%相加应该等于100%。

flat一般是我们最关注的。其代表一个函数可能非常耗时,或者调用了非常多次,或者两者兼而有之,从而导致这个函数消耗了最多的时间。

如果是我们自己编写的代码,则很可能有一些无脑for循环、复杂的计算、字符串操作、频繁申请内存等等。

如果是第三方库的代码,则很可能我们过于频繁地调用了这些第三方库,或者以不正确的方式使用了这些第三方库。

cum cum%

相比flat,cum则是这个函数内所有操作的物理耗时,比如包括了上述的step1、2、3、4。

cum%即是cum的时间/总运行时间。内存等参数同理。

一般cum是我们次关注的,且需要结合flat来看。flat可以让我们知道哪个函数耗时多,而cum可以帮助我们找到是哪些函数调用了这些耗时的(flat值大的)函数。

sum%

其上所有行的flat%的累加。可以视为,这一行及其以上行,其所有的directly操作一共占了多少物理时间。

参考资料

https://zhuanlan.zhihu.com/p/396363069
https://developer.aliyun.com/article/573743

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/15543.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于PHP+MySQL的宠物领养救助社交网站

当前很多的宠物被抛弃和虐杀,它们没有选择权,我们强制性的把狗带进人类的生活中,然后又无情的抛弃,让它们无家可归,变成流浪狗,它们做错了什么&#xff1f;流浪动物被主人遗弃之后居无定所,时刻面对着严寒、酷暑、生病、死亡,饥饿、等一系列威胁它们生命的存在为了能够让这些。…

BlenderGIS插件 城市建筑3D模型自动生成 教程

目录 一、下载Blender和BlenderGIS 二、解决 No imaging library...报错 三、生成城市3D模型 四、导出模型 本文所需文件可在如下链接下载&#xff0c;或者直接按照博文下载步骤下载 https://download.csdn.net/download/ChaoChao66666/87071901?spm1001.2014.3001.550…

Node的Web编程

一、node的事件处理 1、node采用的事件驱动模式来进行事件处理的&#xff1a;只有当事件被触发时才执行相关程序 2、node是单线程运行的&#xff1a;采用事件轮询方式&#xff0c;不断的查询事件队列中的消息&#xff0c;然后根据消息执行对应的回调函数 3、node事件机制中的…

ASEMI代理艾赛斯DSP25-12A,整流二极管DSP25-12A

编辑-Z 艾赛斯整流二极管DSP25-12A参数&#xff1a; 型号&#xff1a;DSP25-12A 最大重复反向阻断电压&#xff08;VRRM&#xff09;&#xff1a;1200V 反向电流、漏极电流&#xff08;IR&#xff09;&#xff1a;40uA 正向电压降&#xff08;VF&#xff09;&#xff1a;1…

this用法总结

文章目录1.常规下this的指向1.1 全局环境中的this1.2 上下文对象调用中的this1.3 this指向绑定事件的元素1.4 箭头函数的this指向2. 改变this指向2.1 call - Function.prototype.call( )2.1.1 call的第一个参数2.1.2 call接受多个参数2.1.3 调用对象的原生方法2.2 apply - Func…

LFMCW雷达测速基础- 多普勒频移和2DFFT

LFMCW雷达测速基础1 基本测速原理——多普勒频移1.0 写在前面1.1 多普勒效应1.2 多普勒频移疑问2 LFMCW雷达测速原理2.1 Doppler Shift 到底是调频还是调相2.2 为什么是二维FFT1 基本测速原理——多普勒频移 1.0 写在前面 振动/波在空间中传播有三个关键变量&#xff0c;分别…

iNFTnews|Web3正在重新定义粉丝的意义

数字身份正在发展&#xff0c;粉丝圈本身也在发展。Web3技术使粉丝们能够以一种更加人际化的方式与同好、媒体、内容创作者甚至他们崇拜的名人进行互动&#xff0c;粉丝和创作者都可以获得更人性化的体验。另外&#xff0c;一些激励措施还有望从根本上改变我们对名人概念本身的…

Java#14(StringJoiner)

目录 一.StringJoiner的构造方法和成员方法 StringJoiner是jdk8才出现的 作用:可以高效和方便的拼接字符串 1.StringJoiner的构造方法 2.StringJoiner的成员方法 一.StringJoiner的构造方法和成员方法 StringJoiner是jdk8才出现的 作用:可以高效和方便的拼接字符串 1.Stri…

一篇文章入门单链表+刷题实践【java实现+详细注释】

文章目录节点定义链表类获取链表长度清空链表添加节点到链表尾部根据id来删除节点根据id来查询节点修改相同id的节点信息打印链表逆序打印反转链表测试代码打印信息习题反转链表删除链表的节点删除链表的倒数第k个节点节点定义 关于节点里面所存储的信息&#xff0c;需要什么就…

洛谷 P1064 - 金明的预算方案(分组背包)

题目描述 金明今天很开心&#xff0c;家里购置的新房就要领钥匙了&#xff0c;新房里有一间金明自己专用的很宽敞的房间。更让他高兴的是&#xff0c;妈妈昨天对他说&#xff1a;“你的房间需要购买哪些物品&#xff0c;怎么布置&#xff0c;你说了算&#xff0c;只要不超过 n…

HTML学生个人网站作业设计:(宠物官网8页)——bootstarp响应式含有轮播图,响应式页面

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 公司官网网站 | 企业官网 | 酒店官网 | 等网站的设计与制 | HTML期末大学生网页设计作业&#xff0c;Web大学生网页 HTML&#xff1a;结构 CSS&#…

H7-TOOL发布V2.19,脱机烧录新增中微半导体、广芯微电子、中移芯昇以及极海和灵动新系列,增加PWM发生器等功能(2022-11-17)

H7-TOOL详细介绍&#xff1a;H7-TOOL开发工具&#xff0c;1拖4/16脱机烧录&#xff0c;高速DAPLINK&#xff0c;RTOS Trace&#xff0c;CAN/串口助手, 示波器, RTT等&#xff0c;支持WiFi&#xff0c;以太网&#xff0c;高速USB和手持 - H7-TOOL开发工具 - 硬汉嵌入式论坛 - Po…

JavaScript对象与内置对象

JavaScript对象与内置对象 文章目录JavaScript对象与内置对象1.JavaScript的基本对象1.1 创建对象1.2 对象的调用1.3 构造函数和对象1.4 变量对象属性2.JavaScript的内置对象2.1 内置对象概念3.JavaScript的Math对象3.1 Math对象概念3.2 Math绝对值和三个取整方法3.3 随机数方法…

AndroidStudio 导入项目模块失败

平台 Ubuntu 20.04AndroidStudio Android Studio Dolphin | 2021.3.1 Patch 1 Build #AI-213.7172.25.2113.9123335, built on September 30, 2022 Runtime version: 11.0.130-b1751.21-8125866 amd64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o. Linux 5.15.0-53-gen…

Structure-Aware Transformer for Graph Representation Learning

Structure-Aware Transformer for Graph Representation Learning 在图表示学习中&#xff0c;Transformer结构通过位置编码对图形结构进行编码&#xff0c;克服了GNN的几个局限性&#xff0c;但其使用位置编码生成的节点表示不一定能捕获他们之间的结构相似性&#xff0c;所以…

「Redis数据结构」哈希表(Dict)

「Redis数据结构」哈希表&#xff08;Dict&#xff09; 文章目录「Redis数据结构」哈希表&#xff08;Dict&#xff09;[toc]一、概述二、结构三、哈希冲突四、链式哈希五、rehash六、 渐进式 rehash七、总结参考我们知道Redis是一个键值型&#xff08;Key-Value Pair&#xff…

Python自制图片拼图小游戏

前言 唉&#xff0c;怎么说&#xff0c;感觉只有上班的时候摸鱼玩游戏才是最爽的 等于带薪摸鱼&#xff0c;现在不是有点流行说什么 带薪…带薪** 干嘛的 今天也是有点无聊&#xff0c;就想起之前搞了个拼图的小游戏&#xff0c;可以自己更改照片的 嘿嘿 这不刚玩了一局&am…

【Python】Pyside6简易版教程

文章目录一、安装及常见指令1.1 安装1.2 转换指令二、设计UI2.1 类别2.1.1 Spacer2.1.2 Buttons2.1.3 Input Widgets2.1.4 Display Widgets2.1.5 注意事项2.2 对象和属性2.2.1 对象2.2.2 属性2.2.2.1 属性的层级结构2.2.2.2 重要的属性2.2.2.3 插入图片三、回到Python3.1 给现有…

公众号配置调试“errMsg“:“config:fail,invalid signature

一:登陆“微信公众平台”,查看“ip白名单是否设置” ,之前是个可选项,现在是必须设置 二: 1:获取access_token微信公众平台接口调试工具https://mp.weixin.qq.com/debug/cgi-bin/apiinfo?t=index&type=%E5%9F%BA%E7%A1%80%E6%94%AF%E6%8C%81&form=%E8%8E%B…

JUC03-volatile、CAS及并发原子类

一、 Volatile Volatile可以用来修饰成员变量和静态成员变量&#xff0c;保证可见性、有序性 可见性&#xff1a;保证volatile修饰的变量每次读取都会从主从中进行读取而不是cpu缓存 有序性&#xff1a;对Volatile修饰变量进行写操作时&#xff0c;会在该操作后加上写屏障&…