Golang内存泄露场景与定位方式

news2024/10/5 14:26:22

个人博客

一、产生原因

Golang有自动垃圾回收机制,但是仍然可能会出现内存泄漏的情况。以下是Golang内存泄漏的常见可能原因:

  1. 循环引用:如果两个或多个对象相互引用,且没有其他对象引用它们,那么它们就会被垃圾回收机制误认为是仍在使用的对象,导致内存泄漏。
  2. 全局变量:在Golang中,全局变量的生命周期与程序的生命周期相同。如果一个全局变量被创建后一直存在于内存中,那么它所占用的内存就无法被回收,可能会导致内存泄漏。
  3. 未关闭的文件句柄:如果程序打开了文件句柄但没有关闭它们,那么这些文件句柄所占用的内存就无法被回收,可能会导致内存泄漏。
  4. 大量的临时对象:如果程序创建了大量的临时对象,但没有及时释放它们,那么这些对象所占用的内存就无法被回收,可能会导致内存泄漏。
  5. goroutine泄漏常见的泄露场景,例如协程发生阻塞,Go运行时并不会将处于永久阻塞状态的协程杀掉,因此永久处于阻塞状态的协程所占用的资源将永得不到释放。
  6. time.Ticker未关闭导致泄漏:当一个time.Timer值不再被使用,一段时间后它将被自动垃圾回收掉。 但对于一个不再使用的time.Ticker值,我们必须调用它的Stop方法结束它,否则它将永远不会得到回收。

二、排查方式

如果出现内存泄漏,可以使用以下方式进行分析,找出内存泄漏的原因并进行修复。

  1. 使用 Go 语言自带的 pprof 工具进行分析。pprof 可以生成程序的 CPU 和内存使用情况的报告,帮助开发者找出程序中的性能瓶颈和内存泄漏问题。可以通过在代码中添加 import _ "net/http/pprof"http.ListenAndServe("localhost:6060", nil) 来开启 pprof 工具。
  2. 使用 Golang 内置的 runtime 包进行分析。runtime 包提供了一些函数,包括 SetFinalizerReadMemStatsStack 等,可以帮助开发者了解程序的内存使用情况和内存泄漏问题。
  3. 使用第三方工具进行分析。例如,可以使用 go-torch 工具生成火焰图,帮助开发者找出程序中的性能瓶颈和内存泄漏问题。
  4. 使用 go vet 工具进行静态分析。go vet 可以检查程序中的常见错误和潜在问题,包括内存泄漏问题。
  5. 代码审查。开发者可以通过代码审查来找出程序中的潜在问题和内存泄漏问题。

三、通过 pprof 的命令排查内存泄露问题

3.1 通过 pprof 的命令行分析 heap

命令行执行命令: go tool pprof -inuse_space [<http://127.0.0.1:9999/debug/pprof/heap>](<http://spark-master.x.upyun.com/debug/pprof/heap>)

这个命令的作用是, 抓取当前程序已使用的 heap. 抓取后, 就可以进行类似于 gdb 的交互操作.

  • top 命令, 默认能列出当前程序中内存占用排名前 10 的函数. 如图. 当时进行到这一步的时候, 我就非常惊讶, 因为 time.NewTimer 居然占据了 6 个多 G 的内存.

img

  • list <函数名>, 展现函数内部的内存占用. 使用 list time.NewTimer 查看了该函数的内部, 真相大白了, 原来每次调用 NewTimer 都会创建一个 channel, 还会生成一个结构体 runtimeTimer, 应该就是这两个地方内存没有释放造成的内存泄露.

img

3.2 修改 for ... select ... time.After 造成的内存泄露

原来程序中存在如下代码:

for {
		select {

		case a := <-chanA:
			...

		case b := <-chanB:
			....

		case <-time.After(20*time.Minutes):
			return nil, errors.New("download timeout")
	}

time.After 就是封装了一层的 NewTimer, time.After 的源码:

func After(d Duration) <-chan Time {
	return NewTimer(d).C
}

修复该错误, 只调用一次 NewTimer:

downloadTimeout := time.NewTimer(20 * time.Minute)
// 添加关闭时退出操作
defer downloadTimeout.Stop()

for {
		select {

		case a := <-chanA:
			...

		case b := <-chanB:
			....

		case <-downloadTimeout.C:
			return nil, errors.New("download timeout")
	}

四、总结

通过这篇文章我们了解到Golang内存泄漏的常见可能原因有哪些:

  1. 循环引用:如果两个或多个对象相互引用,且没有其他对象引用它们,那么它们就会被垃圾回收机制误认为是仍在使用的对象,导致内存泄漏。
  2. 全局变量:在Golang中,全局变量的生命周期与程序的生命周期相同。如果一个全局变量被创建后一直存在于内存中,那么它所占用的内存就无法被回收,可能会导致内存泄漏。
  3. 未关闭的文件句柄:如果程序打开了文件句柄但没有关闭它们,那么这些文件句柄所占用的内存就无法被回收,可能会导致内存泄漏。
  4. 大量的临时对象:如果程序创建了大量的临时对象,但没有及时释放它们,那么这些对象所占用的内存就无法被回收,可能会导致内存泄漏。
  5. goroutine泄漏:比较常见的泄露场景,例如协程发生阻塞,Go运行时并不会将处于永久阻塞状态的协程杀掉,因此永久处于阻塞状态的协程所占用的资源将永得不到释放。
  6. time.Ticker未关闭导致泄漏:当一个time.Timer值不再被使用,一段时间后它将被自动垃圾回收掉。 但对于一个不再使用的time.Ticker值,我们必须调用它的Stop方法结束它,否则它将永远不会得到回收。

然后介绍了相关排查工具以及pprof如何排查内存泄露问题。

五、参考链接

1.一些可能的内存泄漏场景

2.使用 pprof 排查 Golang 内存泄露

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

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

相关文章

【计算机网络实验】BGP和OSPF协议仿真实验

实验内容  BGP和OSPF协议仿真实验 实验目的 &#xff08;1&#xff09;学习BGP协议的配置方法&#xff1b; &#xff08;2&#xff09;验证BGP协议的工作原理&#xff1b; &#xff08;3&#xff09;掌握网络自治系统的划分方法&#xff1b; &#xff08;4&#xff09;验证…

3分钟快速了解—App自动化测试是怎么实现H5测试的?

移动端 app 自动化框架很多&#xff0c;但是有一些框架因为不支持混合应用测试&#xff0c;一直没有完全流行。比较典型的是经典的 Python 框架 uiautomator2, 这个框架简单好用&#xff0c;没有 appium 那样复杂的 api 调用&#xff0c;受到不少 python 自动化工程师的青睐。 …

C++《stack和queue的一些OJ题目》

本文主要讲解C中stack和queue的一些OJ题目 文章目录 1、[最小栈](https://leetcode.cn/problems/min-stack/)2、[栈的压入、弹出序列](https://www.nowcoder.com/practice/d77d11405cc7470d82554cb392585106?tpId13&&tqId11174&rp1&ru/activity/oj&qru/ta…

路径规划算法:基于乌鸦优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于乌鸦优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于乌鸦优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化算法乌鸦…

驱动开发:内核解析PE结构节表

在笔者上一篇文章《驱动开发&#xff1a;内核解析PE结构导出表》介绍了如何解析内存导出表结构&#xff0c;本章将继续延申实现解析PE结构的PE头&#xff0c;PE节表等数据&#xff0c;总体而言内核中解析PE结构与应用层没什么不同&#xff0c;在上一篇文章中LyShark封装实现了K…

ChatGPT国内免费使用方法【国内免费使用地址】

当下人工智能技术的快速发展&#xff0c;聊天机器人成为了越来越多人们日常生活和工作中的必备工具。如何在国内免费使用ChatGPT聊天机器人&#xff0c;成为了热门话题。本文将为你详细介绍ChatGPT国内免费使用方法&#xff0c;让你轻松拥有聊天机器人助手&#xff0c;提高工作…

基于Halcon卡尺测量: Metrology批量测量矩形和圆

处理图如下: 原图如下: 主要思想: 1.准备一次性将图中12个圆和2个矩形都检测出来 2.初步确定12个圆的圆心坐标和半径,初步确定两个矩形的中心坐标,角度,长短边长 3.创建计量模型 4.定义计量模型尺寸 5.增加检测矩形和圆形的信息参数 6.应用计量模型,获取结果 7.显示…

什么是 IMU?惯性测量单元工作和应用

术语IMU代表“惯性测量单元”&#xff0c;我们用它来描述测量工具的集合。当安装在设备中时&#xff0c;这些工具可以捕获有关设备移动的数据。IMU 包含加速度计、陀螺仪和磁力计等传感器。 IMU 如何工作&#xff1f; IMU 可以测量各种因素&#xff0c;包括速度、方向、加速度、…

vue 单点登录的方法

vue 单点登录的方法 当我们在使用 vue开发项目时&#xff0c;一般都是只有一个用户帐号&#xff0c;如果要实现多个帐号的单点登录&#xff0c;可以使用 Session和 LocalStorage这两个技术。这两个技术在实现单点登录时&#xff0c;都需要有一个用户名和一个密码&#xff0c;而…

【C++】C++ 11 智能指针

【C】C 11 智能指针 文章目录 【C】C 11 智能指针1.为什么需要智能指针2. C中智能指针和指针的区别是什么&#xff1f;3. C中的智能指针有哪些&#xff1f;分别解决的问题以及区别&#xff1f;&#xff08;1&#xff09;auto_ptr&#xff08;C98的方案&#xff0c;C11已经弃用&…

JavaEE进阶(Mybatis)5/31

目录 1. SQL注入 2.concat&#xff08;&#xff09;用于like模糊查询 3.resultMap 4. 5.动态SQL 6.foreach标签 1. SQL注入 $问题会导致SQL注入 因为$是直接替换的&#xff0c;and的优先级高于or true or false #不存在SQL注入的问题&#xff0c;因为他是预编译的&…

坚持的工作好习惯

工作好习惯 目录概述需求&#xff1a; 设计思路实现思路分析1.工作好习惯的重要性2.谈下自己的工作方法2.希望有时也从别人那里也学习一下看看 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;s…

windows xp 上 Task Scheduler服务 启动后停止,导致数据库自动备份无法编辑和使用问题解决

项目中使用了mysql数据库&#xff0c;大多数人都会选择Navicat来连接数据库&#xff0c;一般会设置计划来自动备份数据库&#xff0c;但我在编辑自动备份的计划时&#xff0c;弹出task scheduler服务无法启动&#xff0c;退出回到桌面&#xff0c;启动windows的服务&#xff0c…

牛客网C++面试宝典(一)C/C++基础之语言基础

此系列为在学习牛客网C面试宝典过程中记录的笔记&#xff0c;本篇记录第一章C/C基础部分的第一节&#xff1a;语言基础。 牛客网C面试宝典链接&#xff1a;https://www.nowcoder.com/issue/tutorial?tutorialId93&uuida34ed23d58b84da3a707c70371f59c21 文章目录 1.1 简述…

Docker 数据持久化方案详解

目录 一、Docker数据持久化概述 1.1联合文件系统 1.2容器的数据卷 1.2.1 什么是数据卷 1.2.2 数据卷特点 1.2.3 Docker提供三种方式将数据从宿主机挂载到容器 二、 Docker持久化方案 2.1 查看volume 基本命令使用方法 2.2 volume持久化方案 2.2.1volume简介 2.2.2.v…

【JavaSE】Java基础语法(四十一):TCP通信程序

文章目录 1. TCP发送数据2. TCP接收数据【应用】3. TCP程序练习4. TCP程序文件上传练习【应用】 1. TCP发送数据 Java中的TCP通信 Java对基于TCP协议的的网络提供了良好的封装&#xff0c;使用Socket对象来代表两端的通信端口&#xff0c;并通过Socket产生IO流来进行网络通信。…

Android 易忽略小知识

1.设置hint的字体大小 在Android xml文件中并没有直接设置hint字体大小的属性。如果hint文字的大小不希望跟正常字体的大小一样&#xff0c;就只能通过代码的方式来进行处理。 提供两种方式&#xff1a; //设置"用户名"提示文字的大小 EditText etUserName (Ed…

教育硬件“老玩家”进入智能手机新赛道,小度胜算几何?

从5月8日有传言称“百度旗下小度将进军智能手机市场”&#xff0c;到5月17日小度官宣将推出旗下新物种产品——小度青禾学习手机&#xff0c;小度在短短10天时间成为市场关注的焦点。 而5月22日&#xff0c;其也拿出了真正的成果&#xff0c;这部专门为青少年打造的学习手机正…

MySQL——在Linux环境下安装(在线安装)

MySQL的安装&#xff08;在线安装&#xff09; mysql的安装并不是比赛的内容&#xff0c;所以我们用比较方便的在线安装的方法&#xff0c;比起安装&#xff0c;我们更要知道如何去使用&#xff1a; 首先看一下自己有没有安装MySQL的服务&#xff0c;或者自己的服务器上有没有…

application.yml中的配置怎么写

1.问题 application.yml中可以做很多组件的配置,比如redis,mongo, 但是这些的key是什么,value怎么写呢? 2.分析问题 为了搞清楚这个问题,我们需要先了解application.yml中的配置是怎么加载的,以MongoProperties配置加载为例, 在Spring Boot中,可以使用application.y…